2.5D游戏,角色移动限制方法。不用空气墙。

news2025/4/12 17:47:08

有一个项目,2.5D视角。角色在设定好的路线上自由移动,不能超出路线。

之前的做法是用空气墙,设定物理碰撞,然后角色移动。

我感觉这种做法性能有点低。手机上体验平均帧时是4ms

于是想用空间换时间,将可能的运算进行预处理,然后在运算的时候,只对部分数据进行运算以提升效率。

这个目前还在初始阶段,已经完成了移动。还未考虑到后续逻辑,不过应该没问题的。 

效果如下 

 实现思路

因为所有路线都是直线条,所以只要知道了两个点的坐标,然后基于基础菱形块的尺寸就可以算出两个块组成的一个多边形。然后在移动的时候,判断白块位置是否在这个多边形里,如果不在则不移动。

具体实现

地图节点编辑

地图里的数据,主要就是路线上的端点和拐点。所以在地图设计好了以后,就对场景里的端点和拐点创建一个节点。

节点数据初始化

创建这些节点的目的是用来组合出多边形。多边形组合如下图所示:

从图中可以看出,每一个单元,左、上、右、下都有可能会有一个相邻单元。距离可能不同。

对于我的地图,最多也只能会有4个相邻单元。

所以,可以组合出5个凸多边形。如下图所示:

 1,2,3,4个平行四边形和中间的一个菱形。

那么怎么确定,每个菱形单元附近是哪些单元呢?我用的是有意义的节点命名。比如cell_x_a_b_c_d。其中x代表了这个单元的id,后面的a、b、c、d代表了按照左上右下的顺序排布的相邻节点的id。节点管理起的作用就是用来初始化这些数据。用一个数组管理所有单元,到时候用id就可以直接拿到对应的单元数据。每一个单元数据包含了坐标,相邻单元id和单元的5个多边形。

cocos creator代码如下:

//定义数组用于存储所有单元    
private readonly worldCellsArray: Cell[] = [];
//初始化所有单元
private initWorldCellsArray() {
        for (let cellNode of this.node.children) {
            const [curCellId, ...nearCells] = cellNode.name
                .replace('cell_', '')
                .split('_')
                .map(v => Number(v));
            this.worldCellsArray.push({
                node: cellNode,
                nearCellsIdArray: nearCells,
                zoonPolygon: []
            });
        }
}
//初始化所有单元的多边形,最多5个,最少也有2个。
    private initWorldCellsPolygon() {
        const halfCellWidth = this.cellWidth / 2;
        const halfCellHeight = this.cellHeight / 2;
        this.worldCellsArray.forEach(cell => {
            const { x, y } = cell.node.position;
            cell.zoonPolygon.push([
                x - halfCellWidth,
                y,
                x,
                y - halfCellHeight,
                x + halfCellWidth,
                y,
                x,
                y + halfCellHeight
            ]);
            for (let id of cell.nearCellsIdArray) {
                const nearCell = this.worldCellsArray[id - 1];
                if (nearCell) {
                    const { x: oX, y: oY } = nearCell.node.position;
                    if (oX < x && oY < y) {
                        //left bottom
                        cell.zoonPolygon.push([
                            oX - halfCellWidth,
                            oY,
                            oX,
                            oY - halfCellHeight,
                            x,
                            y - halfCellHeight,
                            x - halfCellWidth,
                            y
                        ]);
                    } else if (oX < x && oY > y) {
                        //left top
                        cell.zoonPolygon.push([
                            oX,
                            oY + halfCellHeight,
                            oX - halfCellWidth,
                            oY,
                            x - halfCellWidth,
                            y,
                            x,
                            y + halfCellHeight
                        ]);
                    } else if (oX > x && oY > y) {
                        //right top
                        cell.zoonPolygon.push([
                            oX,
                            oY + halfCellHeight,
                            x,
                            y + halfCellHeight,
                            x + halfCellWidth,
                            y,
                            oX + halfCellWidth,
                            oY
                        ]);
                    } else if (oX > x && oY < y) {
                        //right bottom
                        cell.zoonPolygon.push([
                            x,
                            y + halfCellHeight,
                            x - halfCellWidth,
                            y,
                            oX,
                            oY - halfCellHeight,
                            oX + halfCellWidth,
                            oY
                        ]);
                    }
                }
            }
        });
    }

移动管理

当角色移动的时候,就拿到角色当前的单元id的多边形,挨个和5个多边形比较。但凡和点在一个多边形内,则返回正确,可以继续移动。并且把在哪个多边形同时也返回回去。就可以一直进行判断了。

