Python文字向RPG

这篇文章介绍了作者基于Python和pygame库实现的一个简单的RPG游戏,包括主菜单、大地图功能以及战斗类和村庄类的设计。源码展示了如何创建主程序入口、主菜单选项、地图导航以及基本的战斗逻辑。
摘要由CSDN通过智能技术生成


前几天看到自己四年前看过的文章,闲来无事,也做了一个玩玩

https://blog.csdn.net/abcdu472390947/article/details/84589224/

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主类

'''
主程序入口
'''
import sys
import time
from collections import deque

import pygame

from MainMenu import main_menu_scr
    
def init():
    pygame.init()
    
    clock = pygame.time.Clock()
    clock.tick(30)
    screen = pygame.display.set_mode((1024, 512))
    pygame.display.set_caption('TextRPG')
    return screen

if __name__ == "__main__":
    pages = deque()
    addpages = {
    }
    
    screen = init()
    main_menu = main_menu_scr(addpages)
    pages.append(main_menu)
    args = []
    while len(pages)>0:
        args = pages[-1].disp(screen, pages, addpages, args)
    pygame.quit()
    sys.exit()

主菜单

'''
主菜单类
'''
import pygame

from WorldMap import WorldMap_page

class main_menu_scr:
    def __init__(self, addpages:dict) -> None:
        addpages[self] = [WorldMap_page(addpages)]
        pass
    
    def disp(self, screen, pages, addpages:dict, *args):
        options = ["开始游戏", "结束游戏"]
        selected_option = 0


        running = True
        game_started = False

        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    exit()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP:
                        selected_option -= 1
                    elif event.key == pygame.K_DOWN:
                        selected_option += 1
                    elif event.key == pygame.K_SPACE:
                        if selected_option == 0 and not game_started:
                            # print("游戏开始了")
                            game_started = True
                            pages.append(addpages[self][0])
                            return
                        elif selected_option == 1:
                            running = False

            selected_option %= len(options)

            # 清屏
            screen.fill((0, 0, 0))

            # 显示主菜单
            for i in range(len(options)):
                if i == selected_option:
                    text = "-> " + options[i] + " <-"
                    color = (255, 255, 255)  # 白色
                else:
                    text = options[i]
                    color = (128, 128, 128)  # 灰色

                font = pygame.font.SysFont('simHei', 32)  # 使用系统中可用的 "simHei" 字体
                text_surface = font.render(text, True, color)
                text_rect = text_surface.get_rect(center=(screen.get_size()[0]/2, screen.get_size()[1]/2 + i * 50))
                screen.blit(text_surface, text_rect)

            pygame.display.flip()

大地图

import random

import pygame

from Village import village_page
from Battle import BattleSrc

