2013-12-13 100 views
2

我和一些朋友一直在編碼一個有趣的新射擊機制。爲了它的工作,我們需要朝着玩家面對的方向射擊。 Sprite被Pygame.Transform.Rotate旋轉。我們怎樣才能找到一個角度,並朝這個方向發射我們的子彈?Pygame旋轉射擊

這裏是我們的的雪碧

char_image_number = pygame.mouse.get_pressed() 

    if char_image_number == (0, 0, 0): 
      char_image = pygame.image.load(player_none).convert_alpha() 
      char_image = pygame.transform.rotate(char_image, angle) 
      screen.blit(background, (0,0)) 
      screen.blit(char_image,(540, 260)) 
      pygame.display.update() 
    elif char_image_number == (1, 0, 0): 
      print (angle) 
      char_image = pygame.image.load(player_left).convert_alpha() 
      angle+=1 
      char_image = pygame.transform.rotate(char_image, angle) 
      screen.blit(background, (0,0)) 
      screen.blit(char_image,(540, 260)) 
      pygame.display.update() 
    elif char_image_number == (0, 0, 1): 
      print (angle) 
      angle-=1 
      char_image = pygame.image.load(player_right).convert_alpha() 

      char_image=pygame.transform.rotate(char_image, angle) 
      screen.blit(background, (0,0)) 
      screen.blit(char_image,(540, 260)) 

      pygame.display.update() 

    elif char_image_number == (1, 0, 1): 
      char_image = pygame.image.load(player_both).convert_alpha() 
      char_image = pygame.transform.rotate(char_image, angle) 
      screen.blit(background, (0,0)) 
      screen.blit(char_image,(540, 260)) 
      pygame.display.update() 

我們怎樣才能拍出的球員面臨的角度旋轉代碼?

+0

使用帶'angle'和一些'speed'值三角函數得到'move_x'和'move_y' – furas

+0

你能聯繫我的教程或文檔?我熟悉矢量,但不知如何在代碼中做到這一點。 – user2975896

回答

6

下面是如何使用矢量數學來做你想要的quick'n'dirty可執行示例。

import pygame 
import base64 
import math 

# some functions for vector math 

def magnitude(v): 
    return math.sqrt(sum(v[i]*v[i] for i in range(len(v)))) 

def add(u, v): 
    return [(a+b) for (a, b) in zip(u, v)] 

def sub(u, v): 
    return [(a-b) for (a, b) in zip(u, v)] 

def dot(u, v): 
    return sum((a*b) for a, b in zip(u, v)) 

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

def length(v): 
    return math.sqrt(dot(v, v)) 

def angle(v1, v2): 
    return math.acos(dot(v1, v2)/(length(v1) * length(v2))) 

def get_image(): 
    dec = base64.b64decode(img, 'UTF-8') 
    surf = pygame.image.fromstring(dec, (32, 32), 'RGBA') 
    return surf 

def rot_center(image, angle): 
    orig_rect = image.get_rect() 
    rot_image = pygame.transform.rotate(image, angle) 
    rot_rect = orig_rect.copy() 
    rot_rect.center = rot_image.get_rect().center 
    rot_image = rot_image.subsurface(rot_rect).copy() 
    return rot_image 

class Actor(object): 

    surf = None 

    def __init__(self): 
     self.x, self.y = (0, 0) 
     self.speed, self.angle = 1.7, 0 
     self.target_vector = [0, 0] 

    @property 
    def img(self): 
     if not self.surf: 
      self.surf = get_image() 
     return self.surf 


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

    @property 
    def int_pos(self): 
     return map(int, self.pos) 

    @property 
    def center_pos(self): 
     return [a-16 for a in self.int_pos] 

    def update(self): 
     if self.speed == 0: 
      return 

     # apply speed to target_vector 
     move_vector = [c * self.speed for c in normalize(self.target_vector)] 

     # update position by adding the position vector to the movment vector 
     self.x, self.y = add(self.pos, move_vector) 

    def draw(self, s): 
     # substract 90 from angle because the image is actually 
     # an arrow already rotated by 90 degree 
     s.blit(rot_center(self.img, self.angle-90), self.center_pos) 

def fire(start, angle, target_vector): 
    act = Actor() 
    act.x, act.y = start 
    act.angle = angle 
    act.target_vector = target_vector 
    return act 

def main():  
    pygame.init() 
    quit = False 
    s = pygame.display.set_mode((300, 300)) 
    c = pygame.time.Clock() 
    player = Actor() 
    player.x, player.y, player.speed = 134, 134, 0 
    actors = [player] 

    while not quit: 

     quit = pygame.event.get(pygame.QUIT) 

     # calculate vector that represents the direction 
     target_vector = normalize(sub(pygame.mouse.get_pos(), player.pos)) 

     # rotate player to point in the right direction 
     aangle = 180 * angle(target_vector, [0, 1])/math.pi 
     if target_vector[0] < 0: 
      aangle *= -1 
     player.angle = aangle 

     if pygame.event.get(pygame.MOUSEBUTTONDOWN): 
      actors.append(fire(player.int_pos, player.angle, target_vector)) 

     pygame.event.poll() 
     for ar in actors: 
      ar.update() 
     s.fill((255, 255, 255)) 
     for ar in actors: 
      ar.draw(s) 
     pygame.display.flip() 
     c.tick(60) 

img = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFEAAADUAAAAXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAP8AAADTAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAATwAAAP8AAADTAAAAhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAADTAAAATwAAAP8AAADTAAAAdwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAP8AAADTAAAATwAAAP8AAADTAAAApwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAAnwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAAxQAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAAywAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAA3QAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhgAAAK0AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAA7wAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAA7wAAAC8AAAAAAAAAAAAAAAAAAAAAAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAADwAAAAAAAAAAAAAAAAAAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAAUgAAAFMAAAAAAAAAAAAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAGQAAAAAAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAIAAAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAAggAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAGUAAAAAAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAPoAAABUAAAAAAAAAAAAAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAAPgAAAAAAAAAAAAAAAAAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAA7wAAADAAAAAAAAAAAAAAAAAAAAAAAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIcAAACHAAAAhwAAAIYAAACtAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAPAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEsAAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADdAAAAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAAywAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAATwAAAP8AAADTAAAATwAAAP8AAADTAAAATwAAAMUAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAADTAAAATwAAAP8AAADTAAAATwAAAP8AAACgAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAP8AAADTAAAATwAAAP8AAADTAAAAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAATwAAAP8AAADTAAAATwAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAADTAAAATwAAAP8AAACFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAP8AAADTAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRAAAATgAAAF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' 

if __name__ == '__main__': 
    main() 

enter image description here

注:看來你加載您的播放器的每幀的圖像。你不應該這樣做,因爲這是很慢。只需加載一次圖像。另外,最好在代碼中只有一個點,它調用pygame.display.update(),因爲您應該確保每幀只調用一次。

+0

原諒評論,但是一個偉大而完整的答案。此外,將箭頭更改爲橙色,並且你有新的官方reddit python subs upvote gif。 – KobeJohn

0

你有度angle所以試試這個:

import math 

# angle examples 
for angle in [0, 30, 45, 60, 0+90, 30+90, 45+90, 60+90, 0+180, 30+180, 45+180, 60+180, 0+270, 30+270, 45+270, 60+270]: 

    bullet_speed = 10 

    bullet_move_x = bullet_speed * math.cos(math.radians(angle)) 
    bullet_move_y = -bullet_speed * math.sin(math.radians(angle)) 

    print angle, bullet_move_x, bullet_move_y 

現在你可以添加bullet_move_xbullet_move_y到子彈現在的位置。

爲了獲得更好的成績是子彈的位置float並轉換爲int當你的blit子彈

0

這個例子演示了載體如何可以用來控制位置,速度也開始子彈偏移。

在while循環中,我們使用math.atan2來計算目標的角度,然後用它來旋轉炮圖像並傳遞給Bullet實例。在Bullets的__init__方法中,我們通過角度旋轉偏移矢量,速度矢量和精靈圖像。要移動子彈,我們將(旋轉的)速度矢量添加到位置矢量,並將矩形位置設置爲pos矢量。矩形必須移動,因爲它保持位置並用於碰撞檢測。

import math 
import pygame as pg 
from pygame.math import Vector2 


pg.init() 
screen = pg.display.set_mode((640, 480)) 
FONT = pg.font.Font(None, 24) 
BLACK = pg.Color('black') 
BULLET_IMAGE = pg.Surface((20, 11), pg.SRCALPHA) 
pg.draw.polygon(BULLET_IMAGE, pg.Color('grey11'), [(0, 0), (20, 5), (0, 11)]) 


class Bullet(pg.sprite.Sprite): 

    def __init__(self, pos, angle): 
     super(Bullet, self).__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) 
     # Add the offset vector to the position vector. 
     self.pos = Vector2(pos) + offset # Center of the sprite. 
     # Rotate the velocity vector (9, 0) by the angle. 
     self.velocity = Vector2(9, 0).rotate(angle) 

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


def main(): 
    clock = pg.time.Clock() 
    # The cannon image and rect. 
    cannon_img = pg.Surface((60, 22), pg.SRCALPHA) 
    pg.draw.rect(cannon_img, pg.Color('grey19'), [0, 0, 35, 22]) 
    pg.draw.rect(cannon_img, pg.Color('grey19'), [35, 6, 35, 10]) 
    orig_cannon_img = cannon_img # Store orig image to preserve quality. 
    cannon = cannon_img.get_rect(center=(320, 240)) 
    angle = 0 
    # Add bullets to this group. 
    bullet_group = pg.sprite.Group() 

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

     bullet_group.update() 
     # Find angle to target (mouse pos). 
     x, y = Vector2(pg.mouse.get_pos()) - cannon.center 
     angle = math.degrees(math.atan2(y, x)) 
     # Rotate the cannon image. 
     cannon_img = pg.transform.rotate(orig_cannon_img, -angle) 
     cannon = cannon_img.get_rect(center=cannon.center) 

     # Draw 
     screen.fill(pg.Color('darkseagreen4')) 
     bullet_group.draw(screen) 
     screen.blit(cannon_img, cannon) 
     txt = FONT.render('angle {:.1f}'.format(angle), True, BLACK) 
     screen.blit(txt, (10, 10)) 
     pg.draw.line(
      screen, pg.Color(150, 60, 20), 
      cannon.center, pg.mouse.get_pos(), 2) 
     pg.display.update() 

     clock.tick(30) 

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