当前位置: 首页 > news >正文

THREE练习写了几个简单小游戏的总结

THREE练习写了几个简单小游戏的总结

  • 象棋
    • 设计
      • 隔离
      • 订阅发布
      • 单例模式
      • 单一职责
    • 数据
    • 渲染
      • 填充棋子
      • 移动和吃子
      • 移动判断
      • 记录
      • 悔棋
    • 回放
    • 后续
  • 街道建设游戏
    • 我造的城市

看了一个国外大佬写的游戏教程,跟着做了下。
https://javascriptgametutorials.com/tutorials/three-js/crossy-road
又自己练习做了几个小游戏。感觉收获挺多的。

象棋

实现了人机对战,回放,悔棋等。虽然人机有点傻,后面慢慢改。
请添加图片描述
3D视角
在这里插入图片描述
在这里插入图片描述

设计

比着之前想感觉完成一个练习,这个练习我思考了一点。

隔离

渲染部分只负责渲染,通过修改数据来完成各种操作。

订阅发布

主类Game类负责初始化其他类以及事件传递。
在这里插入图片描述
EventBus为订阅发布类。
这里我给挂在到了window上。

单例模式

应该是单例模式?
画布,相机,配置项,资源加载器都设计为单例模式,为了方便操作,挂在到了global上,也可以挂在到别的地方或者不挂载。构建器变成私有的,通过init来初始化实例。如Renderer。其他类如Scene和Camera都类似。


export class Renderer {private static instance: Renderer;private renderer!: THREE.WebGLRenderer;constructor() {if (Renderer.instance) {return Renderer.instance;}this.renderer = genRenderer(this.getOptions());Renderer.instance = this;this.bindEvents();}public static init(): Renderer {if (!Renderer.instance) {Renderer.instance = new Renderer();}return Renderer.instance;}getCanvas() {return Options.getInstance().getCanvas();}getOptions() {return Options.getInstance().getOptions();}getRender() {return this.renderer;}public static getInstance(): Renderer {return Renderer.instance;}resize() {const canvas = this.getCanvas();this.renderer.setPixelRatio(window.devicePixelRatio);this.renderer.setSize(canvas.clientWidth, canvas.clientHeight);}private bindEvents() {window.$on(GameEvents.UpdateRender, () => {this.renderer.render(Scene.getInstance().getScene(),Camera.getInstance().getCamera());});window.$on(GameEvents.Resize, () => {this.resize();});}
}

各自负责各自的功能。

通过在主类Game里面注册使用。
在这里插入图片描述
比如渲染控制。
在这里插入图片描述

在这里插入图片描述

不在animate里面引入多个。
通过发布事件来传递渲染。
在这里插入图片描述
画布的渲染
在这里插入图片描述
还有窗口尺寸大小这个,这个我还没完善。
在Game类中绑定事件 发布窗口大小改变事件。
在这里插入图片描述
在这里插入图片描述

单一职责

我吹牛逼的,我也不知道是不是哈哈。

基本上所有的方法只处理自己的事情。
移动方法只负责交换数据,然后调用game的update方法,update方法,只负责渲染。

额外的,高亮标记也不是改变棋子的材质,全局只会有一个,直接丢到scene,大小为棋子的1.5倍,然后直接塞上去。看着像棋子高亮了就行。

数据

每个棋子的数据就是这个。

export interface XiangQiMetaDataItem {rowIndex: number;colIndex: number;type?: ChessPieceType;camp?: 'black' | 'red';
}

使用pinia来管理。
在这里插入图片描述
初始化数据,填充默认象棋棋盘。
在这里插入图片描述

渲染

方便读取坐标,写了一个XQGroup

export class XQGroup extends THREE.Group {rowIndex: number;colIndex: number;constructor(rowIndex: number, colIndex: number) {super();this.name = 'piece';this.rowIndex = rowIndex;this.colIndex = colIndex;}
}

每一个metadata的数据就会渲染出来一个XQGroup;

填充棋子

根据数据填充,象棋棋盘是8*9所以中心坐标为4.5,4
根据中心坐标来计算position。

在这里插入图片描述

棋子就是圆柱体加文字。

没有棋子的位置,填充的为
在这里插入图片描述
在这里插入图片描述
一个透明的圆柱体,和棋子大小一样,方便点击操作。

移动和吃子

移动的话,其实就是交换metadata的坐标数据。
比如车到对方的炮上。就是把炮对应的数据,改成车的。
而炮的也就不需要了。

比如车在metadata[1][2];
数据为{rowIndex:1,colIndex:2,type:‘车的那个’,camp:‘red’}

炮的为metadata[2][2];数据为{rowIndex:2,colIndex:2,type:‘炮的那个’,camp:‘black’}

车移动完后metadata[2][2];就变成了{rowIndex:2,colIndex:2,type:‘车的那个’,camp:‘red’}
而metadata[1][2];只需要保留坐标就行了。

移动判断

传入两个点的坐标数据来判断

在这里插入图片描述

炮的话只需要计算两点是否在一条直线上,以及两点之间的有type也就是有棋子的点的个数,大于一个就不能走,等于一个且目标点有棋子则可走,如果是0个那肯定可以走。

记录

