1

I am once again asking the community. I spend hours on this already. I did endless google searches and videos. Please moderators, don't close this question, because the posts with similar questions are not helping.

import pygame
import math
pygame.init()
win_height=400
win_width=800
win=pygame.display.set_mode((0,0),pygame.FULLSCREEN)
pygame.display.set_caption("game")

white=(255,255,255)
black=(0,0,0)
blue=(0,0,255)
green=(255,169,69)
red=(255,0,0)

base_pos=(20,680)

clock=pygame.time.Clock()
arrows=pygame.sprite.Group()

class Arrow(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((5,5))
        self.image.fill(white)
        self.rect=self.image.get_rect()
        self.rect.center=base_pos
        self.speed=2
        self.angle=math.atan2(mouse_pos[1]-base_pos[1],mouse_pos[0]-base_pos[0])

        #I did learn the formula for finding the angle between two points in radians here, but I can't 
        move it properly

        self.xv=math.cos(self.angle)*self.speed
        self.yv=math.sin(self.angle)*self.speed
    def update(self):
        self.rect.x+=self.xv
        self.rect.y+=self.yv

timer=0
while True:
    timer+=0.017
    pygame.event.get()
    mouse_pos=pygame.mouse.get_pos()
    mouse_down=pygame.mouse.get_pressed()
    keys=pygame.key.get_pressed()
    clock.tick(60)

    if keys[pygame.K_ESCAPE]:
        pygame.quit()

    win.fill(blue)
    pygame.draw.rect(win,green,(0,700,2000,2000))
    pygame.draw.rect(win,red,(20,680,20,20))
    if timer>0.5:
        arrow=Arrow()
        arrows.add(arrow)
    arrows.update()
    arrows.draw(win)
    pygame.display.update()

I suspect the culprit is the part where I calculate xv and yv. I did this before, and it somehow worked, but it was really weird. I'm getting so many different answers right now with the google searches and my own projects, so I really need someone to explain what the actually correct way is.

ree
  • 127
  • 1
  • 7

1 Answers1

1

pygame.Rect can just store integral coordinates:

The coordinates for Rect objects are all integers.

In the following code

self.rect.x += self.xv
self.rect.y += self.yv

the fractional component of self.xv and self.yv is lost because self.rect.x and self.rect.y can only store integral values.

You have to do the calculations with floating point accuracy. Add an x ​​and y attribute to the class. Increment the attributes in update and synchronize the rect attribute:

class Arrow(pygame.sprite.Sprite):
    def __init__(self):
        # [...]

        self.xv = math.cos(self.angle)*self.speed
        self.yv = math.sin(self.angle)*self.speed
        self.x = base_pos[0]
        self.y = base_pos[1]
   
     def update(self):
        self.x += self.xv
        self.y += self.yv
        self.rect.center = round(self.x), round(self.y)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174