Python 3.12 + Pygame 2.5.1 游戏开发:从0到1复刻Chrome恐龙游戏的5个关键步骤

1. 环境搭建与项目初始化

在开始编写游戏代码之前,我们需要确保开发环境配置正确。Python 3.12带来了多项性能优化和新特性,而Pygame 2.5.1则提供了更稳定的游戏开发框架。

首先创建一个新的项目目录,建议使用虚拟环境隔离依赖:

mkdir dino_game && cd dino_game
python -m venv venv
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate     # Windows

安装必要的依赖包:

pip install pygame==2.5.1

项目基础结构应该包含以下文件:

dino_game/
├── assets/
│   ├── Dino/
│   │   ├── DinoRun1.png
│   │   ├── DinoRun2.png
│   │   ├── DinoJump.png
│   │   └── DinoDuck.png
│   ├── Cactus/
│   │   ├── SmallCactus1.png
│   │   ├── SmallCactus2.png
│   │   └── LargeCactus1.png
│   └── Other/
│       ├── Cloud.png
│       └── Track.png
├── main.py
└── README.md

提示:游戏素材可以从开源资源网站获取,确保遵守相关版权规定。建议使用64x64像素的PNG格式图片以获得最佳性能。

2. 游戏核心架构设计

优秀的游戏架构应该遵循模块化原则,我们将游戏拆分为几个核心组件:

  • 游戏主循环 :控制游戏整体流程
  • 恐龙角色 :处理玩家控制逻辑
  • 障碍物系统 :生成和管理仙人掌、飞鸟等障碍
  • 场景管理 :处理背景、云朵等元素
  • 计分系统 :记录和显示玩家得分

创建一个基础的游戏类框架:

import pygame
import os
import random
from enum import Enum

class GameState(Enum):
    MENU = 0
    RUNNING = 1
    GAME_OVER = 2

class DinoGame:
    def __init__(self):
        pygame.init()
        self.screen_width = 1100
        self.screen_height = 600
        self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
        pygame.display.set_caption("Chrome Dino Clone")
        
        self.clock = pygame.time.Clock()
        self.game_state = GameState.MENU
        self.game_speed = 14
        self.score = 0
        
    def load_assets(self):
        # 资源加载逻辑
        pass
        
    def handle_events(self):
        # 事件处理逻辑
        pass
        
    def update(self):
        # 游戏状态更新
        pass
        
    def draw(self):
        # 渲染逻辑
        pass
        
    def run(self):
        running = True
        while running:
            self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(60)
            
        pygame.quit()

if __name__ == "__main__":
    game = DinoGame()
    game.run()

3. 恐龙角色实现

恐龙是游戏的核心角色,需要实现奔跑、跳跃和下蹲三种基本动作。我们使用面向对象的方式设计恐龙类:

