2017-10-11 95 views
2

我在移动精灵时遇到了问题。我可以在x轴和y轴上移动它们,完全没有问题。我无法弄清楚的是,我怎样才能将它们按照一定的角度移动。我的意思是,我试图创建一个函数,其中包括我尝试移动的对象,速度和方向(应以度数衡量)。喜欢的东西:如何在Pygame中根据角度移动精灵

MovingObject(obj,speed,direction) #this is the function I'm trying to define 

它更像一个“产卵功能”,而不仅仅是运动......举个例子,我想创建一个类“子弹”的目标,并希望它按照一定的方向(不同于x和y轴,当然) 其实我不清楚如何做这样的事情,我想要一些建议,以实现如此。 感谢您阅读本文!

编辑: @Joran比斯利我试图做你告诉我......但我想我没有错......

import pygame, math, time 
screen=pygame.display.set_mode((320,240)) 
clock=pygame.time.Clock() 
pygame.init() 
def calculate_new_xy(old_xy,speed,angle_in_radians): 
    new_x = old_xy.x + (speed*math.cos(angle_in_radians)) 
    new_y = old_xy.y + (speed*math.sin(angle_in_radians)) 
    return new_x, new_y 
class Bullet(pygame.sprite.Sprite): 
    def __init__(self,x,y,direction,speed):   
      pygame.sprite.Sprite.__init__(self) 
      self.image=pygame.Surface((16, 16)) 
      self.image.fill((255,0,0)) 
      self.rect=self.image.get_rect() 
      self.rect.center=(x,y) 
      self.direction=math.radians(direction) 
      self.speed=speed 
    def update(self): 
      self.rect.center=calculate_new_xy(self.rect,self.speed,self.direction) 
spr=pygame.sprite.Group() 
bullet=Bullet(160,120,45,1); spr.add(bullet) 
play=True 
while play: 
    clock.tick(60) 
    for ev in pygame.event.get(): 
     if ev.type == pygame.QUIT: 
      play=False 
    screen.fill((0,0,0)) 
    spr.update() 
    spr.draw(screen) 
    pygame.display.flip() 
pygame.quit() 

对象移动,但...不是在指定的方向...

+0

将其更改为'calculate_new_xy(self.rect.center ,. ..)'然后访问x为[0],y为[1],并将您的速度设置为2 ...它应该工作 –

回答

0

我推荐使用矢量。要获得速度,请将起始方向矢量Vector2(1, 0)旋转角度并将其乘以所需的速度。然后,将该速度矢量添加到方法update中的位置矢量中,并更新rect位置以移动精灵。 (按“a”或“d”转动,鼠标1或空间来拍摄。)

import pygame as pg 
from pygame.math import Vector2 


pg.init() 
screen = pg.display.set_mode((640, 480)) 
screen_rect = screen.get_rect() 

FONT = pg.font.Font(None, 24) 
BULLET_IMAGE = pg.Surface((20, 11), pg.SRCALPHA) 
pg.draw.polygon(BULLET_IMAGE, pg.Color('aquamarine1'), 
       [(0, 0), (20, 5), (0, 11)]) 


class Bullet(pg.sprite.Sprite): 

    def __init__(self, pos, angle): 
     super().__init__() 
     self.image = pg.transform.rotate(BULLET_IMAGE, -angle) 
     self.rect = self.image.get_rect(center=pos) 
     # To apply an offset to the start position, 
     # create another vector and rotate it as well. 
     offset = Vector2(40, 0).rotate(angle) 
     # Then add the offset vector to the position vector. 
     self.pos = Vector2(pos) + offset # Center of the sprite. 
     # Rotate the direction vector (1, 0) by the angle. 
     # Multiply by desired speed. 
     self.velocity = Vector2(1, 0).rotate(angle) * 9 

    def update(self): 
     self.pos += self.velocity # Add velocity to pos to move the sprite. 
     self.rect.center = self.pos # Update rect coords. 

     if not screen_rect.contains(self.rect): 
      self.kill() 


def main(): 
    clock = pg.time.Clock() 
    cannon_img = pg.Surface((40, 20), pg.SRCALPHA) 
    cannon_img.fill(pg.Color('aquamarine3')) 
    cannon = cannon_img.get_rect(center=(320, 240)) 
    angle = 0 
    bullet_group = pg.sprite.Group() # Add bullets to this group. 

    while True: 
     for event in pg.event.get(): 
      if event.type == pg.QUIT: 
       return 
      elif event.type == pg.MOUSEBUTTONDOWN: 
       # Left button fires a bullet from center with 
       # current angle. Add the bullet to the bullet_group. 
       if event.button == 1: 
        bullet_group.add(Bullet(cannon.center, angle)) 

     keys = pg.key.get_pressed() 
     if keys[pg.K_a]: 
      angle -= 3 
     elif keys[pg.K_d]: 
      angle += 3 
     if keys[pg.K_SPACE]: 
      bullet_group.add(Bullet(cannon.center, angle)) 

     # Rotate the cannon image. 
     rotated_cannon_img = pg.transform.rotate(cannon_img, -angle) 
     cannon = rotated_cannon_img.get_rect(center=cannon.center) 

     bullet_group.update() 

     # Draw 
     screen.fill((30, 40, 50)) 
     screen.blit(rotated_cannon_img, cannon) 
     bullet_group.draw(screen) 
     txt = FONT.render('angle {:.1f}'.format(angle), True, (150, 150, 170)) 
     screen.blit(txt, (10, 10)) 
     pg.display.update() 

     clock.tick(30) 

