pygame实现射击游戏

文章目录

代码

创建shot_demo.py,代码:

python 复制代码
import pygame
import random
import sys

# --- 常量定义 ---
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60

# 颜色定义 (R, G, B)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)


# --- 类定义 ---

class Player(pygame.sprite.Sprite):
    """玩家飞船类"""

    def __init__(self):
        super().__init__()
        # 使用一个绿色矩形代表玩家
        self.image = pygame.Surface((50, 40))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.centerx = SCREEN_WIDTH // 2
        self.rect.bottom = SCREEN_HEIGHT - 30
        self.speed = 8
        self.shoot_delay = 250  # 射击冷却时间(毫秒)
        self.last_shot = pygame.time.get_ticks()

    def update(self):
        # 键盘控制移动
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.rect.x -= self.speed
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.rect.x += self.speed
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            self.rect.y -= self.speed
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.rect.y += self.speed

        # 限制玩家在屏幕范围内
        if self.rect.right > SCREEN_WIDTH:
            self.rect.right = SCREEN_WIDTH
        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.bottom > SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT
        if self.rect.top < 0:
            self.rect.top = 0

    def shoot(self):
        # 处理射击逻辑,包含冷却时间
        now = pygame.time.get_ticks()
        if now - self.last_shot > self.shoot_delay:
            self.last_shot = now
            bullet = Bullet(self.rect.centerx, self.rect.top)
            all_sprites.add(bullet)
            bullets.add(bullet)


class Enemy(pygame.sprite.Sprite):
    """敌机类"""

    def __init__(self):
        super().__init__()
        # 使用一个红色矩形代表敌人
        self.image = pygame.Surface((30, 30))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        # 在屏幕顶部随机位置生成
        self.rect.x = random.randrange(SCREEN_WIDTH - self.rect.width)
        self.rect.y = random.randrange(-100, -40)
        self.speedy = random.randrange(1, 5)

    def update(self):
        self.rect.y += self.speedy
        # 如果敌人飞出屏幕底部,则将其重置到顶部
        if self.rect.top > SCREEN_HEIGHT:
            self.rect.x = random.randrange(SCREEN_WIDTH - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.speedy = random.randrange(1, 5)


class Bullet(pygame.sprite.Sprite):
    """子弹类"""

    def __init__(self, x, y):
        super().__init__()
        # 使用一个白色小矩形代表子弹
        self.image = pygame.Surface((5, 10))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.bottom = y
        self.speedy = -10

    def update(self):
        self.rect.y += self.speedy
        # 如果子弹飞出屏幕顶部,则销毁它以节省内存
        if self.rect.bottom < 0:
            self.kill()


# --- 游戏初始化 ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("简易太空射击游戏")
clock = pygame.time.Clock()
font = pygame.font.SysFont('arial', 30)

# 创建精灵和精灵组
all_sprites = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()

player = Player()
all_sprites.add(player)

# 创建初始敌人
for _ in range(8):
    enemy = Enemy()
    all_sprites.add(enemy)
    enemies.add(enemy)

score = 0
running = True

# --- 游戏主循环 ---
while running:
    # 1. 控制帧率
    clock.tick(FPS)

    # 2. 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                player.shoot()

    # 3. 更新游戏状态
    all_sprites.update()

    # 4. 碰撞检测
    # 子弹击中敌人 (True, True) 表示两者都消失
    hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
    for hit in hits:
        score += 1
        # 重新生成一个敌人
        enemy = Enemy()
        all_sprites.add(enemy)
        enemies.add(enemy)

    # 敌人撞到玩家
    hits = pygame.sprite.spritecollide(player, enemies, False)
    if hits:
        print(f"游戏结束!最终得分: {score}")
        running = False

    # 5. 绘制/渲染
    screen.fill(BLACK)  # 用黑色背景清空屏幕
    all_sprites.draw(screen)  # 绘制所有精灵

    # 绘制分数
    score_text = font.render(f'Score: {score}', True, WHITE)
    screen.blit(score_text, (10, 10))

    # 6. 翻转显示缓冲区
    pygame.display.flip()

pygame.quit()
sys.exit()
操作方式
动作 按键 (方向键 / WASD) 说明
移动 ↑ ↓ ← → 或 W A S D 控制绿色方块(玩家飞船)在屏幕范围内上下左右移动。
射击 空格键 (Space) 发射白色子弹。注意,代码中设置了冷却时间,不能无限连发。
退出 点击窗口 "X" 关闭游戏窗口。

实测wasd无效,方向键有效。

核心代码

这个游戏框架清晰地展示了Pygame开发的核心流程:
1、游戏初始化

pygame.init(): 启动Pygame库。

pygame.display.set_mode(): 创建游戏窗口。

pygame.time.Clock(): 创建时钟对象,用于控制游戏帧率。
2、精灵(Sprite)系统

通过继承 pygame.sprite.Sprite 类来创建玩家、敌人和子弹。这使得每个游戏对象都能方便地管理自己的图像 (image) 和位置 (rect)。

使用 pygame.sprite.Group() 来统一管理大量的游戏对象,可以方便地对它们进行批量更新 (update()) 和绘制 (draw())。
3、游戏主循环 (Game Loop)

这是游戏的心脏,每一帧都会重复执行以下步骤:

  • 处理事件: 监听用户的输入,如关闭窗口、按键按下等。
  • 更新状态: 调用所有精灵的 update() 方法,更新它们的位置、状态等。
  • 碰撞检测: 使用 groupcollide 和 spritecollide 等函数高效地检测不同精灵组之间的碰撞。
  • 绘制渲染: 先清空屏幕 (screen.fill),然后绘制所有需要显示的元素,最后使用 pygame.display.flip() 更新整个屏幕的显示。
相关推荐
sinat_383437361 小时前
如何在 Laravel 中筛选并格式化匹配预定义列表的产品数据
jvm·数据库·python
2401_846339561 小时前
mysql如何用执行流程思维写好SQL_SQL优化方法总结
jvm·数据库·python
forEverPlume1 小时前
SQL如何统计分组内不重复值的数量_COUNT与DISTINCT结合应用
jvm·数据库·python
chaofan9801 小时前
突破大模型落地瓶颈:Claude 4.7 与 GPT-5.5 长上下文工程实测
数据库·人工智能·python·gpt·自动化·php·api
2501_901200532 小时前
PHP源码部署需要多大硬盘空间_PHP项目存储空间估算方法【方法】
jvm·数据库·python
豆瓣鸡2 小时前
Agent实战练习
java·python·学习
2401_832365522 小时前
mysql如何优化mysql在多核CPU下的性能_调整线程并发数
jvm·数据库·python
m0_736439302 小时前
JavaScript中显式创建包装对象的后果与性能损耗
jvm·数据库·python
四维迁跃2 小时前
JavaScript中Object-defineProperties批量设置属性
jvm·数据库·python