class WorldMap_page:
    def __init__(self, addpages) -> None:
        addpages[self] = [village_page(addpages), BattleSrc(addpages)]
        # 读取地图文件
        map_filename = "WorldMap.csv"
        try:
            with open(map_filename, "r") as file:
                self.map_data = [line.strip().replace(",",'') for line in file.readlines()]
        except FileNotFoundError:
            print(f"Error: Cannot find file '{map_filename}'")
            return

        # 确定行数和列数
        c = len(self.map_data)
        r = len(self.map_data[0])
        self.player_pos = [(x,y) for x in range(c) for y in range(r) if self.getmap((x,y))=="初"][0]
        
        pass
    def getmap(self, pos):
        return self.map_data[pos[0]][pos[1]]
    
    def disp(self, screen, pages, addpages:dict, pos)->list:
        #初始化

        # 设置单元大小和字体
        unit_size = 32
        font = pygame.font.SysFont('simHei', unit_size)
        
        # 确定行数和列数
        c = len(self.map_data)
        r = len(self.map_data[0])

        # 计算地图绘制区域的大小
        map_area_width = r * unit_size
        map_area_height = c * unit_size

        # 计算地图绘制区域的左上角坐标
        map_area_x = (screen.get_width() - map_area_width) // 2
        map_area_y = (screen.get_height() - map_area_height) // 2
        
        player_pos = self.player_pos  # 初始化人物位置

        #循环体
        running = True
        isMoved = False

        while running:
            # 位置处理
            if isMoved and self.getmap(player_pos) == "村":
                pages.append(addpages[self][0])
                return [player_pos]
            
            # 事件处理
            if isMoved and random.randint(1, 16) == 1:
                # 遇敌
                pages.append(addpages[self][1])
                return [player_pos]
            isMoved = False
            
            # 接受操作
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                    exit()
                elif event.type == pygame.KEYDOWN:
                    dirkeys = [pygame.K_UP,pygame.K_DOWN,pygame.K_LEFT,pygame.K_RIGHT]
                    movposs = [[-1,0],[1,0],[0,-1],[0,1]]
                    for i in range(len(dirkeys)):
                        if event.key != dirkeys[i]:
                            continue
                        newPos = [x+y for x,y in zip(player_pos,movposs[i])]
                        # print(newPos)
                        if not 0 <= newPos[0] < c or not 0<=newPos[1] <r:
                            print("出界")
                            break
                        if self.getmap(newPos) == "无":
                            print("无")
                            break
                        player_pos = newPos
                        self.player_pos = player_pos
                        isMoved = True

            # 清屏
            screen.fill((0, 0, 0))
            # 绘制土黄区域作为地图背景
            pygame.draw.rect(screen, (205, 133, 63), (map_area_x, map_area_y, map_area_width, map_area_height))

            # 绘制
            # 在黑色区域中绘制地图内容
            for i in range(c):
                for j in range(r):
                    char = self.map_data[i][j]
                    if char == "村":
                        text_surface = font.render(char, True, (255, 255, 255))
                        text_rect = text_surface.get_rect()
                        text_rect.topleft = (map_area_x + j * unit_size, map_area_y + i * unit_size)
                        screen.blit(text_surface, text_rect)
                    elif char == "无":
                        pygame.draw.rect(screen, (0, 0, 0), (map_area_x + j * unit_size, map_area_y + i * unit_size, unit_size, unit_size))

            # 绘制人物位置
            player_char = "♀"
            text_surface = font.render(player_char, True, (255, 0, 0))  # 红色表示人物
            text_rect = text_surface.get_rect()
            text_rect.topleft = (map_area_x + player_pos[1] * unit_size, map_area_y + player_pos[0] * unit_size)
            screen.blit(text_surface, text_rect)

            pygame.display.flip()

战斗类

import pygame
from TextSys import dispText, WHITE, RED, GREEN
from Enemy import enemies
from Character import player

