How to make enemies fire periodically using pygame.USEREVENT
我最近尝试使用
我如何做到使敌人实际上朝任意方向射击,然后最终朝玩家射击?
工作代码如下:
游戏主模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import pygame from constants import * from player import Player from Projectile import Projectile from pygame.math import Vector2 from enemy import Enemy pygame.init() screen = pygame.display.set_mode([500, 500]) pygame.display.set_caption('Labyrinth') all_sprites_list = pygame.sprite.Group() projectiles = pygame.sprite.Group() enemy_sprites = pygame.sprite.Group() # Spawn player player = Player(50, 50) all_sprites_list.add(player) # Spawn enemy enemy = Enemy(150, 150) enemy_sprites.add(enemy) clock = pygame.time.Clock() previous_time = pygame.time.get_ticks() speed = 12 keymap = { pygame.K_LEFT : Vector2(-speed, 0), pygame.K_RIGHT: Vector2(speed, 0), pygame.K_UP: Vector2(0, -speed), pygame.K_DOWN: Vector2(0, speed) } done = False # ----- Event Loop while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: vel = Vector2(-speed, 0) elif event.key == pygame.K_RIGHT: vel = Vector2(speed, 0) elif event.key == pygame.K_UP: vel = Vector2(0, -speed) elif event.key == pygame.K_DOWN: vel = Vector2(0, speed) current_time = pygame.time.get_ticks() pressed = pygame.key.get_pressed() for key in keymap: if pressed[key]: if current_time - previous_time > 500: previous_time = current_time projectiles.add(Projectile(player.rect.x, player.rect.y, vel)) # ----- Game Logic all_sprites_list.update() projectiles.update() enemy_sprites.update() screen.fill(GREEN) all_sprites_list.draw(screen) projectiles.draw(screen) enemy_sprites.draw(screen) pygame.display.flip() clock.tick(60) pygame.quit() |
播放器模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | from constants import * import pygame import time from datetime import datetime, timedelta class Player(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.image = pygame.Surface([15, 15]) self.image.fill(BLACK) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.fire_rate = 1 self.change_x = 0 self.change_y = 0 def changespeed(self, x, y): self.change_x += x self.change_y += y def update(self): self.rect.x += self.change_x self.rect.y += self.change_y |
敌人模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | from constants import * import pygame from Projectile import Projectile from pygame.math import Vector2 CANSHOOT = pygame.USEREVENT + 1 pygame.time.set_timer(CANSHOOT, 2000) speed = 12 projectiles = pygame.sprite.Group() class Enemy(pygame.sprite.Sprite): def __init__(self, x, y): super().__init__() self.image = pygame.Surface([10, 10]) self.image.fill(RED) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def can_shoot(self): for event in pygame.event.get(): if pygame.event.get(CANSHOOT): vel = Vector2(-speed, 0) projectiles.add(Projectile(self.rect.x, self.rect.y, vel)) projectiles.update() projectiles.draw(screen) |
弹丸模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import pygame from constants import * from pygame.math import Vector2 BULLET_IMG = pygame.Surface((4, 4)) BULLET_IMG.fill(RED) class Projectile(pygame.sprite.Sprite): def __init__(self, x, y, vel): super().__init__() self.image = BULLET_IMG self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.vel = Vector2(vel) def update(self): self.rect.move_ip(self.vel) |
程序中永远不要有两个事件循环(
如果敌人的小sprite应该能够独立开火,则需要给每个小sprite设置自己的计时器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import pygame from pygame.math import Vector2 class Enemy(pygame.sprite.Sprite): def __init__(self, x, y, projectiles): super().__init__() self.image = pygame.Surface([10, 10]) self.image.fill(RED) self.rect = self.image.get_rect(topleft=(x, y)) # The previous time when the sprite fired. self.previous_time = pygame.time.get_ticks() self.shoot_delay = 1000 # milliseconds self.speed = 12 self.projectiles = projectiles def update(self): now = pygame.time.get_ticks() if now - self.previous_time > self.shoot_delay: self.previous_time = now vel = Vector2(self.speed, 0) # Add the projectile to the group. self.projectiles.add(Projectile(self.rect.x, self.rect.y, vel)) class Projectile(pygame.sprite.Sprite): def __init__(self, x, y, vel): super().__init__() self.image = BULLET_IMG self.rect = self.image.get_rect(topleft=(x, y)) self.vel = Vector2(vel) def update(self): self.rect.move_ip(self.vel) pygame.init() screen = pygame.display.set_mode([500, 500]) RED = pygame.Color('red') GREEN = pygame.Color(40, 100, 0) BULLET_IMG = pygame.Surface((4, 4)) BULLET_IMG.fill(RED) all_sprites_list = pygame.sprite.Group() projectiles = pygame.sprite.Group() enemy_sprites = pygame.sprite.Group() # Pass the projectiles group to the enemy, so that # we can add the bullets in the update method later. enemy = Enemy(150, 150, projectiles) enemy_sprites.add(enemy) clock = pygame.time.Clock() done = False while not done: for event in pygame.event.get(): if event.type == pygame.QUIT: done = True # ----- Game Logic all_sprites_list.update() projectiles.update() enemy_sprites.update() screen.fill(GREEN) all_sprites_list.draw(screen) projectiles.draw(screen) enemy_sprites.draw(screen) pygame.display.flip() clock.tick(60) pygame.quit() |