0
\$\begingroup\$

The following code is supposed to move a player sprite (in this case it's an 8x8 red square) to the coordinates of where the mouse is clicked. I'm able to move the square in the general direction of the click but the sprites path does not always pass precisely through the point. I'd love someone to analyse the code and show me where I'm going wrong with this.

from __future__ import division
import math
import pygame

SCREEN = pygame.display.set_mode([700, 700])
SCREEN_HEIGHT = pygame.display.Info().current_h
SCREEN_WIDTH = pygame.display.Info().current_w
pygame.display.set_caption('Window Caption')
clock = pygame.time.Clock()

class Player(pygame.sprite.Sprite):
    def __init__(self, color=(255,0,0), dims=[8,8], (originx, originy)=(100,100)):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface(dims)
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.centerx = originx
        self.rect.centery = originy
        self.speed = 10
        self.vx = 0
        self.vy = 0

    def normalize(self, (p1x, p1y), (p2x, p2y)):
        dx = p2x - p1x
        dy = p2y - p1y
        vlength = math.hypot(dx, dy) 
        vnorm = (dx / vlength, dy / vlength)
        self.vx = vnorm[0]
        self.vy = vnorm[1]

    def update(self):
        self.rect.centerx += (self.vx * self.speed)
        self.rect.centery += (self.vy * self.speed)
        print self.rect.centerx, self.rect.centery, self.vx, self.vy # verify calculations

pygame.init()

sprites = pygame.sprite.Group()
player = Player()
sprites.add(player)

looping = True
while looping:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            print "Exiting..."
            looping = False
        if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    print "Exiting..."
                    looping = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            (left_click, middle_click, right_click) = pygame.mouse.get_pressed()
            mouse_pos = pygame.mouse.get_pos()
            if left_click:
                print "left click", (player.rect.centerx, player.rect.centery), mouse_pos
                player.normalize((player.rect.centerx, player.rect.centery), mouse_pos)
            if middle_click:
                print "middle click", mouse_pos
            if right_click:
                print "right click", mouse_pos


    SCREEN.fill((0,0,0))
    sprites.update()
    sprites.draw(SCREEN)

    # Redraw everything we've asked pygame to draw
    pygame.display.flip()

    # Set frames per second to 60
    clock.tick(60)

# Quit gracefully if we exit the main loop
pygame.quit()
\$\endgroup\$
1
\$\begingroup\$

It seems your player coordinates are in integers, in python integer division gives you a float as answer which explains why your player moves mostly in the right direction, but then when you store the new position you drop the decimal point so each frame your losing a bit more precision.

You either need to store the target location instead of a vector so you can compensate for the shift each frame, or you need to store the coordinates as floats instead. Hope that helps

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.