class BattleSrc:
    def __init__(self, addpages:dict) -> None:
        pass
    
    def disp(self, screen:pygame.Surface, pages:list, addpages:dict, wmpos)->list:
        #初始化
        options = ["攻击","技能","物品","逃跑"]
        selected_option = 0
        actors = [player, enemies[0]]
        actor = player
        enemies[0].HP = enemies[0].MHP

        #循环体
        running = True
        Texting = True
        isReturn = False
        text = f"野生的{enemies[0].name}出现了"
        gif_image = pygame.image.load(r'resource\image\Slime\Slime_Front11.png')
        original_width, original_height = gif_image.get_size()
        gif_image = pygame.transform.scale(gif_image, (original_width * 8, original_height * 8))

        # 控制闪烁效果的透明度
        alpha = 255
        alpha_direction = -2  # 透明度改变的方向和速度
        
        while running:
            #接受操作
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    # running = False
                    pass
                elif event.type == pygame.KEYDOWN:
                    if Texting:
                        if event.key == pygame.K_SPACE:
                            Texting = False
                            if isReturn:
                                pages.pop()
                                return [wmpos]
                            
                            if actor == enemies:
                                # 敌方行动
                                damage = [enemies[0].attack if not player.armor else enemies[0].attack-player.armor.attack][0]
                                text = f"{enemies[0].name}对你造成了{damage}点伤害"
                                Texting = True
                                player.HP-=damage
                                actor = player
                    else:
                        if actor == player:
                            if event.key == pygame.K_UP:
                                selected_option -= 1
                            elif event.key == pygame.K_DOWN:
                                selected_option += 1
                            elif event.key == pygame.K_SPACE:
                                if selected_option == 0:
                                    damage = [2 if not player.weapon else player.weapon.attack-enemies[0].defense][0]
                                    text = f"你对{enemies[0].name}造成了{damage}点伤害"
                                    Texting = True
                                    enemies[0].HP-=damage
                                    actor = enemies
                                

            selected_option %= len(options)

            # 清屏
            screen.fill((0, 0, 0))
            # 绘制文本
            dispText(screen, text, bottomleft=(128, 128*3), color=[(255, 255, 255) if Texting else (128, 128, 128)][0])

            # 绘制己方状态
            # 计算血量百分比
            health_percentage = player.getHPpct()

            # 绘制血量条
            HPbarpos = (128*6,128*3)
            health_bar_width = 200
            health_bar_height = 20
            health_bar_fill_width = int((health_percentage / 100) * health_bar_width)
            health_bar_rect = pygame.Rect(HPbarpos[0], HPbarpos[1], health_bar_width, health_bar_height)
            health_bar_fill_rect = pygame.Rect(HPbarpos[0], HPbarpos[1], health_bar_fill_width, health_bar_height)

            pygame.draw.rect(screen, RED, health_bar_rect)
            pygame.draw.rect(screen, GREEN, health_bar_fill_rect)

            # 显示血量百分比
            # font = pygame.font.SysFont(None, 30)
            # # hptext = f"Health: {health_percentage}%"
            # text_surface = font.render(hptext, True, WHITE)
            # screen.blit(text_surface, (HPbarpos[0], HPbarpos[1]))

            # 绘制敌方状态
            # 计算血量百分比
            health_percentage = enemies[0].getHPpct()
            # 绘制敌方血量条
            HPbarpos = (16*26,16*17)
            health_bar_width = 200
            health_bar_height = 20
            health_bar_fill_width = int((health_percentage / 100) * health_bar_width)
            health_bar_rect = pygame.Rect(HPbarpos[0], HPbarpos[1], health_bar_width, health_bar_height)
            health_bar_fill_rect = pygame.Rect(HPbarpos[0], HPbarpos[1], health_bar_fill_width, health_bar_height)

            pygame.draw.rect(screen, RED, health_bar_rect)
            pygame.draw.rect(screen, GREEN, health_bar_fill_rect)
            
            # 绘制行动选项
            for i in range(len(options)):
                optext = options[i]
                if i == selected_option and not Texting:
                    color = (255, 255, 255)  # 白色
                else:
                    color = (128, 128, 128)  # 灰色
                dispText(screen, optext, bottomleft=(64, 64 + i * 64), color=color)

            
            
            # 绘制敌方
            alpha += alpha_direction
            if alpha <= 0 or alpha >= 255:
                alpha_direction *= -1

            gif_image.set_alpha(alpha)
            gif_rect = gif_image.get_rect()
            gif_rect.center = (screen.get_size()[0] // 2, screen.get_size()[1] // 2-gif_image.get_height()/2)
            screen.blit(gif_image, gif_rect)

            # 死亡事件
            if enemies[0].HP <= 0:
                text = f"{enemies[0].name}倒下了"
                Texting = True
                isReturn = True

            pygame.display.flip()

村庄类

from typing import Callable

import pygame

from TextSys import dispText
from WeaponShop import WeaponShopScr

class village_page:
    def __init__(self, addpages:dict[Callable,list]) -> None:
        addpages[self] = [WeaponShopScr(addpages)]
        pass
    
    def disp(self, screen, pages:list, addpages:dict, wmpos):
        options = ["武器店", "防具店", "道具店", "旅馆", "离开村庄"]
        selected_option = 0
        # dispText(screen, "game start", center=(screen.get_width() // 2, screen.get_height() // 2))
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP:
                        selected_option -= 1
                    elif event.key == pygame.K_DOWN:
                        selected_option += 1
                    elif event.key == pygame.K_SPACE:
                        if selected_option == 0:
                            pages.append(addpages[self][0])
                            return [wmpos]
                        elif selected_option == 4:
                            pages.pop()
                            return [wmpos]
                            
                                

            selected_option %= len(options)

            # 清屏
            screen.fill((0, 0, 0))

            # 显示主菜单
            for i in range(len(options)):
                text = options[i]
                if i == selected_option:
                    color = (255, 255, 255)  # 白色
                else:
                    color = (128, 128, 128)  # 灰色
                dispText(screen, text, bottomleft=(0, 50 + i * 50), color=color)
            pygame.display.flip()

源码

TextRPG

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值