class Dinosaur:
    def __init__(self):
        self.X_POS = 80
        self.Y_POS = 310
        self.Y_POS_DUCK = 340
        self.JUMP_VEL = 8.5
        
        # 加载精灵图
        self.run_img = [
            pygame.image.load(os.path.join("assets/Dino", "DinoRun1.png")),
            pygame.image.load(os.path.join("assets/Dino", "DinoRun2.png"))
        ]
        self.jump_img = pygame.image.load(os.path.join("assets/Dino", "DinoJump.png"))
        self.duck_img = [
            pygame.image.load(os.path.join("assets/Dino", "DinoDuck1.png")),
            pygame.image.load(os.path.join("assets/Dino", "DinoDuck2.png"))
        ]
        
        self.reset()
        
    def reset(self):
        self.dino_run = True
        self.dino_jump = False
        self.dino_duck = False
        self.step_index = 0
        self.jump_vel = self.JUMP_VEL
        self.image = self.run_img[0]
        self.rect = self.image.get_rect()
        self.rect.x = self.X_POS
        self.rect.y = self.Y_POS
        
    def update(self, user_input):
        if self.dino_run:
            self.run()
        if self.dino_jump:
            self.jump()
        if self.dino_duck:
            self.duck()
            
        # 动画帧控制
        if self.step_index >= 10:
            self.step_index = 0
            
        # 键盘控制
        if user_input[pygame.K_UP] and not self.dino_jump:
            self.dino_run = False
            self.dino_jump = True
            self.dino_duck = False
        elif user_input[pygame.K_DOWN] and not self.dino_jump:
            self.dino_run = False
            self.dino_jump = False
            self.dino_duck = True
        elif not (self.dino_jump or user_input[pygame.K_DOWN]):
            self.dino_run = True
            self.dino_jump = False
            self.dino_duck = False
    
    def run(self):
        self.image = self.run_img[self.step_index // 5]
        self.rect = self.image.get_rect()
        self.rect.x = self.X_POS
        self.rect.y = self.Y_POS
        self.step_index += 1
        
    def jump(self):
        self.image = self.jump_img
        if self.dino_jump:
            self.rect.y -= self.jump_vel * 4
            self.jump_vel -= 0.8
        if self.jump_vel < -self.JUMP_VEL:
            self.dino_jump = False
            self.jump_vel = self.JUMP_VEL
            
    def duck(self):
        self.image = self.duck_img[self.step_index // 5]
        self.rect = self.image.get_rect()
        self.rect.x = self.X_POS
        self.rect.y = self.Y_POS_DUCK
        self.step_index += 1
        
    def draw(self, screen):
        screen.blit(self.image, (self.rect.x, self.rect.y))

4. 障碍物系统实现

障碍物系统需要随机生成不同类型的障碍,并管理它们的移动和碰撞检测:

class Obstacle:
    def __init__(self, image, type):
        self.image = image
        self.type = type
        self.rect = self.image.get_rect()
        self.rect.x = 1100  # 从屏幕右侧生成
        
    def update(self):
        self.rect.x -= game_speed
        if self.rect.x < -self.rect.width:
            obstacles.pop()
            
    def draw(self, screen):
        screen.blit(self.image, self.rect)

class SmallCactus(Obstacle):
    def __init__(self, image):
        self.type = random.randint(0, 2)
        super().__init__(image, self.type)
        self.rect.y = 325

class LargeCactus(Obstacle):
    def __init__(self, image):
        self.type = random.randint(0, 2)
        super().__init__(image, self.type)
        self.rect.y = 300

class Bird(Obstacle):
    def __init__(self, image):
        self.type = 0
        super().__init__(image, self.type)
        self.rect.y = 250
        self.index = 0
        
    def draw(self, screen):
        if self.index >= 9:
            self.index = 0
        screen.blit(self.image[self.index//5], self.rect)
        self.index += 1

障碍物生成逻辑应该集成到主游戏类中:

def generate_obstacle(self):
    if len(self.obstacles) == 0:
        obstacle_type = random.randint(0, 2)
        if obstacle_type == 0:
            self.obstacles.append(SmallCactus(self.small_cactus_img))
        elif obstacle_type == 1:
            self.obstacles.append(LargeCactus(self.large_cactus_img))
        elif obstacle_type == 2:
            self.obstacles.append(Bird(self.bird_img))

5. 游戏逻辑完善与优化

最后我们需要完善游戏的核心逻辑,包括碰撞检测、计分系统和游戏状态管理:

def check_collision(self):
    for obstacle in self.obstacles:
        if self.player.rect.colliderect(obstacle.rect):
            pygame.time.delay(2000)
            self.game_state = GameState.GAME_OVER
            return True
    return False

def update_score(self):
    self.score += 1
    if self.score % 100 == 0:
        self.game_speed += 1
        
    font = pygame.font.Font(None, 30)
    text = font.render(f"Score: {self.score}", True, (83, 83, 83))
    text_rect = text.get_rect()
    text_rect.center = (1000, 40)
    self.screen.blit(text, text_rect)

def draw_menu(self):
    font = pygame.font.Font(None, 50)
    if self.game_state == GameState.MENU:
        text = font.render("Press any key to START", True, (83, 83, 83))
    elif self.game_state == GameState.GAME_OVER:
        text = font.render("Press any key to RESTART", True, (83, 83, 83))
        score_text = font.render(f"Your Score: {self.score}", True, (83, 83, 83))
        score_rect = score_text.get_rect()
        score_rect.center = (self.screen_width // 2, self.screen_height // 2 + 50)
        self.screen.blit(score_text, score_rect)
        
    text_rect = text.get_rect()
    text_rect.center = (self.screen_width // 2, self.screen_height // 2)
    self.screen.blit(text, text_rect)

完整的主游戏循环应该整合所有这些组件:

def run(self):
    running = True
    while running:
        self.clock.tick(30)
        
        if self.game_state == GameState.MENU:
            self.draw_menu()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                if event.type == pygame.KEYDOWN:
                    self.game_state = GameState.RUNNING
                    
        elif self.game_state == GameState.RUNNING:
            self.screen.fill((255, 255, 255))
            user_input = pygame.key.get_pressed()
            
            self.player.update(user_input)
            self.player.draw(self.screen)
            
            if len(self.obstacles) == 0:
                self.generate_obstacle()
                
            for obstacle in self.obstacles:
                obstacle.update()
                obstacle.draw(self.screen)
                if obstacle.rect.x < -obstacle.rect.width:
                    self.obstacles.remove(obstacle)
                    
            self.update_background()
            self.update_score()
            
            if self.check_collision():
                self.game_state = GameState.GAME_OVER
                
        elif self.game_state == GameState.GAME_OVER:
            self.draw_menu()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                if event.type == pygame.KEYDOWN:
                    self.reset_game()
                    
        pygame.display.update()
        
    pygame.quit()

通过这五个关键步骤,我们完成了一个功能完整的Chrome恐龙游戏复刻版。这个项目不仅展示了Pygame的基本用法,也演示了如何组织一个中等复杂度的游戏项目结构。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