代码如下:

    private readonly backObj: [boolean, number] = [false, 0];
    public judgeIsInCellZoonAndGetCurCellId(cellId: number, judgeVec2: Vec2) {
        const cell = this.worldCellsArray[cellId - 1];
        this.backObj[0] = false;
        this.backObj[1] = cellId;
        if (!cell) return this.backObj;
        for (let polygonIndex = 0; polygonIndex < cell.zoonPolygon.length; polygonIndex++) {
            const polygon = cell.zoonPolygon[polygonIndex];
            for (let vec2Index = 0; vec2Index < this.toolVec2Pool.length; vec2Index++) {
                this.toolVec2Pool[vec2Index].set(polygon[vec2Index * 2], polygon[vec2Index * 2 + 1]);
            }
            const isIn = Intersection2D.pointInPolygon(judgeVec2, this.toolVec2Pool);
            if (isIn) {
                this.backObj[0] = true;
                if (polygonIndex) {
                    this.backObj[1] = cell.nearCellsIdArray[polygonIndex - 1];
                }
                break;
            }
        }
        return this.backObj;
    }

因为每次都只需要进行5个多边形的判断,所以性能比用物理碰撞好得多。最后的手机预览帧时为1.5ms。还是提升了很多的。

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

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

相关文章

chrome 如何下载网站在线预览PDF文件,保存到本地

爱学习的小伙伴肯定遇到过那种只能在线看&#xff0c;但并不提供下载的的PDF文件&#xff01; 但有时候想保存到本地有很费劲。今天准备了一个很简单的方法 以这个在线pdf为例 在线PDF文件 该如何把这个PDF保存到本地呢~ 方法 1.以chrome浏览器为例&#xff0c;打开准备好的示…

iOS运行时Runtime在OC中的应用场景

本篇将会总结Rutime的具体应用实例&#xff0c;结合其动态特性&#xff0c;Runtime在开发中的应用大致分为以下几个方面&#xff1a; 一、动态方法交换&#xff1a;Method Swizzling 实现动态方法交换(Method Swizzling )是Runtime中最具盛名的应用场景&#xff0c;其原理是&a…

SpringBoot2.0中MVC和WebFlux控制层Controller对比

本篇文章是SpringBoot2.0关于Controller控制层的对比&#xff0c;相信很多开发最好奇的也是这块。那么小编就带着大家一起先来看一下尝尝鲜,本篇文章比较短小精悍,只讲如何使用,至于原理剖析,后面会讲。阅读时间大概3分钟,现在开始! 文章目录一、演示目录结构二、演示启动类定义…

昨天阅读量900多

今日阅读量还不错的样子&#xff0c;也有900多了&#xff0c;

【C语言】函数递归详解

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​ &#x1f4e3;系列专栏&#xff1a;鹏哥带我学c带我飞 &#x1f4ac;总结&#xff1a;希望你看…

解析davinci快捷键配置文件

davinci resolve 是一款非线性影片剪辑软件&#xff0c;mac 下快捷键配置文件位于&#xff1a; lucaslucasdeMacBook-Pro DaVinci Resolve % pwd /Users/lucas/Library/Preferences/Blackmagic Design/DaVinci Resolve lucaslucasdeMacBook-Pro DaVinci Resolve % ll | grep k…

“滴灌”代替“漫灌”:“全链路增长”的百度联盟解

作者 | 曾响铃 文 | 响铃说 2021年时&#xff0c;在平台上的日均收益才不足1000元&#xff0c;日活不足1万&#xff1b; 一年时间不到&#xff0c;现在矩阵产品在平台的日均收入已经翻了90倍&#xff0c;日活翻了25倍。 这是一家白牌资讯媒体“早闻天下事”加入百度联盟后发…

跬智信息(Kyligence)荣获浦东新区人工智能创新应用大赛一等奖

近日&#xff0c;2022 浦东新区人工智能创新应用大赛圆满闭幕。经过层层筛选和考核&#xff0c;跬智信息&#xff08;Kyligence&#xff09;从 113 支团队中脱颖而出&#xff0c;参赛项目“Byzer 面向 DataAI 的低代码开源编程语言”在技术创新性、创意性以及项目的可落地性、可…

spi访问fpga

SPI 外设的三线/四线模式及时钟极性相位可以配置&#xff0c;支持主机/从机、全双工/半双工&#xff0c;传送数据格式可灵活配置&#xff0c;并且有发送空接收满 SPI 错误等中断事件功能配合应用使用&#xff0c;更多功能详见本系列芯片手册的相关章节。 SPI四线模式框图&…

轻松玩转树莓派Pico之五、FreeRTOS体验

