【 Cocos Creator 项目实战】益智游戏《2048》(附带完整源码工程)

本文乃Siliphen原创,转载请注明出处

目录

游戏介绍

概述

游戏整体流程

游戏框架设计

主要流程控制类

本文项目的代码组织结构

构建游戏世界

数字方块

地图

 触摸手势识别

防触摸抖动

判断用户输入的方向

地图

任意大小的地图

初始化地图大小

地图绘制

合并和移动

合并和移动的逻辑

丝滑的合并和移动动画

本文的完整实现源码工程


游戏介绍

《2048》是一款曾经风靡全球的数字益智游戏。

目前(2023.08.14)在 App Store 的情况如下图:

关于这个游戏的更多情况可看看百度百科:百度百科-验证

概述

本文讲解用 Cocos Creator 实现经典《2048》的核心流程和算法。

Cocos Creator 版本:Cocos Creator 3.8.0

本文实现的游戏效果如下:

 

可以随意调整地图大小。可随意调整方块移动速度。

上图分别演示了 4 x 4 ,7 x 10 地图大小的效果。

可在这个地址运行体验下本文实现的版本:Cocos Creator | 2048

文本末尾给出完整实现的源码工程。

游戏整体流程

游戏执行一轮玩家操作的流程:等待玩家输入操作 -> 用户滑动屏幕 -> 移动数字方块 -> 合并方块 -> 空白地方随机出现一个数字方块 -> 等待玩家输入操作

以上流程是游戏玩家操作一次,游戏执行一轮的分解动作循环。

游戏通关条件:合成数字方块2048。

游戏失败条件:当整个棋盘都填满数字方块,且没有可以合并的方块。

游戏框架设计

主要流程控制类

从调用先后顺序开始依次如下:

类名

作用

UiTouch

处理用户触摸输入

Merge

处理移动、合并的逻辑和动画。

FlowRound.fillEntity()

在地图空白处随机生成一个数字方块。

FlowRound.judge()

判断输赢。

本文项目的代码组织结构

构建游戏世界

《2048》的游戏世界只有2个实体:数字方块、棋盘地图。

棋盘是数字方块的容器。后面的移动和合并算法,都是作用在棋盘上计算的。

数字方块

// 实体
export class Entity {// 实体所代表的数值public val : number ;// 表现public presentation = new EntityPresentation() ;}// 实体表现
export class EntityPresentation {public root : Node ;}

地图

地图数据本质是个二维数组。定义如下:

export class Map {// 单件public static ins : Map = null ;// 地图单元格public grid = new Array< Array< MapCell > >() ;// 格子宽高public size = new Size() ; // 表现public presentation = new MapPresentation() ;}// 地图表现
export class MapPresentation {// 根节点public root : Node ;}// 地图单元格
export class MapCell {// 单元格上的实体public entity : Entity = null ;// 单元格所在的局部空间的坐标public pos : Vec3 = null ;}

我们规定地图单元格(0,0)的位置在地图显示的左下角。x , y 的增长分别向右边和上边延伸。如下图:

