2017-10-11 96 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