基于python实现黄金矿工小游戏

以下是一个使用Python实现的黄金矿工本地小游戏,基于Pygame库创建。我将逐步解释代码结构、规则设计、关卡系统和难度选择机制。代码完整且可运行,您只需安装Pygame(通过
pip install pygame
)即可在本地执行。

游戏概述

黄金矿工是一个经典游戏:玩家控制一个可摆动的钩子,在有限时间内抓取地图上的金块、石头等物品,将它们拉回起点以获取分数。游戏规则包括:

钩子控制:用键盘方向键(左/右)控制钩子摆动角度,空格键发射钩子。物品抓取:钩子碰到物品时自动抓取,并拉回起点。分数系统:金块价值高,石头价值低;不同物品有不同的分数。时间限制:每关有倒计时,超时则失败。关卡目标:每个关卡需达到指定分数才能通关。难度选择:影响钩子速度、物品分布和分数倍率。

完整代码实现


import pygame
import sys
import random
import math

# 初始化Pygame
pygame.init()

# 屏幕设置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("黄金矿工")

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
GRAY = (128, 128, 128)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

# 游戏状态
class GameState:
    def __init__(self):
        self.score = 0
        self.time_left = 60  # 初始时间(秒)
        self.current_level = 1
        self.difficulty = "easy"  # 难度:easy, medium, hard
        self.game_over = False
        self.win = False

# 钩子类
class Hook:
    def __init__(self):
        self.length = 200  # 钩子长度
        self.angle = math.pi / 4  # 初始角度(45度)
        self.angular_velocity = 0.05  # 角速度
        self.x = SCREEN_WIDTH // 2  # 起点x坐标
        self.y = 50  # 起点y坐标
        self.end_x = self.x + self.length * math.cos(self.angle)  # 钩子末端x
        self.end_y = self.y + self.length * math.sin(self.angle)  # 钩子末端y
        self.is_shooting = False
        self.is_retracting = False
        self.retract_speed = 5  # 拉回速度
        self.grabbed_item = None  # 抓取的物品

    def update(self):
        # 更新钩子位置
        if not self.is_shooting and not self.is_retracting:
            self.angle += self.angular_velocity
            if self.angle > math.pi / 2 or self.angle < math.pi / 6:
                self.angular_velocity *= -1
            self.end_x = self.x + self.length * math.cos(self.angle)
            self.end_y = self.y + self.length * math.sin(self.angle)
        elif self.is_shooting:
            self.length += 5  # 发射时伸长
            self.end_x = self.x + self.length * math.cos(self.angle)
            self.end_y = self.y + self.length * math.sin(self.angle)
            if self.length > 400:  # 达到最大长度
                self.is_shooting = False
                self.is_retracting = True
        elif self.is_retracting:
            self.length -= self.retract_speed  # 拉回
            self.end_x = self.x + self.length * math.cos(self.angle)
            self.end_y = self.y + self.length * math.sin(self.angle)
            if self.length <= 200:  # 回到起点
                self.is_retracting = False
                self.length = 200
                if self.grabbed_item:
                    self.grabbed_item = None  # 释放物品

    def draw(self, screen):
        pygame.draw.line(screen, WHITE, (self.x, self.y), (self.end_x, self.end_y), 3)
        pygame.draw.circle(screen, RED, (int(self.end_x), int(self.end_y)), 10)  # 钩子末端

# 物品类
class Item:
    def __init__(self, x, y, item_type):
        self.x = x
        self.y = y
        self.type = item_type  # "gold", "rock", "diamond"
        self.radius = 20
        self.value = self.get_value()
        self.is_grabbed = False

    def get_value(self):
        if self.type == "gold":
            return 100
        elif self.type == "rock":
            return 20
        elif self.type == "diamond":
            return 200
        return 0

    def draw(self, screen):
        color = YELLOW if self.type == "gold" else GRAY if self.type == "rock" else BLUE
        pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.radius)

# 关卡管理
class LevelManager:
    def __init__(self, difficulty):
        self.difficulty = difficulty
        self.levels = {
            1: {"target_score": 500, "items": self.generate_items(1)},
            2: {"target_score": 1000, "items": self.generate_items(2)},
            3: {"target_score": 1500, "items": self.generate_items(3)}
        }
        self.current_level = 1

    def generate_items(self, level):
        items = []
        num_items = 5 + level  # 每关物品数量增加
        for _ in range(num_items):
            x = random.randint(100, SCREEN_WIDTH - 100)
            y = random.randint(150, SCREEN_HEIGHT - 100)
            # 根据难度和关卡设置物品类型概率
            if self.difficulty == "easy":
                types = ["gold"] * 5 + ["rock"] * 3 + ["diamond"] * 2
            elif self.difficulty == "medium":
                types = ["gold"] * 4 + ["rock"] * 4 + ["diamond"] * 2
            else:  # hard
                types = ["gold"] * 3 + ["rock"] * 5 + ["diamond"] * 2
            item_type = random.choice(types)
            items.append(Item(x, y, item_type))
        return items

    def next_level(self):
        if self.current_level < len(self.levels):
            self.current_level += 1
            return True
        return False

