AI生成 Python小游戏 怪物防御战???

一、前言

一个一点人工都没有,全靠Deepseek生成的游戏是什么样子的呢?

答:

二、游戏介绍

1. 游戏核心机制

  • 玩家控制:WASD移动,鼠标瞄准射击

  • 怪物系统

    • 黄色怪物:3点生命,速度慢,受伤会缩小

    • 蓝色怪物:1点生命,速度快

    • 红色怪物:2点生命,速度中等

  • 死亡效果:怪物死亡时产生对应颜色的爆炸碎片

2. 道具系统

  • 四种道具箱从天而降:

    • 三连发(蓝色)

    • 扇形散射(紫色)

    • 射速加快(青色)

    • 子弹变大(橙色)

  • 击中道具箱获得对应能力,持续10秒

3. 视觉效果

  • 怪物血量条显示

  • 粒子爆炸效果

  • 击中道具箱的闪烁效果

  • 网格背景和游戏UI

4. 游戏进度

  • 波数系统:每消灭10个怪物进入下一波

  • 难度递增:怪物生成速度加快

  • 计分系统:不同怪物不同分数

5.操作说明:

  • WASD:移动玩家

  • 鼠标左键:射击

  • ESC:退出游戏

  • R:重新开始游戏

三、完整代码

import pygame
import sys
import math
import random
from pygame.locals import *

# 初始化pygame和字体
pygame.init()

# 设置中文字体
try:
    # 尝试使用系统字体
    font = pygame.font.Font("C:/Windows/Fonts/simhei.ttf", 24)  # 黑体
    small_font = pygame.font.Font("C:/Windows/Fonts/simhei.ttf", 18)
except:
    # 如果找不到,使用默认字体并打印提示
    print("警告: 找不到中文字体,请确保文件路径正确")
    font = pygame.font.SysFont(None, 24)
    small_font = pygame.font.SysFont(None, 18)

# 游戏窗口设置
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("怪物防御战")
clock = pygame.time.Clock()

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 100, 255)
YELLOW = (255, 255, 50)
PURPLE = (200, 50, 200)
CYAN = (0, 200, 200)
ORANGE = (255, 150, 0)
GRAY = (150, 150, 150)


class Player:
    def __init__(self):
        self.x = SCREEN_WIDTH // 2
        self.y = SCREEN_HEIGHT // 2
        self.radius = 20
        self.color = GREEN
        self.speed = 5
        self.shoot_cooldown = 0
        self.base_shoot_delay = 15
        self.shoot_delay = self.base_shoot_delay
        self.bullet_speed = 8
        self.bullet_size = 5
        self.bullet_color = WHITE
        self.shoot_mode = "single"  # single, triple, spread
        self.powerup_timer = 0
        self.score = 0
        self.lives = 3

    def update(self):
        # 玩家移动
        keys = pygame.key.get_pressed()
        if keys[K_w] and self.y > self.radius:
            self.y -= self.speed
        if keys[K_s] and self.y < SCREEN_HEIGHT - self.radius:
            self.y += self.speed
        if keys[K_a] and self.x > self.radius:
            self.x -= self.speed
        if keys[K_d] and self.x < SCREEN_WIDTH - self.radius:
            self.x += self.speed

        # 更新射击冷却
        if self.shoot_cooldown > 0:
            self.shoot_cooldown -= 1

        # 更新道具效果时间
        if self.powerup_timer > 0:
            self.powerup_timer -= 1
            if self.powerup_timer == 0:
                self.reset_powerup()

    def shoot(self, bullet_manager):
        if self.shoot_cooldown > 0:
            return

        mouse_x, mouse_y = pygame.mouse.get_pos()
        dx = mouse_x - self.x
        dy = mouse_y - self.y
        distance = max(0.1, math.sqrt(dx * dx + dy * dy))
        base_angle = math.atan2(dy, dx)

        if self.shoot_mode == "single":
            bullet_manager.add_bullet(self.x, self.y, base_angle,
                                      self.bullet_speed, self.bullet_size, self.bullet_color)

        elif self.shoot_mode == "triple":
            for i in range(3):
                angle = base_angle - 0.2 + (i * 0.2)
                bullet_manager.add_bullet(self.x, self.y, angle,
                                          self.bullet_speed, self.bullet_size, self.bullet_color)

        elif self.shoot_mode == "spread":
            for i in range(5):
                angle = base_angle - 0.4 + (i * 0.2)
                bullet_manager.add_bullet(self.x, self.y, angle,
                                          self.bullet_speed, self.bullet_size, self.bullet_color)

        self.shoot_cooldown = self.shoot_delay

    def apply_powerup(self, powerup_type):
        if powerup_type == "triple":
            self.shoot_mode = "triple"
            self.powerup_timer = 600  # 10秒
        elif powerup_type == "spread":
            self.shoot_mode = "spread"
            self.powerup_timer = 600
        elif powerup_type == "fast_shoot":
            self.shoot_delay = self.base_shoot_delay // 2
            self.powerup_timer = 600
        elif powerup_type == "big_bullet":
            self.bullet_size = 10
            self.powerup_timer = 600

    def reset_powerup(self):
        self.shoot_mode = "single"
        self.shoot_delay = self.base_shoot_delay
        self.bullet_size = 5

    def draw(self, surface):
        # 绘制玩家
        pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)
        pygame.draw.circle(surface, WHITE, (int(self.x), int(self.y)), self.radius, 2)

        # 绘制玩家朝向指示器
        mouse_x, mouse_y = pygame.mouse.get_pos()
        angle = math.atan2(mouse_y - self.y, mouse_x - self.x)
        end_x = self.x + math.cos(angle) * (self.radius + 10)
        end_y = self.y + math.sin(angle) * (self.radius + 10)
        pygame.draw.line(surface, RED, (self.x, self.y), (end_x, end_y), 3)


