2013-02-11 2 views
0

Я столкнулся с логической ошибкой, когда спрайт просто не перемещается независимо от ввода.
Мой код будет ниже, поэтому контекст не будет опущен, он довольно короткий.
Есть ли лучший способ переместить спрайт отдельно от blit?
Я видел где-то вещи об обновлении спрайта или некоторых таких, совершенно по-другому, чтобы просто блеснуть.pygame sprite not moving

import pygame 
pygame.init() 
import random 
import math 

screen=pygame.display.set_mode([700,400]) 
black = ( 0, 0, 0) 
white = (255, 255, 255) 
red  = (255, 0, 0) 
player_x=350 
player_y=200 
player_x_vel=0 
player_y_vel=0 
rot_player=pygame.image 

pi=math.pi 

class Player(pygame.sprite.Sprite): 
    def __init__(self): 
     global player 
     pygame.sprite.Sprite.__init__(self) 
     self.pos=(350,200) 
     self.image=pygame.image.load("arrowtest.png").convert() 
     self.rect=self.image.get_rect() 
     screen=pygame.display.get_surface() 
     self.area=screen.get_rect() 
     self.speed=10 
     self.state="still" 
     self.reinit()  

    def reinit(self): 
     self.state="still" 
     self.movepos=[0,0] 

    def update(self): 
     newpos=self.rect.move(self.movepos) 
     if self.area.contains(newpos): 
      self.rect=newpos 
     pygame.event.pump() 

    def moveup(self): 
     self.movepos[1]-=(self.speed) 
     self.state="moveup" 
    def movedown(self): 
     self.movepos[1]+=(self.speed) 
     self.state="movedown" 
    def moveleft(self): 
     self.movepos[0]-=(self.speed) 
     self.state="moveleft" 
    def moveright(self): 
     self.movepos[0]+=(self.speed) 
     self.state="moveright" 
    def moveupright(self): 
     self.movepos[1]-=(self.speed) 
     self.movepos[0]+=(self.speed) 
    def moveupleft(self): 
     self.movepos[1]-=(self.speed) 
     self.movepos[0]-=(self.speed) 
    def movedownright(self): 
     self.movepos[1]+=(self.speed) 
     self.movepos[0]+=(self.speed) 
    def movedownleft(self): 
     self.movepos[1]+=(self.speed) 
     self.movepos[0]-=(self.speed) 

    def angleplayer(self): 
     mouse_pos=pygame.mouse.get_pos() 
     dx=mouse_pos[0]-player_x 
     dy=mouse_pos[1]-player_y 
     rads=math.atan2(-dy, dx) 
     rads %= 2*pi 
     angle = math.degrees(rads) 
     print angle 
     rot_player.image=pygame.transform.rotate(player.image, angle-90) 

done=False 
clock=pygame.time.Clock() 

while done==False: 

    player = Player() 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      done=True 
     if event.type == pygame.MOUSEBUTTONDOWN: 
      fired_pos=pygame.mouse.get_pos() 
      fired=True 
     if event.type == pygame.KEYDOWN: 
      player.angleplayer() 
      if event.key == pygame.K_w: 
       player.moveup() 
      if event.key == pygame.K_s: 
       player.movedown() 
      if event.key == pygame.K_a: 
       player.moveleft() 
      if event.key == pygame.K_d: 
       player.moveright() 

      print "co ords", player_x,player_y 
      print "x vel", player_x_vel 
      print "y vel", player_y_vel 

     if event.type == pygame.KEYUP: 
      player.movepos=[0,0] 
      player.state="still" 
      player.angleplayer() 

     screen.fill(white) 
     screen.blit(player.image, player.pos) 

    clock.tick(20) 
    pygame.display.flip() 

pygame.quit() 

Заранее спасибо

ответ

5

Прежде всего, вы создаете новый игрок каждую итерацию основного цикла:

... 
while done == False: 
    player = Player() 
    ... 

Вы хотите создать плеер раз, поэтому переместите создание вне цикла:

... 
player = Player() 
while not done: 
    ... 

Во-вторых: Для того, чтобы получить позицию игрока, вы используете player.pos:

... 
screen.blit(player.image, player.pos) 
... 

