毕业论文写作

毕业设计需求

计算机毕业设计中设计一个卡牌游戏

          这个游戏类似于卡牌游戏和类《神界:原罪》的回合制RPG结合。玩家扮演一个召唤师,可以将随从召唤到战场上(类似炉石和万智牌),而在战场上则遵循回合制战棋游戏的规则。玩家每个回合的资源由Action Point决定。做任何的动作:移动随从,攻击、打出卡牌都会消耗Action Point,因此玩家必须合理的规划自己的Action Point来进行对战。

此外,我们的Action Point不像炉石或万智牌一样每回合增长,而更像战场女武神,每一个玩家召唤的强力角色(例如一个英雄单位)都会提高总的Action Point。为了增加趣味性,还为每个队伍增加一个Magic Point资源,玩家作为召唤师,召唤到战场上的随从是靠法力进行维持的,因此在战场上的每一个单位都会占用一定的Magic Point,玩家需要规划自己召唤出的随从:例如可以召唤一个强力的随从,但这会占用全部的MP;也可以召唤许多脆弱的随从。游戏设计上大致就是这样。一些具体的细节规则我还在进行调整。

       可以看到,从实现的角度来看,我们主要要开发两套系统:一个战棋类回合制RPG和一个卡牌系统。两者其实耦合程度很低,完全可以分开来进行实现。我打算先从比较核心的战棋类回合制游戏入手。

        在写代码之前我们先分析一遍战棋类回合制RPG的战斗流程:
        首先是回合内的流程:

之后是回合间的流程

       这个流程我们把它拆成两块来实现。首先一个全局的TurnManager负责管理回合的进行:例如回合的切换等,这个类也负责用鼠标选取的方式生成一个controllingUnit,使得玩家可以对其进行操作。即第一张流程图到选取单位这个部分的内容在TurnManager中实现。而对于单个单位的操作可以抽象出来,由一个controller来进行。controller负责接收按钮的回调,确定玩家下的指令,并分配当前这个controller正在操作的unit来执行这个指令。Controller主要通过一个Run函数进行实现,这个函数输入一个选中的单位,然后对这个单位进行一系列的玩家操作。返回操作是否成功/完成。如果操作成功则进入下一个选单位流程,否则不做任何操作,继续这个操作(如流程图1所示)。

       玩家的单位目前用一个基类Unit来处理,玩家的具体操作以及一系列的判定就在unit中进行实现。

       首先是TurnManager的update()实现:
       整个游戏进程的执行相当于全部在这个update中实现。这个update的作用相当于选中单位和对应的操作后等待操作完成,操作完成后选下一个单位,如果没有完成则阻塞等待操作完成(这里的阻塞利用了update每帧循环调用的特性来实现,不需要自己写一个死循环来阻塞)

void Update () {
if (selectedUnit != null)
{
if (controller.run(selectedUnit))
{
team[currenTeamIndex].ActionPoint--;
selectedUnit = selectUnit();
}
//选中一个单位,把它放到controller进行操作,并返回一个操作是否完成的布尔值。
//如果操作完成,那么这个队伍的AP减少1,并选一个新的单位
//如果操作还没完成,那么不做任何事情,下一帧继续这个操作
}
if (team[currenTeamIndex].ActionPoint <= 0)
{
team[currenTeamIndex].ActionPoint = team[currenTeamIndex].maxActionPoint;
currenTeamIndex = 1 - currenTeamIndex;
}
//当一个队伍的AP小于等于0时,我们重置这个队伍的AP并将当前的控制权转移到另一支队伍上面(即改变当前索引值)
}

其中的SelectUnit函数实现比较简单,目前用了一个鼠标raycast的方法来选中对应物体

GameObject selectUnit()
{
if (Input.GetMouseButtonUp(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;

if (Physics.Raycast(ray, out hit))
{
if (isIn(hit.transform.gameObject, team[currenTeamIndex].units))
//判断选中的这个单位是不是在(isIn)当前的队伍列表中,只有选中当前队伍的单位才返回
return hit.transform.gameObject;
else
return null;
}
else
return null;
}
else
return null;
}

有了TurnManager以后,我们就可以开始实现Controller里面的Run函数。这个函数负责给selectedUnit分配一个操作,并执行。

public bool run(GameObject selectedUnit)
{
controllerMenu.SetActive(true);
Unit unit = selectedUnit.GetComponent<Unit>();

bool result = false;
switch (currentState)
{
case State.IDLE:
result = false;
break;
case State.MOVE:
result = unit.Move();
break;
case State.ATTACK:
result = unit.Attack();
break;
case State.SKILL:
result = unit.Cast();
break;
case State.SUMMON:
result = unit.Summon();
break;
default:
result = false;
break;
}
if (result == true)
{
currentState = State.IDLE;
controllerMenu.SetActive(false);
}
return result;
}

目前暂定有四种操作:移动、攻击、使用技能(一些随从有主动技能)和召唤(即使用卡牌)。在unit类中进行具体实现。
其中currentState由四个按钮的回调函数来设置对应的值,例如按下Move按钮对应的值就是State.MOVE。最后这个函数需要返回一个执行的结果,如果进行了操作,那么返回操作的结果,如果没有按下任何按钮(没有输入,即IDLE状态),则返回false。

最后,在Unit类中,实现了一个移动的功能

 public bool Move()
{
if (Input.GetMouseButtonUp(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;

if (Physics.Raycast(ray, out hit))
{
agent.SetDestination(hit.point);
}
}
if (agent.remainingDistance < agent.radius && agent.hasPath)
return true;
else
return false;
}

一个比较简单的点击地面移动的实现。每次执行的时候检测是否有鼠标按键抬起,如果有则射一道光束到地面,并用NavMeshAgent将当前单位移动过去。设置完目的地后判断一下剩余距离是否小于agent的半径,如果是的说明到达目的地,返回true说明操作结束,可以进行下一个单位的选择和操作;如果没有,说明操作没有结束,返回false,下次update继续这个操作。
这边的实现其实会有一点bug,如果选择move以后在到达目的地前不停点击鼠标会使单位不停的重新定向,可以考虑在input里面加一个flag使得在到达目的地前只能接受一次鼠标的输入。另外在移动过程中我个人倾向于还是需要把菜单暂时关闭,这个需要调整一下controller中的实现。
代码写完以后场景就比较好处理了。我做了一个贼简单的场景,其中蓝色方块是己方单位,红色方块是敌方单位。选中效果还没有加上,但目前已经可以接近回合制式的移动各个单位了。

今天基本上把回合制的框架搭了个七七八八,下面可以往里面填unit中的几个操作的实现了。下面一个比较麻烦是一套RPG系统,例如实现血量、攻击等等机制。另外ActionPoint这个机制也要做更复杂的实现,每一个技能、每一个动作都应该有一个自己消耗的ActionPoint。最后,其实这样去实现一个回合制的流程动作应该还有不少bug,还要等后面慢慢进行重构。

最新毕业设计成品

版权所有© 帮我毕业网 并保留所有权利

QQ 1370405256 微信 biyebang

QQ:629001810微信:biyebang

收缩