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()