树莓派Pico开发板片上主芯片为RP2040单片机&#xff0c;双核 Arm Cortex-M0 处理器&#xff0c;工作主频为133MHz&#xff0c;264K片上SRAM&#xff0c;和2MByteFlash。 这么大的RAM和Flash资源&#xff0c;不跑一下RTOS操作系统实在有些可惜&#xff0c;这次就先体验一下Fre…

基于新型战争策略优化算法的光伏模型优化(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f389;作者研究&#xff1a;&#x1f3c5;&#x1f3c5;&#x1f3c5;本科计算机专业&#xff0c;研究生电气学硕…

vscode通过插件一键运行 c++单元测试

gtest使用初探 简介: 本文在 ubuntu18.04 上实现了 googletest 的全局安装&#xff0c;并在一个 demo项目中演示了使用 cmake 引入了该库&#xff0c;实现了在命令行中运行 c 单元测试&#xff0c;包括运行单个 TEST 函数。另外通过 vscode 的插件 C TestMate&#xff0c; 实现…

MATLAB应用2——MATLAB串口采集加速度计数据

串口保存数据为txt格式&#xff1a; clc ; %死机的时候&#xff0c;在命令窗口输入return %getcominstrhwinfo (serial) %寻找串口 delete(instrfindall) %这句话必须有 global xx; global nn; global data1; global s; xx0; nn500; data1(1:nn)0; sserial(COM8); set(s,Bau…

什么?用Python实用脚本也能实现快速卡通画人物头像,这不就是妥妥的QQ秀嘛。

前言 今天我们就利用Python脚本实现天气查询应用吧。直接开整~ 思路分析 从大量照片/卡通数据中习得照片到卡通画的映射。 开发工具 python版本&#xff1a; 3.6 相关模块&#xff1a; pytorch 1.4 tensorflow-gpu 1.14 face-alignment dlib 1.数据准备 训练数据包括…

Linux入门—Shell常用命令之打包压缩

本文由【正厚软件】沙老师提供 打包压缩命令 1. gzip 命令 命令功能&#xff1a;压缩或展开文件 命令格式&#xff1a; ogzip [ -acdfhlLnNrtvV19 ] [-S 后缀] [ 文件名 ... ] &#xff1a;压缩文件 ogunzip [ -acfhlLnNrtvV ] [-S 后缀] [ 文件名 ... ] &#xff1a;解压缩文件…

离线安装harbor容器镜像仓库单机版(harbor-v2.3.5)

记录&#xff1a;358 场景&#xff1a;在CentOS 7.9操作系统上&#xff0c;离线部署harbor容器镜像仓库单机版&#xff0c;使用Redis为外部缓存、使用PostgreSQL为外部数据库、使用docker-ce操作容器、使用docker-compose操作harbor容器镜像仓库。 版本&#xff1a; 操作系统…

OpenAI chatGPT火爆出圈,世界悄悄发生着变化

OpenAI chatGPT火爆出圈&#xff0c;世界悄悄发生着变化一、为什么突然火起来了&#xff1f;二、ChatGPT功能实例2.1 [AI聊天](https://chat.openai.com/chat)2.2 [AI写新闻稿](https://chat.openai.com/chat)2.3 [AI写代码](https://chat.openai.com/chat)2.4 [AI写论文](http…

Kubernetes二进制单节点集群部署

Kubernetes二进制单节点集群部署 常见的K8S按照部署方式 ●Mini kube Minikube是一个工具&#xff0c;可以在本地快速运行一个单节点微型K8S&#xff0c;仅用于学习、预览K8S的一些特性使用部署地址&#xff1a; https://kubernetes.io/docs/setup/minikube ●Kubeadmin Kubea…

浅谈Kernel32.dll(Windows平台下必有的动态库文件)

今天听了前辈的黑客攻击的知识分享&#xff0c;里面比较基础的元素就是Kernel32.dll&#xff0c;我对它感兴趣好久了&#xff0c;今天搜集一些资料&#xff0c;有关Kernel32的。 目录 ​编辑 一、Kernel32介绍 二、Kernel32内存管理 三、引起Kernel32出错的主要元凶 四、解…

【求助帖】从技术转为项目经理后,如何快速进入角色?

近日&#xff0c;看到了一个求助贴&#xff0c;小李今年26岁&#xff0c;干了两年技术后&#xff0c;现在转行到项目经理的岗位。每天东奔西跑、天天加班还是感觉很吃力、工作也没有成效&#xff0c;想问下如何能快速进入角色&#xff1f; 那么小李的一天具体是怎么样的呢&…