if __name__ == '__main__': 
    main() 
    pg.quit() 

关于在您的添加实施例的代码,最简单的解决方案是计算speed_xspeed_y(”速度“将更适合)在__init__方法中,然后只更新update方法中的self.rect.xy属性。

import math 
import pygame 


pygame.init() 

screen = pygame.display.set_mode((640, 480)) 
clock = pygame.time.Clock() 

BULLET_IMAGE = pygame.Surface((20, 11), pygame.SRCALPHA) 
pygame.draw.polygon(BULLET_IMAGE, pygame.Color('aquamarine1'), 
       [(0, 0), (20, 5), (0, 11)]) 


class Bullet(pygame.sprite.Sprite): 

    def __init__(self, x, y, angle, speed): 
     pygame.sprite.Sprite.__init__(self) 
     # Rotate the bullet image (negative angle because y-axis is flipped). 
     self.image = pygame.transform.rotate(BULLET_IMAGE, -angle) 
     self.rect = self.image.get_rect(center=(x, y)) 
     angle = math.radians(angle) 
     self.speed_x = speed * math.cos(angle) 
     self.speed_y = speed * math.sin(angle) 

    def update(self): 
     self.rect.x += self.speed_x 
     self.rect.y += self.speed_y 

spr = pygame.sprite.Group() 
bullet = Bullet(10, 10, 60, 3) 
bullet2 = Bullet(10, 10, 30, 3) 
spr.add(bullet, bullet2) 

play = True 
while play: 
    clock.tick(60) 
    for ev in pygame.event.get(): 
     if ev.type == pygame.QUIT: 
      play = False 
    screen.fill((30,30,40)) 
    spr.update() 
    spr.draw(screen) 
    pygame.display.flip() 

pygame.quit() 

有一个问题,因为pygame.Rect s只能有整数作为x和y的属性,所以运动不会是100%正确的。为了解决这个问题,需要将精灵的COORDS /位置存储在不同的变量,速度加入到他们事后更新RECT:

# In `__init__`. 
    self.pos_x = x 
    self.pos_y = y 

def update(self): 
    self.pos_x += self.speed_x 
    self.pos_y += self.speed_y 
    self.rect.center = (self.pos_x, self.pos_y) 
+0

我真的很感谢你的回答......但是我不敢说......这有点令人困惑......另外......我不知道这是我想要的...... 也许我应该有这样的说法:我想定义一个函数,它创建一个在特定方向上移动的“移动对象”...也许...如果你向我解释... ...以更简单的方式......单词... ? (我很抱歉,这对我来说有点难以理解......) – DarkBlood202

+0

你知道载体如何工作吗? – skrx

+0

我想......我不 – DarkBlood202

2

你只需要一点点基本TRIG

def calculat_new_xy(old_xy,speed,angle_in_radians): 
    new_x = old_xy.X + (speed*math.cos(angle_in_radians)) 
    new_y = old_xy.Y + (speed*math.sin(angle_in_radians)) 
    return new_x, new_y 

---编辑---

这里是你的代码从上面编辑到工作

import pygame, math, time 
screen=pygame.display.set_mode((320,240)) 
clock=pygame.time.Clock() 
pygame.init() 
def calculate_new_xy(old_xy,speed,angle_in_radians): 
    new_x = old_xy[0] + (speed*math.cos(angle_in_radians)) 
    new_y = old_xy[1] + (speed*math.sin(angle_in_radians)) 
    return new_x, new_y 
class Bullet(pygame.sprite.Sprite): 
    def __init__(self,x,y,direction,speed): 
      pygame.sprite.Sprite.__init__(self) 
      self.image=pygame.Surface((16, 16)) 
      self.image.fill((255,0,0)) 
      self.rect=self.image.get_rect() 
      self.rect.center=(x,y) 
      self.direction=math.radians(direction) 
      self.speed=speed 
    def update(self): 
      self.rect.center=calculate_new_xy(self.rect.center,self.speed,self.direction) 
spr=pygame.sprite.Group() 
bullet=Bullet(160,120,45,2); spr.add(bullet) 
play=True 
while play: 
    clock.tick(60) 
    for ev in pygame.event.get(): 
     if ev.type == pygame.QUIT: 
      play=False 
    screen.fill((0,0,0)) 
    spr.update() 
    spr.draw(screen) 
    pygame.display.flip() 
pygame.quit() 
+0

并且...它没有工作。无论如何谢谢你...可能我只是误解了我应该使用它的方式...... – DarkBlood202

+0

哦,它也可以!谢谢你的帮助! – DarkBlood202