, но вы никогда не обновлять player.pos (это всегда (350,200)), вы меняете только self.rect:

def update(self): 
    newpos=self.rect.move(self.movepos) 
    if self.area.contains(newpos): 
     self.rect=newpos 
    pygame.event.pump() 

либо используйте player.rect для получения позиции игрока или обновите player.pos соответственно:

def update(self): 
    newpos=self.rect.move(self.movepos) 
    if self.area.contains(newpos): 
     self.rect = newpos 
     self.pos = self.rect.topleft 
     # don't call pygame.event.pump() here. Doesn't make any sense :-) 

В-третьих, обновить позицию игрока в функции update, но вы никогда не называли. Назовите это перед нанесением игрока:

... 
while not done: 
    ... 
    player.update() 
    screen.fill(white) 
    screen.blit(player.image, player.pos) 
... 

Вы можете упростить код МНОГО, установив movepos непосредственно и удаление move... функций.

рабочий пример:

import pygame 
pygame.init() 
colors = pygame.color.THECOLORS 
screen = pygame.display.set_mode([700,400]) 

class Player(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.surface.Surface((32,32)) 
     self.image.fill(colors['green']) 
     self.rect = self.image.get_rect().move(350, 200) 
     self.speed = 4 

    def update(self): 
     dx, dy = self.movepos[0] * self.speed, self.movepos[1] * self.speed 
     self.rect = self.rect.move(dx, dy) 


done=False 
clock = pygame.time.Clock() 
player = Player() 

while not done: 

    if pygame.event.get(pygame.QUIT): 
     break 

    pressed = pygame.key.get_pressed() 
    l, r, u, d = [pressed[k] for k in pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s] 
    player.movepos = -l + r, -u + d 
    player.update() 

    screen.fill(colors['white']) 
    screen.blit(player.image, player.rect.topleft) 
    pygame.display.flip() 

    clock.tick(60) 
+1

Также обратите внимание, что вы заполняете экран и нарисовываете плеер один раз для каждого происходящего события.Это приведет к тому, что ваша программа не будет работать бесперебойно. Просто вызовите функции рисования после каждого цикла. – sloth

+1

Это помогло кучам, спасибо. Честно говоря, я даже не знал, что сделал насос, я просто следил за учебником. Я не уверен, стоит ли начинать задавать новый вопрос, но как я могу сделать движение плавным? Сейчас он перемещается только один раз, когда я нажимаю клавиши. – Alex

+0

Я добавил пример моего ответа. Ключ состоит в том, чтобы использовать «pygame.key.get_pressed», чтобы проверить, нажат ли ключ, а не проверять событие «KEYDOWN». – sloth

0

У вас есть много функций двигаться. Попробуйте объединить их в простой класс две функции как в этом примере:

class Puck(pygame.sprite.Sprite): 
    def __init__(self, image_file, speed, location): 
     pygame.sprite.Sprite.__init__(self) #call Sprite initializer 
     self.image = pygame.image.load(image_file) 
     self.rect = self.image.get_rect() 
     self.rect.left, self.rect.top = location 

Два главных контроллеров являются self.rect.left и self.rect.top. Изменяя их значения, вы можете перемещать спрайты, как в этом примере.

#Name of varible# = Puck('#Image File#', [#value of self.rect.left#, value of self.rect.top] 

Затем вы можете использовать события, чтобы изменить их, как:

for event in pygame.event.get(): 
    if event.type==pygame.QUIT: 
     pygame.quit() 
     exit(0) 
    elif event.type == pygame.KEYDOWN: 
     if event.key == K_UP: 
      random.rect.top =random.rect.top - 75 
     elif event.key == K_LEFT: 
      random.rect.left = random.rect.left - 75 
     elif event.key == K_DOWN: 
      random.rect.top = random.rect.top + 75 
     elif event.key == K_RIGHT: 
      randoml.rect.left = randoml.rect.left + 75 
     elif event.key == K_w: 
      random.rect.top = random.rect.top - 50 
     elif event.key == K_a: 
      random.rect.left = random.rect.left - 50 
     elif event.key == K_s: 
      random.rect.top = random.rect.top + 50 
     elif event.key == K_d: 
      random.rect.left = random.rect.left + 50 

Это должно быть в состоянии переместить спрайт.