通过记录每一步的交换的坐标点的数据,来记录下棋。
在这里插入图片描述

在这里插入图片描述
optionHistory就代表了步长。

悔棋

悔棋,通过操作metadata来完成。
前面记录了optionHistory,而optionHistory是从基础的metadata上走的每一步,可以通过metadata基础数据加optionHistory来还原。

在XiangQiGame类中完善。
在这里插入图片描述

在这里插入图片描述
pop移除最后两条数据,然后合并成最新的数据,就实现了悔棋。

回放

回放和上面的悔棋一样,悔棋是合并所有optionHistory后渲染,而回放是,每合并一条optionHistory的数据就渲染一次。如果做优化,也可以只渲染改变的坐标的棋子。

后续

基础版基本上完成了,除了人机还有点问题,权重没做好。
打算搞一个炫酷模型版的,把炮换成迫击炮,车换成坦克,将换成指挥部,士换成哨所,相换成卫队营区,卒子换成大兵,马换成步兵战车,然后炮吃子的时候,在炮原位置加上烟雾,在目标位置加上火,空中加一个飞线炮弹。

街道建设游戏

在象棋游戏之前的练习。

在这里插入图片描述

在这里插入图片描述
玩法很简单,资金买建筑,电厂建筑提供电,生产建筑挣钱,没电无法生产且屏幕变暗色。

有电了。

在这里插入图片描述
工厂会赚钱
在这里插入图片描述
有钱后可以打造自己喜欢的街道。
当前很少资源。

做象棋游戏之前这里思考了下职责分离。注册插件的那种形式。这里的建筑资源引入,就是统一格式。
在这里插入图片描述
在这里插入图片描述

我造的城市

真丑

在这里插入图片描述

在这里插入图片描述


文章转载自:

http://uIiMIwkK.wjqbr.cn
http://Wlu6knNH.wjqbr.cn
http://JoI9DCdM.wjqbr.cn
http://9lArYJGH.wjqbr.cn
http://1uo717pT.wjqbr.cn
http://XydKHBw9.wjqbr.cn
http://JDwUtNaB.wjqbr.cn
http://XSN0nNHz.wjqbr.cn
http://Aw2RxtCK.wjqbr.cn
http://NsPqnqY6.wjqbr.cn
http://WS0kLfhn.wjqbr.cn
http://A6nKxnnT.wjqbr.cn
http://TUEKEDRs.wjqbr.cn
http://jTD078Fs.wjqbr.cn
http://rp1omM87.wjqbr.cn
http://9GRE3g0V.wjqbr.cn
http://UI2iVSnX.wjqbr.cn
http://ZAOCZMYK.wjqbr.cn
http://We1FKizq.wjqbr.cn
http://03I0ygFI.wjqbr.cn
http://BipeCab1.wjqbr.cn
http://KEZxROy0.wjqbr.cn
http://NxwxI2Sa.wjqbr.cn
http://2toz73nw.wjqbr.cn
http://ucSpyB1S.wjqbr.cn
http://DMjFW7JU.wjqbr.cn
http://OffeRAT0.wjqbr.cn
http://6OQ1a7xw.wjqbr.cn
http://n2vDCYiD.wjqbr.cn
http://x0VjseCR.wjqbr.cn
http://www.dtcms.com/a/388034.html

相关文章:

  • Flume与Sqoop核心知识点总结:Hadoop生态的数据传输双引擎
  • 微服务spring cloud alibabab 启动报错: No spring.config.import set
  • 开心实习之第n天
  • 【系列文章】Linux系统中断的应用04-共享工作队列实验
  • Java的jdk21与 Go语言对比
  • 告别 MaaS 模型选型困难:AI Ping 为大模型服务选型提供精准性能评测排行榜
  • 41.OpenCV入门:计算机视觉的瑞士军刀
  • 初识golang
  • UE5 the “XXX“plugin was designed for build XXX,Attempt to load it anyway
  • docker快速安装环境
  • 如何安装TraeCN(字节跳动的IDE)使用AI IDE书写Vue3数据可视化大屏项目
  • Spark NLP: 最先进的自然语言处理和LLM库
  • 基于国产银河麒麟服务器SP3项目实战(Nginx+Keepalive)实现高可用负载均衡
  • 每日随机展示10个wordpress置顶文章
  • Leecode hot100 - 303. 区域和检索
  • 【审计试题案例】
  • 深度学习基础:线性回归与Softmax回归全面解析
  • C语言Prj03 运行显示乱码的解决方案
  • 车载操作系统总体技术要求解析
  • Spring Boot + MyBatis 实现站位标记系统实战
  • 读取X射线DICOM图像时需注意MONOCHROME1和PixelSpacing
  • mp4格式分析
  • LeetCode 1471.数组中的k个最强值
  • 基于R语言的水文、水环境模型优化技术及快速率定方法与多模型案例实践
  • python的守护线程设置
  • LTC5591IUH#TRPBF 无线和射频集成电路IC ADI亚德诺半导体 电子元器件解析
  • 【数据分享】土地利用shp数据分享-海南
  • 分布式拜占庭容错算法——PBFT算法深度解析
  • 《兔兔秘密花园》情人节密技曝光 输入隐藏指令即可
  • SQuAD:机器阅读理解领域的里程碑数据集