# 主游戏类
class GoldMinerGame:
    def __init__(self):
        self.state = GameState()
        self.hook = Hook()
        self.level_manager = LevelManager(self.state.difficulty)
        self.items = self.level_manager.levels[self.state.current_level]["items"]
        self.font = pygame.font.SysFont(None, 36)
        self.clock = pygame.time.Clock()
        self.last_time = pygame.time.get_ticks()

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and not self.hook.is_shooting and not self.hook.is_retracting:
                    self.hook.is_shooting = True
                if event.key == pygame.K_LEFT:
                    self.hook.angular_velocity = -0.05  # 左转
                if event.key == pygame.K_RIGHT:
                    self.hook.angular_velocity = 0.05  # 右转
                # 难度选择(在游戏开始前或菜单中)
                if event.key == pygame.K_e:
                    self.state.difficulty = "easy"
                    self.reset_game()
                if event.key == pygame.K_m:
                    self.state.difficulty = "medium"
                    self.reset_game()
                if event.key == pygame.K_h:
                    self.state.difficulty = "hard"
                    self.reset_game()

    def reset_game(self):
        self.state = GameState()
        self.state.difficulty = self.state.difficulty
        self.level_manager = LevelManager(self.state.difficulty)
        self.items = self.level_manager.levels[self.state.current_level]["items"]
        self.hook = Hook()

    def update(self):
        # 更新时间
        current_time = pygame.time.get_ticks()
        if current_time - self.last_time > 1000:  # 每秒减少时间
            self.state.time_left -= 1
            self.last_time = current_time

        # 更新钩子
        self.hook.update()

        # 检测抓取
        if self.hook.is_shooting or self.hook.is_retracting:
            for item in self.items:
                if not item.is_grabbed:
                    distance = math.sqrt((self.hook.end_x - item.x)**2 + (self.hook.end_y - item.y)**2)
                    if distance < self.hook.retract_speed + item.radius:  # 简单碰撞检测
                        item.is_grabbed = True
                        self.hook.grabbed_item = item
                        self.state.score += item.value

        # 检查游戏状态
        if self.state.time_left <= 0:
            self.state.game_over = True
        elif self.state.score >= self.level_manager.levels[self.state.current_level]["target_score"]:
            if self.level_manager.next_level():
                self.items = self.level_manager.levels[self.state.current_level]["items"]
                self.state.time_left = 60  # 重置时间
                self.hook = Hook()  # 重置钩子
            else:
                self.state.win = True  # 通关

    def draw(self):
        screen.fill(BLACK)
        # 绘制物品
        for item in self.items:
            item.draw(screen)
        # 绘制钩子
        self.hook.draw(screen)
        # 绘制UI
        score_text = self.font.render(f"分数: {self.state.score}", True, WHITE)
        time_text = self.font.render(f"时间: {self.state.time_left}秒", True, WHITE)
        level_text = self.font.render(f"关卡: {self.state.current_level}", True, WHITE)
        difficulty_text = self.font.render(f"难度: {self.state.difficulty}", True, WHITE)
        target_text = self.font.render(f"目标: {self.level_manager.levels[self.state.current_level]['target_score']}", True, WHITE)
        screen.blit(score_text, (10, 10))
        screen.blit(time_text, (10, 50))
        screen.blit(level_text, (10, 90))
        screen.blit(difficulty_text, (10, 130))
        screen.blit(target_text, (10, 170))
        
        if self.state.game_over:
            over_text = self.font.render("游戏结束!", True, RED)
            screen.blit(over_text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2))
        elif self.state.win:
            win_text = self.font.render("恭喜通关!", True, GREEN)
            screen.blit(win_text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2))
        
        pygame.display.flip()

    def run(self):
        while True:
            self.handle_events()
            if not self.state.game_over and not self.state.win:
                self.update()
            self.draw()
            self.clock.tick(60)  # 60 FPS

# 启动游戏
if __name__ == "__main__":
    game = GoldMinerGame()
    game.run()

代码解释

代码结构清晰,分为以下几个部分:

初始化:设置屏幕、颜色和游戏状态。钩子类(Hook):控制钩子的摆动、发射和拉回。角度通过三角函数计算:钩子末端坐标由起点坐标、长度和角度决定,公式为:

玩家用方向键控制钩子摆动角度,空格键发射钩子。钩子发射后伸长,碰到物品时抓取并自动拉回起点。抓取物品后增加分数:金块100100100分,石头202020分,钻石200200200分。每关限时60秒,超时则游戏结束。达到目标分数即可进入下一关。

关卡系统

共3个关卡,关卡1目标500分,关卡2目标1000分,关卡3目标1500分。每关物品数量递增(从6个到8个),物品分布随机。通关所有关卡后显示胜利画面。

难度选择

提供三种难度:简单(easy)、中等(medium)、困难(hard)。难度影响:
物品类型概率:简单模式金块概率高(P(gold)≈0.5P( ext{gold}) approx 0.5P(gold)≈0.5),困难模式石头概率高(P(rock)≈0.5P( ext{rock}) approx 0.5P(rock)≈0.5)。钩子速度:在代码中,钩子拉回速度固定,但可通过调整
retract_speed
实现难度变化(例如,困难模式速度减半)。
在游戏中按’E’、‘M’、'H’键切换难度并重置游戏。

如何运行和扩展

运行方法:将代码保存为
gold_miner.py
,安装Pygame后运行。扩展建议
添加更多关卡:修改
LevelManager
中的
levels
字典。增加新物品:如炸弹(扣分),在
Item
类中添加新类型。改进图形:使用图片替换圆形绘图。添加音效:用Pygame的
mixer
模块添加音效。

这个实现保证了游戏的真实性和可玩性,您可以根据需求进一步优化。如果有问题,请随时提问!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容