class Bullet:
    def __init__(self, x, y, angle, speed, size, color):
        self.x = x
        self.y = y
        self.angle = angle
        self.speed = speed
        self.size = size
        self.color = color
        self.radius = size
        self.rect = pygame.Rect(x - size, y - size, size * 2, size * 2)

    def update(self):
        self.x += math.cos(self.angle) * self.speed
        self.y += math.sin(self.angle) * self.speed
        self.rect.center = (int(self.x), int(self.y))

    def draw(self, surface):
        pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)

    def is_out_of_screen(self):
        return (self.x < -self.radius or self.x > SCREEN_WIDTH + self.radius or
                self.y < -self.radius or self.y > SCREEN_HEIGHT + self.radius)


class BulletManager:
    def __init__(self):
        self.bullets = []

    def add_bullet(self, x, y, angle, speed, size, color):
        bullet = Bullet(x, y, angle, speed, size, color)
        self.bullets.append(bullet)

    def update(self):
        # 更新所有子弹并移除超出屏幕的
        bullets_to_remove = []
        for bullet in self.bullets:
            bullet.update()
            if bullet.is_out_of_screen():
                bullets_to_remove.append(bullet)

        for bullet in bullets_to_remove:
            self.bullets.remove(bullet)

    def draw(self, surface):
        for bullet in self.bullets:
            bullet.draw(surface)

    def clear(self):
        self.bullets.clear()


class Monster:
    def __init__(self, monster_type):
        self.type = monster_type  # "yellow", "blue", "red"

        # 根据类型设置属性
        if monster_type == "yellow":  # 血量厚,移速慢
            self.color = YELLOW
            self.max_health = 3
            self.health = 3
            self.speed = 1.0
            self.radius = 30
            self.score_value = 50
        elif monster_type == "blue":  # 速度快,血量少
            self.color = BLUE
            self.max_health = 1
            self.health = 1
            self.speed = 3.5
            self.radius = 20
            self.score_value = 20
        else:  # "red" 综合属性
            self.color = RED
            self.max_health = 2
            self.health = 2
            self.speed = 2.0
            self.radius = 25
            self.score_value = 30

        # 随机在屏幕边缘生成
        side = random.randint(0, 3)
        if side == 0:  # 上边
            self.x = random.randint(0, SCREEN_WIDTH)
            self.y = -self.radius
        elif side == 1:  # 右边
            self.x = SCREEN_WIDTH + self.radius
            self.y = random.randint(0, SCREEN_HEIGHT)
        elif side == 2:  # 下边
            self.x = random.randint(0, SCREEN_WIDTH)
            self.y = SCREEN_HEIGHT + self.radius
        else:  # 左边
            self.x = -self.radius
            self.y = random.randint(0, SCREEN_HEIGHT)

        self.rect = pygame.Rect(self.x - self.radius, self.y - self.radius,
                                self.radius * 2, self.radius * 2)
        self.particles = []

    def update(self, player_x, player_y):
        # 计算朝向玩家的方向
        dx = player_x - self.x
        dy = player_y - self.y
        distance = max(0.1, math.sqrt(dx * dx + dy * dy))

        # 归一化并移动
        self.x += (dx / distance) * self.speed
        self.y += (dy / distance) * self.speed

        self.rect.center = (int(self.x), int(self.y))

    def take_damage(self):
        self.health -= 1
        if self.type == "yellow" and self.health > 0:
            # 黄色怪物受伤时缩小
            self.radius = max(10, int(self.radius * 0.7))
            self.rect = pygame.Rect(self.x - self.radius, self.y - self.radius,
                                    self.radius * 2, self.radius * 2)
        return self.health <= 0

    def create_death_particles(self):
        particles = []
        num_particles = 15 if self.type == "yellow" else 10

        for _ in range(num_particles):
            angle = random.uniform(0, math.pi * 2)
            speed = random.uniform(2, 5)
            size = random.randint(3, 8)
            life = random.randint(30, 60)

            particle = {
                'x': self.x,
                'y': self.y,
                'vx': math.cos(angle) * speed,
                'vy': math.sin(angle) * speed,
                'size': size,
                'color': self.color,
                'life': life,
                'max_life': life
            }
            particles.append(particle)

        return particles

    def draw(self, surface):
        # 绘制怪物
        pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)

        # 绘制血量条(如果血量大于1)
        if self.max_health > 1:
            bar_width = self.radius * 1.5
            bar_height = 5
            bar_x = self.x - bar_width // 2
            bar_y = self.y - self.radius - 10

            # 背景条
            pygame.draw.rect(surface, GRAY, (bar_x, bar_y, bar_width, bar_height))

            # 血量条
            health_width = int((self.health / self.max_health) * bar_width)
            health_color = GREEN if self.health > self.max_health * 0.5 else ORANGE if self.health > self.max_health * 0.25 else RED
            pygame.draw.rect(surface, health_color, (bar_x, bar_y, health_width, bar_height))


