How to create bullets in pygame?

前端 未结 2 555
滥情空心
滥情空心 2020-11-27 21:48

I know there have been several topics on this but I still can\'t figure out how to make my ship shoot bullets.. I want to add to my MOUSEBUTTONDOWN bullets shooting from the

相关标签:
2条回答
  • 2020-11-27 22:33

    There are several steps you have to go through to do this. You will need a picture of the bullet, a way to store the locations of the bullets, a way to create the bullets, a way to render the bullets, and a way to update the bullets. You appear to know how to import pictures already, so I'll skip that part.

    There are several ways that you can store pieces of information. I will be using a list of the top left corner of the bullets. Create the list anywhere before the final loop with bullets = [].

    To create the bullets, you will want to use the location of the mouse. Add in bullets.append([event.pos[0]-32, 500]) after shot.play(), indented the same amount.

    To render the bullets, you will be adding a for loop into your game loop. After the line screen.blit(background, (0, 0)), add the following code:

    for bullet in bullets:
        screen.blit(bulletpicture, pygame.Rect(bullet[0], bullet[1], 0, 0)
    

    To update the bullets, you need to put something somewhere in your game loop that looks like this:

    for b in range(len(bullets)):
        bullets[b][0] -= 10
    

    Finally, you need to remove the bullets when they reach the top of the screen. Add this after the for loop you just created (iterate over a slice copy, because lists shouldn't be modified during the iteration):

    for bullet in bullets[:]:
        if bullet[0] < 0:
            bullets.remove(bullet)
    

    After putting this all into your code, it should look something like this:

    import sys, pygame, pygame.mixer
    from pygame.locals import *
    
    pygame.init()
    
    size = width, height = 800, 600
    screen = pygame.display.set_mode(size)
    
    clock = pygame.time.Clock()
    
    bullets = []
    
    background = pygame.image.load("bg.png").convert()
    ship = pygame.image.load("ship.png").convert_alpha()
    ship = pygame.transform.scale(ship, (64, 64))
    bulletpicture = pygame.image.load("You know what to do").convert_alpha()
    
    shot = pygame.mixer.Sound("shot.wav")
    soundin = pygame.mixer.Sound("sound.wav")
    
    soundin.play()
    
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
    
            elif event.type == MOUSEBUTTONDOWN:
                shot.play()
                bullets.append([event.pos[0]-32, 500])
    
        clock.tick(60)
    
        mx, my = pygame.mouse.get_pos()
    
        for b in range(len(bullets)):
            bullets[b][0] -= 10
    
        # Iterate over a slice copy if you want to mutate a list.
        for bullet in bullets[:]:
            if bullet[0] < 0:
                bullets.remove(bullet)
    
        screen.blit(background, (0, 0))
    
        for bullet in bullets:
            screen.blit(bulletpicture, pygame.Rect(bullet[0], bullet[1], 0, 0))
    
        screen.blit(ship, (mx-32, 500))
        pygame.display.flip()
    

    If both you and I have done everything correctly, this should give you functioning bullets. Please, don't hesitate to ask me any questions if you don't understand what is going on or if something doesn't work.

    Note that images/pygame.Surfaces should be converted with the convert or convert_alpha methods to improve the performance.

    0 讨论(0)
  • 2020-11-27 22:55

    Here's an example that demonstrates how pygame.sprite.Sprites and pygame.sprite.Groups can be used to create bullets. It also shows how to shoot continuously with the help of a timer variable and the dt (delta time) that clock.tick returns.

    pygame.sprite.groupcollide is used for the collision detection between the bullets and the enemies sprite group. I iterate over the items in the hits dict to reduce the health points of the enemies.

    import random
    import pygame as pg
    
    
    pg.init()
    
    BG_COLOR = pg.Color('gray12')
    PLAYER_IMG = pg.Surface((30, 50), pg.SRCALPHA)
    pg.draw.polygon(PLAYER_IMG, pg.Color('dodgerblue'), [(0, 50), (15, 0), (30, 50)])
    ENEMY_IMG = pg.Surface((50, 30))
    ENEMY_IMG.fill(pg.Color('darkorange1'))
    BULLET_IMG = pg.Surface((9, 15))
    BULLET_IMG.fill(pg.Color('aquamarine2'))
    
    
    class Player(pg.sprite.Sprite):
    
        def __init__(self, pos, all_sprites, bullets):
            super().__init__()
            self.image = PLAYER_IMG
            self.rect = self.image.get_rect(center=pos)
            self.all_sprites = all_sprites
            self.add(self.all_sprites)
            self.bullets = bullets
            self.bullet_timer = .1
    
        def update(self, dt):
            self.rect.center = pg.mouse.get_pos()
    
            mouse_pressed = pg.mouse.get_pressed()
            self.bullet_timer -= dt  # Subtract the time since the last tick.
            if self.bullet_timer <= 0:
                self.bullet_timer = 0  # Bullet ready.
                if mouse_pressed[0]:  # Left mouse button.
                    # Create a new bullet instance and add it to the groups.
                    Bullet(pg.mouse.get_pos(), self.all_sprites, self.bullets)
                    self.bullet_timer = .1  # Reset the timer.
    
    
    class Enemy(pg.sprite.Sprite):
    
        def __init__(self, pos, *sprite_groups):
            super().__init__(*sprite_groups)
            self.image = ENEMY_IMG
            self.rect = self.image.get_rect(center=pos)
            self.health = 30
    
        def update(self, dt):
            if self.health <= 0:
                self.kill()
    
    
    class Bullet(pg.sprite.Sprite):
    
        def __init__(self, pos, *sprite_groups):
            super().__init__(*sprite_groups)
            self.image = BULLET_IMG
            self.rect = self.image.get_rect(center=pos)
            self.pos = pg.math.Vector2(pos)
            self.vel = pg.math.Vector2(0, -450)
            self.damage = 10
    
        def update(self, dt):
            # Add the velocity to the position vector to move the sprite.
            self.pos += self.vel * dt
            self.rect.center = self.pos  # Update the rect pos.
            if self.rect.bottom <= 0:
                self.kill()
    
    
    class Game:
    
        def __init__(self):
            self.clock = pg.time.Clock()
            self.screen = pg.display.set_mode((800, 600))
    
            self.all_sprites = pg.sprite.Group()
            self.enemies = pg.sprite.Group()
            self.bullets = pg.sprite.Group()
            self.player = Player((0, 0), self.all_sprites, self.bullets)
    
            for i in range(15):
                pos = (random.randrange(30, 750), random.randrange(500))
                Enemy(pos, self.all_sprites, self.enemies)
    
            self.done = False
    
        def run(self):
            while not self.done:
                # dt = time since last tick in milliseconds.
                dt = self.clock.tick(60) / 1000
                self.handle_events()
                self.run_logic(dt)
                self.draw()
    
        def handle_events(self):
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    self.done = True
    
        def run_logic(self, dt):
            self.all_sprites.update(dt)
    
            # hits is a dict. The enemies are the keys and bullets the values.
            hits = pg.sprite.groupcollide(self.enemies, self.bullets, False, True)
            for enemy, bullet_list in hits.items():
                for bullet in bullet_list:
                    enemy.health -= bullet.damage
    
        def draw(self):
            self.screen.fill(BG_COLOR)
            self.all_sprites.draw(self.screen)
            pg.display.flip()
    
    
    if __name__ == '__main__':
        Game().run()
        pg.quit()
    
    0 讨论(0)
提交回复
热议问题