2017-10-17 17 views
1

Je fais un clone d'astéroïdes, et j'ai de la difficulté à déterminer où stocker l'angle du mouvement du sprite du joueur et comment avoir accès à la balle (si cela a du sens). À l'heure actuelle, je pense que la rotation de mon vaisseau est stockée dans la variable angle_speed, que j'utilise pour produire les coordonnées de la balle dest_x et dest_y (destination x et y). Cependant, la balle continue de tirer sur (0, 0). Quelqu'un peut-il aider?Pygame - Comment tirer en direction du sprite du joueur?

try: 
    import sys 
    import math 
    import os 
    import getopt 
    import pygame 
    from pygame.locals import * 
    from pygame.math import Vector2 
except ImportError, err: 
    print "couldn't load module. %s" % (err) 
    sys.exit(2) 

# these are warnings if font or sound modules are not available. 
if not pygame.font: print 'Warning, fonts disabled' 
if not pygame.mixer: print 'Warning, sound disabled' 

SCREEN_WIDTH = 800 
SCREEN_HEIGHT = 600 

BLACK = (0, 0, 0) 
WHITE = (255, 255, 255) 
RED = (255, 0, 0) 
BLUE = (0, 0, 255) 


class Player(pygame.sprite.Sprite): 
    """moves ship on screen""" 
    def __init__(self, pos=(420,420)): 
     super(Player, self).__init__() # call Sprite initializer 
     self.image = pygame.Surface([20, 20]) 
     self.image.fill(RED) 
     self.original_image = self.image 
     self.rect = self.image.get_rect(center=pos) 
     self.position = Vector2(pos) 
     self.direction = Vector2(0,1) 
     self.speed = 0 
     self.angle_speed = 0 
     self.angle = 0 


    def update(self): 
     if self.angle_speed != 0: 
      # Rotate the direction vector and then the image 
      self.direction.rotate_ip(self.angle_speed) 
      self.angle += self.angle_speed 
      self.image = pygame.transform.rotate(self.original_image, -self.angle) 
      self.rect = self.image.get_rect(midtop=self.rect.midtop) 
     # Update the position vector and the rect. 
     self.position += self.direction * self.speed 
     self.rect.center = self.position 
class Bullet(pygame.sprite.Sprite): 
    """ This class represents the bullet. """ 

    def __init__(self, start_x, start_y, dest_x, dest_y): 
     """ Constructor. 
     It takes in the starting x and y location. 
     It also takes in the destination x and y position. 
     """ 

     # Call the parent class (Sprite) constructor 
     super(Bullet, self).__init__() 

     # Set up the image for the bullet 
     self.image = pygame.Surface([4, 10]) 
     self.image.fill(BLACK) 

     self.rect = self.image.get_rect() 

     # Move the bullet to our starting location 
     self.rect.x = start_x 
     self.rect.y = start_y 

     # Because rect.x and rect.y are automatically converted 
     # to integers, we need to create different variables that 
     # store the location as floating point numbers. Integers 
     # are not accurate enough for aiming. 
     self.floating_point_x = start_x 
     self.floating_point_y = start_y 

     # Calculation the angle in radians between the start points 
     # and end points. This is the angle the bullet will travel. 
     x_diff = dest_x - start_x 
     y_diff = dest_y - start_y 
     angle = math.atan2(y_diff, x_diff); 

     # Taking into account the angle, calculate our change_x 
     # and change_y. Velocity is how fast the bullet travels. 
     velocity = 11 
     self.change_x = math.cos(angle) * velocity 
     self.change_y = math.sin(angle) * velocity 

    def update(self): 
     """ Move the bullet. """ 

     # The floating point x and y hold our more accurate location. 
     self.floating_point_y += self.change_y 
     self.floating_point_x += self.change_x 

     # The rect.x and rect.y are converted to integers. 
     self.rect.y = int(self.floating_point_y) 
     self.rect.x = int(self.floating_point_x) 

     # If the bullet flies of the screen, get rid of it. 
     if self.rect.x < 0 or self.rect.x > SCREEN_WIDTH or self.rect.y < 0 or self.rect.y > SCREEN_HEIGHT: 
      self.kill() 

def main(): 


    pygame.init() 
    pygame.mixer.init() 
    pygame.key.set_repeat(500,30) 


    screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT]) 
    pygame.display.set_caption('Asteroids') 

    screen_rect = screen.get_rect() 

    all_sprites_list = pygame.sprite.Group() 
    # List of each bullet 
    bullet_list = pygame.sprite.Group() 
    bullets = [] 

    player = Player() 
    all_sprites_list.add(player) 

    MAXSPEED = 15 
    MINSPEED = -5 

    clock = pygame.time.Clock() 

    done = False 
    while not done: 
     clock.tick(60) 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       done = True 
      elif event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_UP and player.speed > MINSPEED: 
        player.speed -= 3 
       if event.key == pygame.K_DOWN and player.speed < MAXSPEED: 
        player.speed += 3 
       if event.key == pygame.K_LEFT: 
        player.angle_speed = -3 
       if event.key == pygame.K_RIGHT: 
        player.angle_speed = 3 
       if event.key == pygame.K_SPACE: 

        dest_x = math.sin(player.angle_speed) 
        dest_y = math.cos(player.angle_speed) 
        # Create the bullet based on where we are, and where we want to go. 
        bullet = Bullet(player.rect.x, player.rect.y, dest_x, dest_y) 

        # Add the bullet to the lists 
        all_sprites_list.add(bullet) 
        bullet_list.add(bullet) 
      elif event.type == pygame.KEYUP: 
       if event.key == pygame.K_LEFT: 
        player.angle_speed = 0 
       elif event.key == pygame.K_RIGHT: 
        player.angle_speed = 0 

     all_sprites_list.update() 
     player.rect.clamp_ip(screen_rect) 
     screen.fill((255, 255, 255)) 
     # screen.blit(player.image, player.rect) 
     all_sprites_list.draw(screen) 
     pygame.display.flip() 

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