 触摸手势识别

防触摸抖动

在触摸按下时记录按下的坐标,在触摸结束时用结束时的坐标减去按下时的坐标,得到一个向量。

判断这个向量的长度,大于某个数值后,就认为是有效的输入。

如果只是个很小的滑动,可能是抖动造成的,为了防止玩家误操作,可以丢弃这种输入。

判断用户输入的方向

用上一步减法得到的向量就可以判断用户操作的方向。

主要是用到 Math.atan2 这个系统函数。atan2 判断一个向量与 x 轴正方向的夹角,单位是弧度。

注意:atan2 的参数是 ( y , x ) , 不是( x , y ),y 是第一个参数。

不习惯使用弧度的话,可以转换成角度。

判断角度代码如下:

// 手势识别
export class GestureRecognition {// 返回:上左下右 1234 从上开始顺时针。0 无效方向public static exe( v : Vec2 ) : number {let rad = Math.atan2( v.y , v.x ) ;let degree = rad * ( 180 / Math.PI ) ;if( 45 < degree && degree < 135 ){return 1 ;} else if( -45 < degree && degree < 45  ){return 2 ;} else if( -135 < degree && degree < -45 ){return 3 ;}else if( 135 < degree && degree < 180 || -180 < degree && degree < -135 ){return 4 ;}// console.log( "度数:" + degree ) ;return 0 ;}}

地图

任意大小的地图

本文的实现,可设置任意地图大小。

如下图:

上图展示了这些尺寸的地图大小效果:3 x 3 , 5 x 5 , 6 x 4 , 7 x 10

不同地图尺寸对应不同的地图根结点缩放值。

要实现可指定任意大小的地图的前提是,动态绘制地图。

先初始化地图二维数组结构的大小,然后,地图绘制类再处理地图的绘制。

初始化地图大小

// 地图数据初始化
export class MapInit {public static exe( map : Map ) {map.presentation.root = find( "Canvas/Map" ) ;// 地图宽高let mapWidth = 3 ; let mapHeight = 3 ; map.size = new Size( mapWidth , mapHeight ) ;for( let y = 0 ; y < mapHeight ; ++y ) {let row = new Array< MapCell >( ) ;map.grid.push(row) ;for( let x = 0 ; x < mapWidth ; ++x ){let cell = new MapCell() ; row.push( cell ) ;} // end for} // end for}}

地图绘制

本文实现的中心对其的地图布局,地图的几何中心点与其父节点的原点重叠。

算法是,先算出整个地图的大小,然后宽高分别除以2,先算出 ( 0 , 0 ) 起始逻辑坐标单元格的位置。

先算出左下角的起始单元格的位置,后续可以统一处理其他单元格位置。仅仅是通过不断累加间隔就行。

地图绘制 具体实现查看源码工程的类 MapDraw

设置地图大小位置:MapInit.exe 函数

合并和移动

这个是2048的核心玩法实现,也是最难的部分。

合并和移动的逻辑

可以先算方块逻辑上的合并,后算方块逻辑上的移动。

也可以合并和移动合并在一起计算。

上下左右的合并和移动要分别处理。

这里列举用户向左( <- )滑动的处理算法,其他3个方向的以此类推。为了说明原理和简单起见以下为描述性伪代码。

// 一行行遍历地图。从左到右(->)
for( let y = 0 ; y < map.size.height ; ++y ) {for( let x = 0 ; x < map.size.width ; ++x ) {let cell = map.grid[ y ][ x ] ;// 如果单元格上没有实体,略过。因为我们只处理实体。不处理空格。if( cell.entity == null ) continue ;let cell2 = 向右(->)查找一个最近的实体所在的单元格。if( cell2 != null && cell2 和 cell 的实体数字相同 ){   // 这表示找到一个可以合并的实体2个实体合并,合并和的实体放在 cell 单元格的位置上。}以 cell 单元格为起点向左(<-)查找一个连续的空位的最右边的那个空位这个空位便是 cell 上的方块实体要移动到的位置。} // end for
} // end for

算法图示:

丝滑的合并和移动动画

如果只是按照上一步说的先在逻辑上计算合并和移动的结果,然后直接更新画面显示,会显得很生硬。

大部分的瞬间更新结果都会让画面显得生硬。好的做法是,有个滑动和合并的移动缓动动画。

加入动画后,流程就变成了:

所有的方块都会先移动到一边,然后进行合并,如果合并后留出了空位,需要再移动。保证移动后,中间不留空位。

这个流程需要对以上的逻辑处理进行改造。

具体实现查看源码工程的类 Merge

本文的完整实现源码工程

源码工程下载地址:Cocos Store

作者创作不易,您的支持让我创造出更多更好的作品。​:)

【 Cocos Creator 项目实战】系列文章链接:

【 Cocos Creator 项目实战】益智游戏《2048》

​​​​​​【Cocos Creator 项目实战 】消灭星星加强版

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/42453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无涯教程-Perl - sysread函数

描述 该函数等效于C /操作系统函数read(),因为它绕过了诸如print,read和seek之类的函数所采用的缓冲系统,它仅应与相应的syswrite和sysseek函数一起使用。 它从FILEHANDLE中读取LENGTH个字节,并将输出放入SCALAR中。如果指定了OFFSET,则将数据从OFFSET字节写入SCALAR,从而有效…

IC流程中 DFT 学习笔记(2)

引言 DFT是ASIC芯片设计流程中不可或缺的环节。其主要目的是在芯片前端设计验证完成后插入一些诸如寄存器链等可供测试的逻辑&#xff0c;算是IC后端设计的范畴&#xff0c;属于结构测试而非功能测试。主要是在ASIC芯片流片完成后&#xff0c;通过这些已插入的逻辑&#xff0c…

手机照片误删怎么办,电脑照片误删怎么办怎么才能找回,EasyRecovery来帮您

手机照片误删怎么办&#xff0c;电脑照片误删怎么办怎么才能找回&#xff0c;EasyRecovery 2023来帮您&#xff01;&#xff01;&#xff01; EasyRecovery 2023是一款操作安全、价格便宜、用户自主操作的 数据恢复 方案&#xff0c;它支持从各种各样的 存储介质 恢复删除 或者…

Vue3.X 创建简单项目

一、环境安装与检查 首先&#xff0c;我们要确保我们安装了构建vue框架的环境&#xff0c;不会安装的请自行百度&#xff0c;有很多安装教程。检查环境 node -v # 如果没有安装nodejs请安装&#xff0c;安装教程自行百度 vue -V# 没有安装&#xff0c;请执行npm install -g v…

TCP服务器实现—多进程版,多线程版,线程池版

目录 前言 1.存在的问题 2.多进程版 3.多线程版 4.线程池版 总结 前言 在上一篇文章中使用TCP协议实现了一个简单的服务器&#xff0c;可以用来服务端和客户端通信&#xff0c;但是之前的服务器存在一个问题&#xff0c;就是当有多个客户端连接服务器的时候&#xff0c;服…

002-Spring boot 自动配置相关分析

目录 自动配置 EnableAutoConfiguration开启自动配置读取配置提前过滤自动配置配置包 AutoConfigurationPackage 自动配置 EnableAutoConfiguration 开启自动配置 在Spring 启动类上的 SpringBootApplication 中有 EnableAutoConfiguration 读取配置 Import(AutoConfigurat…

musl libc ldso 动态加载研究笔记:01

前言 musl 是一个轻量级的标准C库&#xff0c;建立在系统调用之上&#xff0c;可以认为是【用户态】的C 库&#xff0c;与 glibc 或者 uClibc 属于同一类。 基于 musl 的 gcc 工具链包括交叉编译工具链&#xff0c;可以用于编译 Linux 或者其他的操作系统&#xff0c;如当前 L…

构建可远程访问的企业内部论坛

文章目录 前言1.cpolar、PHPStudy2.Discuz3.打开PHPStudy&#xff0c;安装网页论坛所需软件4.进行网页运行环境的构建5.运行Discuz网页程序6.使用cpolar建立穿透内网的数据隧道&#xff0c;发布到公网7.对云端保留的空白数据隧道进行配置8.Discuz论坛搭建完毕 前言 企业在发展…

Python中import模块导入的实现原理

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 Python中import模块导入的实现原理 什么是模块import搜索路径import导入模块的原理图书推荐 专栏&…

京东门详一码多端探索与实践 | 京东云技术团队

本文主要讲述京东门详业务在支撑过程中遇到的困境&#xff0c;面对问题我们在效率提升、质量保障等方向的探索和实践&#xff0c;在此将实践过程中问题解决的思路和方案与大家一起分享&#xff0c;也希望能给大家带来一些新的启发 一、背景 1.1、京东门详介绍 1.1.1、京东门…

数据的深海潜行:数据湖、数据仓库与数据湖库之间的微妙关系

导言&#xff1a;数据的重要性与存储挑战 在这个信息爆炸的时代&#xff0c;数据已经成为企业的核心资产&#xff0c;而如何高效、安全、便捷地存储这些数据&#xff0c;更是每个组织面临的重大挑战。 数据作为组织的核心资产 数据在过去的几十年里从一个辅助工具演变成企业的…

Ubuntu 20.04(服务器版)安装 Anaconda

0、Anaconda介绍 Anaconda是一个开源的Python发行版本&#xff0c;包含了包括Python、Conda、科学计算库等180多个科学包及其依赖项。因此&#xff0c;安装了Anaconda就不用再单独安装CUDA、Python等。 CUDA&#xff0c;在进行深度学习的时候&#xff0c;需要用到GPU&#xf…

操作符详解上(非常详细)

目录 二进制介绍二进制2进制转10进制10进制转2进制数字2进制转8进制和16进制2进制转8进制2进制转16进制 原码、反码、补码移位操作符左移操作符右移操作符 位操作符&#xff1a;&、|、^逗号表达式 二进制介绍 在初学计算机时我们常常会听到2进制、8进制、10进制、16进制……

C++中String的语法及常用接口用法

在C语言中&#xff0c;string是一个标准库类&#xff08;class&#xff09;&#xff0c;用于处理字符串&#xff0c;它提供了一种更高级、更便捷的字符串操作方式&#xff0c;string 类提供了一系列成员函数和重载运算符&#xff0c;以便于对字符串进行操作和处理。 一、string…

Redis高可用:主从复制详解

目录 1.什么是主从复制&#xff1f; 2.优势 3.主从复制的原理 4.全量复制和增量复制 4.1 全量复制 4.2 增量复制 5.相关问题总结 5.1 当主服务器不进行持久化时复制的安全性 5.2 为什么主从全量复制使用RDB而不使用AOF&#xff1f; 5.3 为什么还有无磁盘复制模式&#xff…

C# 一种求平方根的方法 立方根也可以 极大 极小都可以

不知道研究这些干啥&#xff0c;纯纯的浪费时间。。。 public static double TQSquare(double number){Random random1 new Random(DateTime.Now.Millisecond);double x1 0, resultX1 0, diff 9999999999, diffTemporary 0;for (int i 0; i < 654321; i){if (random1…

怎么做Tik Tok海外娱乐公会呢?新加坡市场怎么样?

一、为什么选择TikTok直播 1. 海外市场潜力巨大 • 自2016年始&#xff0c;多家直播平台陆续拓展至东南亚、中东、俄罗斯、日韩、欧美、拉美等地区。 • 海外市场作为直播发展新蓝海&#xff0c;2021年直播行业整申请cmxyci体规模达百亿美元&#xff0c;并维持高速增长。 &a…

C++初阶语法——内部类

前言&#xff1a;内部类&#xff0c;顾名思义是定义在类中的类&#xff0c;许多人会以为它属于外部的类&#xff0c;实际上并不是&#xff0c;它们是两个独立的类&#xff0c;但是内部类受外部类类域的限制。 目录 一.概念二.特性1.内部类和外部类相互独立2.内部类是外部类的友…

Git多版本并行开发实践

本文目的&#xff1a; 实现多个项目同时进行的git多版本管理工作流。 名词解释&#xff1a; feature-XXXX&#xff1a;特性分支指CCS中一个项目或者一个迭代&#xff0c;在该分支上开发&#xff0c;完成后&#xff0c;合并&#xff0c;最后&#xff0c;删除该分支&#xff0c;…

【广州虚拟现实开发】VR智能中控系统进一步提高VR教学管理水平

随着科技的不断发展&#xff0c;虚拟现实(VR)技术已经逐渐走进了人们的生活。在教育领域&#xff0c;VR技术也得到了广泛的应用&#xff0c;尤其是在教学终端中控系统方面。那么&#xff0c;广州华锐互动开发的VR智能中控系统对学校有何益处呢&#xff1f; 首先&#xff0c;VR智…