class PowerupBox:
    def __init__(self):
        self.x = random.randint(50, SCREEN_WIDTH - 50)
        self.y = -30
        self.width = 40
        self.height = 40
        self.speed = 2
        self.types = ["triple", "spread", "fast_shoot", "big_bullet"]
        self.type = random.choice(self.types)
        self.colors = {
            "triple": BLUE,
            "spread": PURPLE,
            "fast_shoot": CYAN,
            "big_bullet": ORANGE
        }
        self.color = self.colors[self.type]
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
        self.hit_effect = 0

    def update(self):
        self.y += self.speed
        self.rect.y = self.y

        if self.hit_effect > 0:
            self.hit_effect -= 1

        return self.y > SCREEN_HEIGHT

    def hit(self):
        self.hit_effect = 10  # 闪烁10帧

    def draw(self, surface):
        # 绘制物品箱
        pygame.draw.rect(surface, self.color, self.rect, border_radius=8)
        pygame.draw.rect(surface, WHITE, self.rect, 3, border_radius=8)

        # 绘制类型图标
        if self.type == "triple":
            # 三个点
            for i in range(3):
                pygame.draw.circle(surface, WHITE,
                                   (int(self.x + self.width // 2 - 8 + i * 8),
                                    int(self.y + self.height // 2)), 4)
        elif self.type == "spread":
            # 扇形
            center_x = self.x + self.width // 2
            center_y = self.y + self.height // 2
            pygame.draw.circle(surface, WHITE, (center_x, center_y), 8, 2)
            for angle in [-30, 0, 30]:
                rad = math.radians(angle)
                end_x = center_x + math.cos(rad) * 12
                end_y = center_y + math.sin(rad) * 12
                pygame.draw.line(surface, WHITE, (center_x, center_y), (end_x, end_y), 2)
        elif self.type == "fast_shoot":
            # 闪电符号
            points = [
                (self.x + self.width // 2, self.y + 10),
                (self.x + self.width // 2 - 5, self.y + self.height // 2),
                (self.x + self.width // 2 + 5, self.y + self.height // 2),
                (self.x + self.width // 2, self.y + self.height - 10)
            ]
            pygame.draw.lines(surface, WHITE, False, points, 3)
        elif self.type == "big_bullet":
            # 大子弹
            center_x = self.x + self.width // 2
            center_y = self.y + self.height // 2
            pygame.draw.circle(surface, WHITE, (center_x, center_y), 10)

        # 击中特效
        if self.hit_effect > 0:
            pygame.draw.rect(surface, WHITE, self.rect, 5, border_radius=8)


class ParticleSystem:
    def __init__(self):
        self.particles = []

    def add_particles(self, particles):
        self.particles.extend(particles)

    def update(self):
        particles_to_remove = []
        for particle in self.particles:
            particle['x'] += particle['vx']
            particle['y'] += particle['vy']
            particle['vy'] += 0.1  # 重力效果
            particle['life'] -= 1

            # 根据生命值调整大小
            if particle['life'] > 0:
                particle['size'] = max(1, particle['size'] * (particle['life'] / particle['max_life']))
            else:
                particles_to_remove.append(particle)

        for particle in particles_to_remove:
            self.particles.remove(particle)

    def draw(self, surface):
        for particle in self.particles:
            alpha = int(255 * (particle['life'] / particle['max_life']))
            color_with_alpha = (*particle['color'], alpha)

            # 创建一个临时surface来绘制带透明度的粒子
            particle_surface = pygame.Surface((particle['size'] * 2, particle['size'] * 2), pygame.SRCALPHA)
            pygame.draw.circle(particle_surface, color_with_alpha,
                               (particle['size'], particle['size']), particle['size'])
            surface.blit(particle_surface,
                         (int(particle['x'] - particle['size']),
                          int(particle['y'] - particle['size'])))


class Game:
    def __init__(self):
        self.player = Player()
        self.bullet_manager = BulletManager()
        self.monsters = []
        self.powerups = []
        self.particle_system = ParticleSystem()
        self.monster_spawn_timer = 0
        self.powerup_spawn_timer = 0
        self.game_over = False
        self.wave = 1
        self.monsters_killed = 0
        self.monster_spawn_delay = 90  # 初始怪物生成间隔
        self.powerup_spawn_delay = 600  # 道具生成间隔

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pygame.quit()
                    sys.exit()
                elif event.key == K_r and self.game_over:
                    self.__init__()  # 重新开始游戏
            elif event.type == MOUSEBUTTONDOWN:
                if event.button == 1:  # 左键
                    self.player.shoot(self.bullet_manager)

    def update(self):
        if self.game_over:
            return

        # 更新玩家
        self.player.update()

        # 自动射击(按住鼠标)
        if pygame.mouse.get_pressed()[0]:
            self.player.shoot(self.bullet_manager)

        # 更新子弹
        self.bullet_manager.update()

        # 生成怪物
        self.monster_spawn_timer += 1
        if self.monster_spawn_timer >= self.monster_spawn_delay:
            monster_type = random.choice(["yellow", "blue", "red"])
            monster = Monster(monster_type)
            self.monsters.append(monster)
            self.monster_spawn_timer = 0

            # 随着波数增加,生成速度加快
            self.monster_spawn_delay = max(30, 90 - self.wave * 5)

        # 生成道具
        self.powerup_spawn_timer += 1
        if self.powerup_spawn_timer >= self.powerup_spawn_delay:
            powerup = PowerupBox()
            self.powerups.append(powerup)
            self.powerup_spawn_timer = 0

        # 更新怪物
        monsters_to_remove = []
        for monster in self.monsters:
            monster.update(self.player.x, self.player.y)

            # 检查怪物是否碰到玩家
            dx = monster.x - self.player.x
            dy = monster.y - self.player.y
            distance = math.sqrt(dx * dx + dy * dy)

            if distance < monster.radius + self.player.radius:
                self.player.lives -= 1
                monsters_to_remove.append(monster)
                self.particle_system.add_particles(monster.create_death_particles())

                if self.player.lives <= 0:
                    self.game_over = True

        # 更新道具
        powerups_to_remove = []
        for powerup in self.powerups:
            if powerup.update():  # 如果超出屏幕
                powerups_to_remove.append(powerup)

        # 检测子弹和怪物碰撞
        for bullet in self.bullet_manager.bullets[:]:
            bullet_rect = bullet.rect

            for monster in self.monsters[:]:
                if bullet_rect.colliderect(monster.rect):
                    if monster.take_damage():
                        # 怪物死亡
                        self.player.score += monster.score_value
                        self.monsters_killed += 1
                        monsters_to_remove.append(monster)

                        # 添加死亡粒子效果
                        self.particle_system.add_particles(monster.create_death_particles())

                    # 移除子弹
                    if bullet in self.bullet_manager.bullets:
                        self.bullet_manager.bullets.remove(bullet)
                    break

        # 检测子弹和道具碰撞
        for bullet in self.bullet_manager.bullets[:]:
            for powerup in self.powerups[:]:
                if bullet.rect.colliderect(powerup.rect):
                    powerup.hit()
                    self.player.apply_powerup(powerup.type)
                    powerups_to_remove.append(powerup)

                    # 移除子弹
                    if bullet in self.bullet_manager.bullets:
                        self.bullet_manager.bullets.remove(bullet)
                    break

        # 移除已处理的怪物和道具
        for monster in monsters_to_remove:
            if monster in self.monsters:
                self.monsters.remove(monster)

        for powerup in powerups_to_remove:
            if powerup in self.powerups:
                self.powerups.remove(powerup)

        # 更新粒子系统
        self.particle_system.update()

        # 更新波数
        if self.monsters_killed >= 10 * self.wave:
            self.wave += 1
            self.monsters_killed = 0

    def draw(self):
        screen.fill((20, 20, 40))  # 深蓝色背景

        # 绘制网格背景
        for x in range(0, SCREEN_WIDTH, 50):
            pygame.draw.line(screen, (30, 30, 50), (x, 0), (x, SCREEN_HEIGHT), 1)
        for y in range(0, SCREEN_HEIGHT, 50):
            pygame.draw.line(screen, (30, 30, 50), (0, y), (SCREEN_WIDTH, y), 1)

        # 绘制粒子
        self.particle_system.draw(screen)

        # 绘制道具
        for powerup in self.powerups:
            powerup.draw(screen)

        # 绘制怪物
        for monster in self.monsters:
            monster.draw(screen)

        # 绘制子弹
        self.bullet_manager.draw(screen)

        # 绘制玩家
        self.player.draw(screen)

        # 绘制UI
        self.draw_ui()

        # 游戏结束画面
        if self.game_over:
            self.draw_game_over()

        pygame.display.flip()

    def draw_ui(self):
        # 分数
        score_text = font.render(f"分数: {self.player.score}", True, WHITE)
        screen.blit(score_text, (10, 10))

        # 生命值
        lives_text = font.render(f"生命: {self.player.lives}", True, WHITE)
        screen.blit(lives_text, (10, 40))

        # 波数
        wave_text = font.render(f"波数: {self.wave}", True, WHITE)
        screen.blit(wave_text, (10, 70))

        # 当前能力
        mode_text = small_font.render(f"射击模式: {self.player.shoot_mode}", True, WHITE)
        screen.blit(mode_text, (10, 100))

        # 道具剩余时间
        if self.player.powerup_timer > 0:
            timer_text = small_font.render(f"能力剩余: {self.player.powerup_timer // 60}秒", True, YELLOW)
            screen.blit(timer_text, (10, 130))

        # 怪物数量
        monster_count_text = small_font.render(f"怪物数量: {len(self.monsters)}", True, WHITE)
        screen.blit(monster_count_text, (10, 160))

        # 帮助文本
        help_text = small_font.render("WASD移动, 鼠标瞄准射击, ESC退出, R重新开始", True, GRAY)
        screen.blit(help_text, (SCREEN_WIDTH // 2 - help_text.get_width() // 2, SCREEN_HEIGHT - 30))

        # 绘制怪物图例
        legend_y = SCREEN_HEIGHT - 150
        pygame.draw.rect(screen, YELLOW, (SCREEN_WIDTH - 200, legend_y, 15, 15))
        yellow_text = small_font.render("黄色: 血厚(3枪), 移速慢", True, WHITE)
        screen.blit(yellow_text, (SCREEN_WIDTH - 180, legend_y - 3))

        pygame.draw.rect(screen, BLUE, (SCREEN_WIDTH - 200, legend_y + 30, 15, 15))
        blue_text = small_font.render("蓝色: 血少(1枪), 移速快", True, WHITE)
        screen.blit(blue_text, (SCREEN_WIDTH - 180, legend_y + 27))

        pygame.draw.rect(screen, RED, (SCREEN_WIDTH - 200, legend_y + 60, 15, 15))
        red_text = small_font.render("红色: 中等(2枪), 移速中等", True, WHITE)
        screen.blit(red_text, (SCREEN_WIDTH - 180, legend_y + 57))

    def draw_game_over(self):
        # 半透明覆盖层
        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
        overlay.fill((0, 0, 0, 180))
        screen.blit(overlay, (0, 0))

        # 游戏结束文本
        game_over_text = font.render("游戏结束!", True, RED)
        screen.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2, SCREEN_HEIGHT // 2 - 50))

        final_score_text = font.render(f"最终分数: {self.player.score}", True, WHITE)
        screen.blit(final_score_text, (SCREEN_WIDTH // 2 - final_score_text.get_width() // 2, SCREEN_HEIGHT // 2))

        final_wave_text = font.render(f"到达波数: {self.wave}", True, WHITE)
        screen.blit(final_wave_text, (SCREEN_WIDTH // 2 - final_wave_text.get_width() // 2, SCREEN_HEIGHT // 2 + 40))

        restart_text = font.render("按 R 键重新开始", True, GREEN)
        screen.blit(restart_text, (SCREEN_WIDTH // 2 - restart_text.get_width() // 2, SCREEN_HEIGHT // 2 + 90))


def main():
    game = Game()

    while True:
        game.handle_events()
        game.update()
        game.draw()
        clock.tick(60)


if __name__ == "__main__":
    main()

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值