最近有一个卡牌游戏的创意,打算用Unity把Demo实现出来练练手。我尽量尝试每天记录一下开发的进度。
打算在这里主要记录游戏设计和开发的过程,作为自己的一个摸索的记录。
虽然只有一个人在做,但还是打算用git来做一下版本控制,毕竟回退之类的相当方便
https://github.com/LouisHuangGT/Yggdrasills-dream

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

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

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

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

Created with Raphaël 2.1.2 玩家回合开始 选择一个单位 AP是否耗完 End 弹出菜单,选择这个单位的动作 执行动作 动作是否执行完成? yes no yes no

之后是回合间的流程

Created with Raphaël 2.1.2 游戏开始 玩家回合 玩家回合结束? 敌方回合 敌人回合结束? 循环,直到达到胜利条件 yes no yes no

这个流程我们把它拆成两块来实现。首先一个全局的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;elsereturn null;}elsereturn null;}elsereturn 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;elsereturn false;}

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

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

一个卡牌游戏的DEMO(0)相关推荐

  1. EUI卡牌游戏的制作全过程

    转载自:https://bbs.egret.com/forum.php?mod=viewthread&tid=50009&highlight=%E5%8D%A1%E7%89%8C 为了 ...

  2. 天池 在线编程 卡牌游戏(01背包)

    文章目录 1. 题目 2. 解题 1. 题目 你跟你的朋友在玩一个卡牌游戏,总共有 n 张牌. 每张牌的成本为 cost[i] 并且可以对对手造成 damage[i] 的伤害. 你总共有 totalM ...

  3. [省选联考 2020 B 卷] 卡牌游戏 题解c++

    看到这题,真的忒简单啊! 咳咳,开个玩笑.关于这题: 题目描述 轩轩某天想到了一个卡牌游戏,游戏规则如下: 初始时轩轩的手中有自左向右排成一排的 n 张卡牌,每张卡牌上有一个整数分值. 接下来,轩轩每 ...

  4. SPS | 卡牌游戏Splinterlands,你也可以达到最强王者

    那些最好的买卖,刚开始的时候,从数字上看,几乎都会告诉你不要买.--沃伦·巴菲特 现在的链游,概念预售为多,真正能玩的少.不少项目,游戏还没做出来,就开始炒预期,或者收一笔不少的入场费. 我今天想跟大 ...

  5. 《刀塔传奇》最初不是卡牌游戏——专访龙图COO王彦直

    http://game.donews.com/201407/2814031.shtm "最早是以投资商的身份去合作,后来又转换成发行商的身份去合作." 6月28日,<刀塔传奇 ...

  6. CCF201612-5 卡牌游戏(募集解题代码)

    试题编号: 201612-5 试题名称: 卡牌游戏 时间限制: 3.0s 内存限制: 256.0MB 问题描述: 问题描述 小Q和小M是游戏数值策划师,他们最近在测试自己新设计的卡牌对战游戏.游戏总共 ...

  7. 算法题 - 卡牌游戏问题 - Python

    问题描述: 卡牌游戏问题   小a和小b玩一个游戏,有 n张卡牌,每张上面有两个正整数 x, y.取一张牌时,个人积分增加 x,团队积分增加 y.求小a,小b各取若干张牌,使得他们的 个人积分相等,且 ...

  8. java卡牌游戏详解

    代码如下: package zxc;//文件夹名称 import java.awt.*; import java.awt.event.ActionEvent; import java.awt.even ...

  9. 基于QT开发的开源局域网联机UNO卡牌游戏报告(附github仓库地址)

    源代码: https://github.com/yunwei37/UNO-game-oop 目录 1. 需求分析 1.1. UNO卡牌游戏的基本功能 1.2. UNO卡牌游戏的规则 2. 总体设计 3 ...

最新文章

  1. 公司终于决定放弃微服务传统设计模式,全面拥抱 DDD!
  2. java mina多线程_Java多线程基础总结九:Mina窥探(1)
  3. Github标星2w+,热榜第一,如何用Python实现所有算法
  4. performance and scalability
  5. Facebook 最新可佩戴 AR 设备、AR 设备未来五年市场扩张、语音社交新创Swell等|Decode the Week...
  6. Iphone4信号,苹果象个被惯坏的孩子
  7. c语言入门敲打,C语言基础三(敲打键盘、寻找资料,循环语句)
  8. 仅需6道题轻松掌握Python异常捕获 | Python技能树征题
  9. 豆丁 道客巴巴 千图网 千库网 包图网 我图网 摄图网 巧办网 万方设计 中国知网 VIP会员一个月开通方法,十网通用
  10. 十大简单排序:桶排序
  11. 计算机休眠模式是关机吗,电脑中的待机、休眠、睡眠和关机状态的区别。
  12. edge搁置标签页_如何自定义Microsoft Edge的新标签页
  13. java数字转汉字大写(全)
  14. 关于斐讯K2无管理员密码路由器重置问题
  15. c++中字符数组与字符串的转换
  16. 科研 | 国家自然科学基金委 | 资助项目简介
  17. 【181018】基于MFC文档方式制作的飞碟射击游戏
  18. HTML七种加密解密
  19. ubuntu系统matlab2021a安装及设置matlab快捷方式
  20. 张宇1000题线性代数 第一、二章 行列式、余子式和代数余子式的计算

热门文章

  1. 数据科学家必须符合道德吗
  2. 初入深度学习1——如何下载与打开一个Github深度学习库
  3. Oracle FIND_IN_SET函数
  4. css 字间距离_css 字体字符间距设置
  5. 《原神》鸣声水位岛屿解密方法介绍
  6. div居中方法(共8种)
  7. 【实时数仓】DWS层的定位、DWS层之访客主题计算(PV、UV、跳出次数、计入页面数、连续访问时长)
  8. 20181018杂谈——身体是革命的本钱
  9. 关于Adaboos选择最优弱分类器过程的理解
  10. 安卓 线框_草绘基于网格的线框的最佳资源