QT大作业——自制小游戏

The RPGgame with QT

一、 系统架构

QT大作业——自制小游戏_第1张图片
该项目有4个ui组成,其中mainwindow作为项目程序入口,窗口跳转流程为:mainwindow->gamegraph->area_prairrie->playerstastus。

主要游戏功能装载在gamegraph和area_prairrie两个ui中,而该两个ui中,主要功能函数分别装载在gamegraph.h、monster中。

对于RPG游戏,person类主要存储了关于游戏玩家的个人属性,包括攻击力、防御力、HP、LV等基础属性以及装备、称号等高级属性。而monster类则存储了怪物的基础属性、战斗模式、击杀奖励等属性及方法。area_prairrie类则存储一个区域的所有怪物对象,及区域内一些游戏性功能。

二、游戏玩法

首先是开始游戏画面,这里可以选择开始游戏,继续游戏和结束游戏三个选项,点击开始/继续游戏后进入下一个界面——主游戏界面。
QT大作业——自制小游戏_第2张图片
在主游戏界面下,玩家可以选择恢复生命值、前往武器或防具店强化自身属性、出城打怪、保存游戏及退出游戏等功能,如下图所示:
QT大作业——自制小游戏_第3张图片
武器、防具点及旅店与常规游戏一样,这里不再介绍,我们直接看出城即战斗界面:
QT大作业——自制小游戏_第4张图片
如上图所示,出城后,我们可以查看自身状态,点击原处刷怪或继续前进则可以进入战斗状态,战斗过程在本游戏中直接跳过,在下方直接输出战斗结果,如下图所示:
QT大作业——自制小游戏_第5张图片
战斗结束后可以选择是否继续前进,需要注意的是,为了区分难度,这里每一次继续前进遇到的怪物难度都会逐渐增加,直到遇到BOSS,而如果玩家在与怪物对战过程中失败,则游戏结束,如下图所示:
QT大作业——自制小游戏_第6张图片
而如果不继续前进,则可以持续和当前难度水平怪物战斗提升等级,积攒金币,通过购买装备提升自己从而击败怪物,在这过程中,玩家可以随时查看自身状态,如下图所示:
QT大作业——自制小游戏_第7张图片

三、关键算法设计

3.1 战斗

本游戏中,与怪物战斗采用最简单的攻防相抵造成伤害。算法封装在Monster类中,代码如下:

void monster::battle(person &you)
{
    while (you.HP_now > 0 && HP >0)
    {
        if(you.DEF+you.have[2] < ATK)
            you.HP_now -= (ATK - you.DEF-you.have[2]);
        if(you.ATK +you.have[1] > DEF)
            HP -= (you.ATK +you.have[1]- DEF);
        else
        {
            QMessageBox box;
            box.setText("怪物防御力太高了,你打不动它,于是逃跑了!");
            box.exec();
            return ;
        }
        cout << "你的当前生命值为:" << you.HP_now << endl;
        cout << "怪物的当前生命值为:" << HP << endl;
    }
    if (you.HP_now <= 0)
    {
          you.gameover();
    }
    if (HP<=0)
    {
        cout << "恭喜你击败了怪物" << endl;
        cout << "你获得了金币,同时升级了" << endl;
        you.LVUP(1);
        you.show_stastus();
        you.getmoney(money);
    }
}

void monster::BOSS_battle(person& you)
{
    int MAX=HP;
    while (you.HP_now > 0 && HP > 0)
    {
        if(you.DEF+you.have[2] < ATK)
            you.HP_now -= (ATK - you.DEF-you.have[2]);
        if(you.ATK +you.have[1] > DEF)
            HP -= (you.ATK +you.have[1]- DEF);
        if (HP * 2 <= MAX)
            ATK = ATK * 1.2;
        if (HP * 10 <= MAX)
            ATK = ATK * 1.25;
        cout << "你的当前生命值为:" << you.HP_now << endl;
        cout << "怪物的当前生命值为:" << HP << endl;
    }
    if (you.HP_now <= 0)
    {
       you.gameover();
    }
    if (HP <= 0)
    {
        you.LVUP(5);
        you.show_stastus();
        you.getmoney(money);
    }
}

从上述代码中可以看到,游戏采用回合制,每次怪物对玩家造成的伤害=怪物的攻击力-玩家的防御力,而玩家对怪物造成的伤害同理,当有一方生命值先扣为0以下时,另一方获胜。而对于BOSS战,为了提升游戏难度,BOSS战中,Boss的战斗方式多了一个当BOSS血量降至一半以下时,BOSS造成的伤害提升,当血量降至10%以下时,BOSS攻击力再次提升。

3.2 玩家属性的全程使用

在RPG游戏中,玩家的属性在各个游戏环节中均要用到,因此这一大属性的传递是游戏设计过程中的一大重点。

在本游戏中,玩家游戏属性通过一个类对象来存储,而该类对象在第一次开始游戏时初始化,在以后则使用该对象的值进行各游戏功能。在这个过程中,如何在各个窗体之间传递该类对象值则是重中之重。在本游戏中,玩家属性通过QVariant包装,然后通过信号触发SLOT槽函数,将该包装属性传递给下一子窗体,从而实现了类对象的不同窗体间的传递功能。

具体算法如下:

首先对类对象做一个宏定义

Q_DECLARE_METATYPE(person)

接着在窗口构造函数中创建子窗口对象的一个指针变量,然后通过connect函数链接

 area =new area_prairie(this);
 connect(this, SIGNAL(send_data(QVariant)), area, SLOT(setvalue(QVariant))); // send the message of player to area_prairie

然后在对应窗口跳转功能处发送信号

QVariant variance;
variance.setValue(Player);
emit send_data(variance);//发出信号

接着在子窗口处接受该variance包装,接受函数为connect函数参数内的SLOT函数(定义在子窗体)。

void area_prairie::setvalue(QVariant data)
{
    person player ;
    player = data.value();
}

如上便完成了类对象在不同窗体间的传递。而子窗体要将数据传回父窗体算法也大致相同,只是大部分定义需在父窗体定义,如connect函数如下:

connect(area, SIGNAL(send_data(QVariant)),this,SLOT(setvalue(QVariant)) );  //receive the message of player from area_prairie

send_data信号在子窗口定义,SLOT函数在父窗口定义,如法炮制即可。

你可能感兴趣的:(游戏开发)