2013-04-29 5 views
1

저는 파이 게임에서 약간의 해적 게임을 쓰고 있습니다. Empires Total War에서 바다 전투를했다면, 내가 얻고 싶은 것을 생각할 수 있습니다.마우스 클릭 위치로 단계별로 스프라이트 이동

우주선의 스프라이트 위치는 (x1|y1)입니다. 이제 플레이어는 화면상의 (x2|y2) 위치를 클릭합니다. 스프라이트는 이제 새로운 위치로 (x2|y2)을 가져 가기로되어 있습니다. 즉각적으로 거기를 비추는 것이 아니라 단계적으로 진행하는 것입니다.

이 나는 ​​사각형 (x1|y1), (x1|y2), (x2|y2), (x2|y1)의 대각선 함께 할 수있는 뭔가가 있지만 난 그냥, 특히하지에 상관없이 각 대각선이 같은 속도를 유지하지로, 그것을 알아낼 수 있다고 생각 xy 중 하나 (선박 또는 클릭)의 값이 다른 것보다 크거나 작을 수도 있습니다.

def update(self, new_x, new_y, speed, screen, clicked): 

    if clicked: 
     self.xshift = (self.x - new_x) 
     self.yshift = ((self.y - new_y)/(self.x - new_x)) 

    if self.x > (new_x + 10): 
     self.x -= 1 
     self.y -= self.yshift 
    elif self.x > new_x and self.x < (new_x + 10): 
     self.x -= 1 
     self.y -= self.yshift 
    elif self.x < (new_x - 10): 
     self.x += 1 
     self.y += self.yshift 
    elif self.x < new_x and self.x < (new_x - 10): 
     self.x += 1 
     self.y += self.yshift 
    else: 
     self.x += 0 
     self.y += 0 

    screen.set_at((self.x, self.y), (255, 0, 255)) 

은 "배는"여기에 단지 분홍색 픽셀입니다 :

이 작은 조각은 작동 기능을 쓸 수있는 내 마지막 시도입니다. 내 클릭이 화면에 표시되는 반응은 대략 내 클릭으로 이동하지만 클릭 한 지점의 임의의 거리에서 멈추는 것입니다.

변수는 : 마우스 클릭
speed = 일정한 속도

new_x

, new_y = 위치 선종
clicked에 따라 = xshift 자기의 yshift가되도록 상기 MOUSEBUTTONDOWN 이벤트에 의해 true 세트 플레이어가 클릭 할 때만 정의되고 각 프레임은 다시 정의되지 않습니다.

우주선을 현재 위치에서 플레이어가 클릭 한 지점까지 부드럽게 움직이게하려면 어떻게해야합니까?

답변

0

현재 위치가 pos이고 플레이어가 클릭 한 포인트가 target_pos 인 경우 postarget_pos 사이의 벡터를 가져옵니다.

pos에서 target_pos까지 얻는 방법을 알았지 만 일정한 속도로 이동하려면 (한 번에 전체 거리가 아닌) 벡터를 표준화하고 스칼라 곱셈을 사용하여 속도 상수를 적용해야합니다.

그게 전부입니다.


전체 예제 :(관련 코드는 Ship.update 방법입니다)

import pygame 
import math 

# some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637 
def magnitude(v): 
    return math.sqrt(sum(v[i]*v[i] for i in range(len(v)))) 

def add(u, v): 
    return [ u[i]+v[i] for i in range(len(u)) ] 

def sub(u, v): 
    return [ u[i]-v[i] for i in range(len(u)) ]  

def dot(u, v): 
    return sum(u[i]*v[i] for i in range(len(u))) 

def normalize(v): 
    vmag = magnitude(v) 
    return [ v[i]/vmag for i in range(len(v)) ] 

class Ship(object): 
    def __init__(self): 
     self.x, self.y = (0, 0) 
     self.set_target((0, 0)) 
     self.speed = 0.7 

    @property 
    def pos(self): 
     return self.x, self.y 

    # for drawing, we need the position as tuple of ints 
    # so lets create a helper property 
    @property 
    def int_pos(self): 
     return map(int, self.pos) 

    @property 
    def target(self): 
     return self.t_x, self.t_y 

    @property 
    def int_target(self): 
     return map(int, self.target) 

    def set_target(self, pos): 
     self.t_x, self.t_y = pos 

    def update(self): 
     # if we won't move, don't calculate new vectors 
     if self.int_pos == self.int_target: 
      return 

     target_vector = sub(self.target, self.pos) 

     # a threshold to stop moving if the distance is to small. 
     # it prevents a 'flickering' between two points 
     if magnitude(target_vector) < 2: 
      return 

     # apply the ship's speed to the vector 
     move_vector = [c * self.speed for c in normalize(target_vector)] 

     # update position 
     self.x, self.y = add(self.pos, move_vector) 

    def draw(self, s): 
     pygame.draw.circle(s, (255, 0 ,0), self.int_pos, 2) 

pygame.init() 
quit = False 
s = pygame.display.set_mode((300, 300)) 
c = pygame.time.Clock() 
ship = Ship() 

while not quit: 
    quit = pygame.event.get(pygame.QUIT) 
    if pygame.event.get(pygame.MOUSEBUTTONDOWN): 
     ship.set_target(pygame.mouse.get_pos()) 
    pygame.event.poll() 
    ship.update() 
    s.fill((0, 0, 255)) 
    ship.draw(s) 
    pygame.display.flip() 
    c.tick(60) 
+0

내 동생의 이름도 (그러나 "C"를 "K"와) "도미니크"입니다 : D 대단히 감사합니다! 내 생각에, 나는 내 문제를 알아 냈다. :) 대답은 분명했다. –

+0

완료 :) 한 가지 더 : 문서에서 @property를 어디에서 찾을 수 있습니까? 파이 게임 특유입니까? 파이썬의 문서에서 단어를 찾을 수 없습니까 (아니면 그냥 간과 했습니까?) –

+0

@patrichartmann http://docs.python.org/2/library/functions.html#property – sloth

관련 문제