Répondre

1

L'angle est stocké dans l'attribut de l'image-objet self.angleplayer. Le angle_speed est juste la vitesse avec laquelle il tourne.

Il n'est pas nécessaire de calculer l'angle et la vélocité des puces, puisque vous pouvez simplement passer les angle et direction de l'image-objet du joueur.

import math 
import pygame 
from pygame.math import Vector2 


SCREEN_WIDTH = 800 
SCREEN_HEIGHT = 600 

BLACK = (0, 0, 0) 
WHITE = (255, 255, 255) 
RED = (255, 0, 0) 


class Player(pygame.sprite.Sprite): 

    def __init__(self, pos=(420, 420)): 
     super(Player, self).__init__() 
     self.image = pygame.Surface([20, 40], pygame.SRCALPHA) 
     self.image.fill(RED) 
     self.original_image = self.image 
     self.rect = self.image.get_rect(center=pos) 
     self.position = Vector2(pos) 
     # The vector points upwards. 
     self.direction = Vector2(0, -1) 
     self.speed = 0 
     self.angle_speed = 0 
     self.angle = 0 

    def update(self): 
     if self.angle_speed != 0: 
      # Rotate the direction vector and then the image 
      self.direction.rotate_ip(self.angle_speed) 
      self.angle += self.angle_speed 
      self.image = pygame.transform.rotate(self.original_image, -self.angle) 
      self.rect = self.image.get_rect(midtop=self.rect.midtop) 
     # Update the position vector and the rect. 
     self.position += self.direction * self.speed 
     self.rect.center = self.position 


class Bullet(pygame.sprite.Sprite): 
    """ This class represents the bullet. """ 

    def __init__(self, pos, direction, angle): 
     """Take the pos, direction and angle of the player.""" 
     super(Bullet, self).__init__() 
     self.image = pygame.Surface([4, 10], pygame.SRCALPHA) 
     self.image.fill(BLACK) 
     # Rotate the image by the player.angle (negative since y-axis is flipped). 
     self.image = pygame.transform.rotozoom(self.image, -angle, 1) 
     # Pass the center of the player as the center of the bullet.rect. 
     self.rect = self.image.get_rect(center=pos) 
     self.position = Vector2(pos) # The position vector. 
     self.velocity = direction * 11 # Multiply by desired speed. 

    def update(self): 
     """Move the bullet.""" 
     self.position += self.velocity # Update the position vector. 
     self.rect.center = self.position # And the rect. 

     if self.rect.x < 0 or self.rect.x > SCREEN_WIDTH or self.rect.y < 0 or self.rect.y > SCREEN_HEIGHT: 
      self.kill() 


def main(): 
    pygame.init() 
    pygame.key.set_repeat(500,30) 

    screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT]) 
    screen_rect = screen.get_rect() 

    all_sprites_list = pygame.sprite.Group() 
    bullet_group = pygame.sprite.Group() # "group" not "list". 

    player = Player() 
    all_sprites_list.add(player) 

    MAXSPEED = 15 
    MINSPEED = -5 

    clock = pygame.time.Clock() 

    done = False 
    while not done: 
     clock.tick(60) 

     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       done = True 
      elif event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_UP and player.speed > MINSPEED: 
        player.speed += 3 
       if event.key == pygame.K_DOWN and player.speed < MAXSPEED: 
        player.speed -= 3 
       if event.key == pygame.K_LEFT: 
        player.angle_speed = -3 
       if event.key == pygame.K_RIGHT: 
        player.angle_speed = 3 
       if event.key == pygame.K_SPACE: 
        # Just pass the rect.center, direction vector and angle. 
        bullet = Bullet(
         player.rect.center, player.direction, player.angle) 
        all_sprites_list.add(bullet) 
        bullet_group.add(bullet) 
      elif event.type == pygame.KEYUP: 
       if event.key == pygame.K_LEFT: 
        player.angle_speed = 0 
       elif event.key == pygame.K_RIGHT: 
        player.angle_speed = 0 

     all_sprites_list.update() 
     player.rect.clamp_ip(screen_rect) 

     screen.fill(WHITE) 
     all_sprites_list.draw(screen) 
     pygame.display.flip() 

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