tilemap 菱形_【cocos3.x+tilemap】制作rpg小游戏(二)遮挡与碰撞

2023-10-31

前面制作了地图,现在就可以在工程中使用了。现在只实现了遮挡与碰撞,后续再实现点击屏幕移动、寻路算法、npc交互等。

实现遮挡与碰撞,都需要解决一个核心问题——当前角色到底在哪一块瓦片上,也就是cocos坐标如何转化为TileMap瓦片坐标,这个问题搞了n久,最后实现方法还是很麻烦,如果有人知道有更好的方式,请联系我^_^

一、坐标转换

其原理就在第一篇回答中,不过其最后一步转换是flash中通过取色来完成的,cocos中无法使用,就使用第二篇文章中的利用简单二元方程坐标系来判断点在线上还是线下来完成。

简单说一下原理就是:

如下图,将交错地图看做两个矩形网格覆盖在一起:

通过地图上一点的cocos坐标,可以知道点是在哪一个小的交叉矩形中:

通过判断点在线的上面还是在线的下面,来判断是在哪一个菱形中:

具体上代码:

1.小矩形中,两点确定一条直线y=ax+b,通过判断cx在线上对应点与cy的关系,来判断点与线的关系

//小矩形中,两点确定一条直线y=ax+b,通过判断cx在线上对应点与cy的关系,来判断点与线的关系

//return:0:线中,1:线下面,-1:线上面

int Map45Scene::getPosOfLine(float ax,float ay,float bx,float by,float cx,float cy){

//计算斜率

float slope = (by - ay) / (bx - ax);

//计算截距

float yIntercept = ay - ax * slope;

//计算cx对应的线上的解

float cSolution = cx * slope + yIntercept;

//通过判断解与cy的关系,判断在线上还是线下

if(cy < cSolution){

return -1;

}else if(cy > cSolution){

return 1;

}else{

return 0;

}

}

2.cocos坐标转换为交错地图坐标

Vec2 Map45Scene::getTilePosAtPos(const Vec2 &pos){

//pos应该转换为相对地图的坐标

auto mapPos = _map->convertToNodeSpaceAR(pos);

//auto mapPos = pos;

auto tileSize = _map->getTileSize();

auto mapSize = _map->getMapSize();

//将其转换为左上角坐标系

mapPos.y = mapSize.height * tileSize.height / 2 + tileSize.height / 2 - mapPos.y;

//取到小矩形的位置

int sx = int(mapPos.x / tileSize.width * 2);

int sy = int(mapPos.y / tileSize.height * 2);

int tx,ty;

//判断小矩形中线的位置

if(sx %2 == sy %2){

//如果线斜率是大于0

//取线上的两个点

float ax = sx * tileSize.width;

float ay = (sy + 1) * tileSize.height;

float bx = (sx + 1) * tileSize.width;

float by = sy * tileSize.height;

if(getPosOfLine(ax,ay,bx,by,mapPos.x,mapPos.y) < 0){

//在线上面

if(sy % 2 == 1){

//偶数行上

tx = int(mapPos.x / tileSize.width);

ty = int(mapPos.y / tileSize.height) * 2;

}else{

//奇数行上

tx = int((mapPos.x - tileSize.width / 2) / tileSize.width);

ty = int((mapPos.y - tileSize.height / 2) / tileSize.height) * 2 + 1;

}

}else if(getPosOfLine(ax,mapPos.y) >= 0){

//线下面或正好在线上

if(sy % 2 == 1){

//奇数行上

tx = int((mapPos.x - tileSize.width / 2) / tileSize.width);

ty = int((mapPos.y - tileSize.height / 2) / tileSize.height) * 2 + 1;

}else{

//偶数行上

tx = int(mapPos.x / tileSize.width);

ty = int(mapPos.y / tileSize.height) * 2;

}

}

}else{

//线斜率小于0

float ax = sx * tileSize.width;

float ay = sy * tileSize.height;

float bx = (sx + 1) * tileSize.width;

float by = (sy + 1) * tileSize.height;

if(getPosOfLine(ax,mapPos.y) < 0){

if(sy % 2 == 0){

//奇数行上

tx = int((mapPos.x - tileSize.width / 2) / tileSize.width);

ty = int((mapPos.y - tileSize.height / 2) / tileSize.height) * 2 + 1;

}else{

tx = int(mapPos.x / tileSize.width);

ty = int(mapPos.y / tileSize.height) * 2;

}

}else{

if(sy % 2 == 0){

//偶数行上

tx = int(mapPos.x / tileSize.width);

ty = int(mapPos.y / tileSize.height) * 2;

}else{

tx = int((mapPos.x - tileSize.width / 2) / tileSize.width);

ty = int((mapPos.y - tileSize.height / 2) / tileSize.height) * 2 + 1;

}

}

}

return Vec2(tx,ty);

}

下面看取到TileMap坐标后的应用

二、碰撞检测

前面制作地图时,我们加了一个blocks用于画玩家不可以穿越的块,我们现在可以取到一个cocos坐标所对应的地图瓦片坐标,这个碰撞功能的实现就很简单了:

我们在update时,取得更新后的玩家位置;

将位置转化为瓦片坐标;

取得blocks层中对应坐标的块,如果能取到,说明这个块是不可以穿越的,则取消移动,否则进行移动动作。

代码如下:

void Map45Scene::dealPlayerPos(float dt){

//玩家移动速度

float speed = MAP45_PLAYER_SPEED;

//两个方向的速度增量

float xDelta = speed * dt;

float yDelta = xDelta * _map->getTileSize().height / _map->getTileSize().width;

Vec2 pos;

//确定移动方向

if(_status == BTN_DOWN){

pos.x -= xDelta;

pos.y -= yDelta;

}else if(_status == BTN_UP){

pos.x += xDelta;

pos.y += yDelta;

}else if(_status == BTN_LEFT){

pos.x -= xDelta;

pos.y += yDelta;

}else if(_status == BTN_RIGHT){

pos.x += xDelta;

pos.y -= yDelta;

}

auto newPos = _normal->getPosition() + pos;

auto tile = getTileAtPosition(newPos,_map->getLayer("blocks"));

if(tile) {

//如果有阻挡,不移动

return;

}

//地图移动代替角色移动

_map->setPosition(_map->getPosition() - pos);

_normal->setPosition(_normal->getPosition() + pos);

_anim->setPosition(_normal->getPosition() + pos);

}

三、遮挡

我们虽然用45度斜角制作了一个2.5D的世界,看起来有了点立体感,但人物即使位于树、墙等的后面,还是会遮挡掉前面的物体,这样一下子就不真实了,所以我们需要动态修改玩家的渲染层级,来让玩家位于树前面遮挡树,树后面则被树遮挡。

1.为瓦片地图添加不同的渲染层级,我们需要在制作地图时,为图层添加OpenGl的Z order属性

为ground层添加属性:cc_vertexz=-500(我测试使用-1000层就不知道显示到哪去了,感觉是透视后太小导致,有时间研究下是为什么),这是为了玩家永远位于这个层的上面

为objects层添加属性:cc_vertexz=automatic,cc_alpha_func=0.5,这样添加后,cocos就会自动为这个层的瓦片分配动态的Z order属性值,算法为:pos.y - _layerSize.height,如下图黑色数字所示:

2.开启OpenGl的深度渲染:注意在scene显示前调用

Director::getInstance()->setProjection(cocos2d::Director::Projection::_2D);

Director::getInstance()->setDepthTest(true);

3.我们知道了z order的算法,又可以根据玩家位置知道玩家位置的瓦片地图坐标,就可以直接动态设置玩家的vertexz属性,达到我们的目的:

void Map45Scene::updatePlayer(){

auto pos = getTilePosAtPos(_normal->getPosition());

auto mapSize = _map->getMapSize();

//设置玩家的vertexz属性

_normal->setPositionZ( pos.y - mapSize.height);

_anim->setPositionZ( pos.y - mapSize.height);

}

四、结语

其他实现后续再补充。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

tilemap 菱形_【cocos3.x+tilemap】制作rpg小游戏(二)遮挡与碰撞 的相关文章

  • 字节跳动前端面经

    面试经历 我入职字节大概一个多月 目前准大四 实习生 现在写面经不仅仅是牛客网 YYSD 真tm灵 的还愿 还是就是想给大家推荐推荐我们部门 技术中台 可能大家对技术中台不太了解 但是大家肯定听说过掘金吧 我们组主要负责ByteTech 字
  • 相机的信噪比

    在图像传感器的成像过程中 真实的信号是无法探测到的理想值 在成像过程中理想值被引入了一系列的不确定性 最终形成读出信号也即图像 此过程中的不确定性被统一称为噪声 而信号与噪声的比值被定义为信噪比 Signal to NoiseRatio S
  • hibernate: Duplicate class/entity; Could not parse mapping document from resource

    近日在学习Hibernate时 总是遇到以下异常 org hibernate InvalidMappingException Could not parse mapping document from resource kpy db Cus
  • ModelScope-Agent: Building Your Customizable Agent System with Open-source Large Language Models

    本文是LLM系列文章 针对 ModelScope Agent Building Your Customizable Agent System with Open source Large Language Models 的翻译 ModelS
  • 1072. 开学寄语(20)

    下图是上海某校的新学期开学寄语 天将降大任于斯人也 必先删其微博 卸其QQ 封其电脑 夺其手机 收其ipad 断其wifi 使其百无聊赖 然后 净面 理发 整衣 然后思过 读书 锻炼 明智 开悟 精进 而后必成大器也 本题要求你写个程序帮助
  • Webpack 基础配置介绍(二)

    今天继续分享webpack的有关内容 我还是接着从上篇文章的项目来给大家分享后续内容 如果还有小伙伴没有阅读之前的文章 请关注博主进行阅读 今日分享 1 webpack的规范配置 2 webpack config js基础配置 3 单页开发
  • JSP+ssm计算机毕业设计考研资源共享平台设计与实现399xv【源码、数据库、LW、部署】

    项目运行 项目含有源码 文档 程序 数据库 配套开发软件 软件安装教程 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEcl
  • 环境变量路径中有空格该怎么办?

    本机环境变量的设置 java home C Program Files Java jdk1 5 0 09 bat中的命令格式 java home bin java 或者 C Program Files Java jdk1 5 0 09 bi
  • Python、Matplot的subplot实现一行3列的子图绘制,并添加背景色

    Python Matplot的subplot实现一行3列的子图绘制 并添加背景色 1 可能遇到的问题 2 示例 1 绘制2 2 俩行俩列 的子图 并设置背景色 2 绘制1 3 一行三列 的子图 并设置横轴纵轴值 3 绘制1 3 一行三列 的
  • 记一次kafka Consumer线程停止消费过程分析

    前言 kafka消息队列在项目开发中经常被使用 尤其是在大数据领域经常见到它的身影 spring集成了kafka方便我们使用 只要引入spring kafka即可 问题描述 有一天我们后台版本发布 虽然改动很大 但是大家还是自信满满 因为经
  • Spring Boot中使用WebSocket [第三部分]

    使用消息队列实现分布式WebSocket 在上一篇文章 https www zifangsky cn 1359 html 中我介绍了服务端如何给指定用户的客户端发送消息 并如何处理对方不在线的情况 在这篇文章中我们继续思考另外一个重要的问题
  • PTA自测-1 打印沙漏 python实现

    本题要求你写个程序把给定的符号打印成沙漏的形状 例如给定17个 要求按下列格式打印 所谓 沙漏形状 是指每行输出奇数个符号 各行符号中心对齐 相邻两行符号数差2 符号数先从大到小顺序递减到1 再从小到大顺序递增 首尾符号数相等 给定任意N个
  • 前端接收后端返回换行符 /n 不生效

    问题 前端接收后端返回换行符 n 不换行 不生效 解决方案 一 设置css的white space属性 div class text container text div export default data return text 这是
  • StackOverflow 第四周周报及19年就业情况分析

    这是 Stack Overflow 第四周周报 两篇 Java 两篇 Python 公众号 渡码 为日更 欢迎关注 另外 我搜集了今年的就业数据 对招聘情况和岗位情况做了简单总结 想了解的朋友点这里 DAY1 枚举对象 和 equals 区
  • TypeError: can only concatenate str (not “int“) to str

    看见报的错误我们可以发现大致的错误 首先要做的是先梳理一下代码整体的思路 确保思路没有问题 然后再断点调试 每个步骤的打印也可以 这样可以很好的得到每个阶段所获得的值 定位错误 然后就是针对错误进行解决 简而言之就是报错解决的范围太泛了 太
  • 【自然语言处理】Transformer 讲解

    有任何的书写错误 排版错误 概念错误等 希望大家包含指正 在阅读本篇之前建议先学习 自然语言处理 Seq2Seq 讲解 自然语言处理 Attention 讲解 Transformer 为了讲解更加清晰 约定 预测阶段 被称为 推断阶段 in
  • cubemx hal stm32 舵机 可减速 任意位置停止 驱动代码

    CubeMX配置 对于 STM32 F407VE 这里的84是来自APB1那路2倍频得到 代码部分 两个舵机都是180度的 servo c include servo h include tim h include stdio h IO u
  • css补充2:flex布局,居中方案等

    一 flex 布局 1 1 flex布局原理 flex是flexible Box的缩写 意为 弹性布局 用来为盒状模型提供最大的灵活性 任何一个容器都可以指定为flex布局 当我们为父盒子设为flex布局以后 子元素的float clear
  • 相似度计算

    在推荐系统中 最基础的一个概念就是计算相似度 很多的相似度都是基于距离计算出来的 计算距离的方法有很多种 包括 Euclidian Distance Pearson Correlation Cosine Similarity interse

随机推荐

  • 【华为OD机试真题2023B卷 JAVA&JS】模拟消息队列

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 模拟消息队列 知识点排序 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 让我们来模拟一个消息队列的运作 有一个发布者和若干消费者 发布者会在给定的时刻向消息队列发送消
  • JQuery美化下拉框插件

  • 简单卸载硬盘安装的ubuntu

    我们多数要卸载ubuntu的都是双系统 简简单单 两步搞定ubuntu的卸载前提拥有一张windows的光盘 上面带有PE系统即可 用优盘启动盘估计也可以第一步 先去除grub 进入PE 多数PE里面有一个分区表医生或者类似的软件 我用的F
  • ubuntu解压zip文件命令_Ubuntu压缩及解压文件简介

    使用Ubuntu的过程中 无论用来干什么 都会有文件上的交流 必不可免的就是压缩文件 Ubuntu系统中自带了部分格式的压缩软件 但是win系统习惯的rar格式文件解压需要下载相关软件 现整理如下 1 文件格式及解压工具 tar 用 tar
  • ARM中MMU之地址转换

    第一次发帖略微有点激动 有不足的地方还请各位大神指教 最近看了看mmu 找了好多资料 看了好多博文终于稍微清楚了一点 现在我把自己理解的内容总结一下 首先我来说一下MMU的作用 MMU就是负责虚拟地址 virtual address 转化成
  • response.getWriter().write()和 response.getWriter().print()的区别 以及 PrintWriter对象 和 out对象 的区别

    一 response getWriter write 和 response getWriter print 的区别 response getWriter 返回的是PrintWriter 这是一个打印输出流 response getWrite
  • Pytorch之经典神经网络Generative Model(三) —— GAN (MNIST)

    2014年由GAN之父Ian Goodfellow提出 加拿大蒙特利尔大学 GAN 生成式对抗网络 前面我们讲了自动编码器和变分自动编码器 不管是哪一个 都是通过计算生成图像和输入图像在每个像素点的误差来生成 loss 这一点是特别不好的
  • 一篇文章,让你彻底搞懂单例设计模式

    今天在一群小哥哥的带领下 本程序媛终于学会了所有单例模式 非常感谢大哥哥 小哥哥 下文是我总结的单例模式的八种实现方式 如下所示 单例模式的简介 我们将一个类在当前进程中只有一个实例的这种模式 称之为 单例模式 那么Java代码如何实现一个
  • Postman —— 配置环境变量

    PostMan是一套比较方便的接口测试工具 但我们在使用过程中 可能会出现创建了API请求 但API的URL会随着服务器IP地址的变化而改变 这样的情况下 如果每一个API都重新修改URL的话那将是非常的麻烦 所以PostMan中也提供环境
  • 【ViT 微调时关于position embedding如何插值(interpolate)的详解】

    目录 1 问题描述 2 positional embedding如何interpolate 3 输入的sequence length改变了ViT还能正常前向推断 本文适合对Vision Transformer有一定了解 知道内部结构和一些实
  • 项目6—利用中断实现单位数码管0~9显示

    项目5中有介绍中断问题 中断函数命名格式 函数值类型 函数名 形式参数列表 interrupt x interrupt为中断函数关键字 表中第二行T0中断 使能T0中断 就要将ET0置1 当它的中断标志位TF0变为1时 就会触发T0中断 这
  • UVA1613 K-GraphOddity

    UVA1613 K GraphOddity 题目传送门 刚看第一眼一点思路都没有 后面看了大佬的题解发现这道题其实是一道水题 用到的方法就是DFS遍历图 我是废物 题目意思很简单 就不分析了 下面直接说方法 首先求出k 然后dfs遍历一遍图
  • 出现这个问题 -bash: /etc/profile.d/env.sh: Permission denied

    记录一下搞了一个上午都没有解决的问题 如下图 出现的问题很奇怪 从root用户切换到普通用户是出现了 bash etc profile d env sh Permission denied 然后用root 把这个env sh文件 内容是PS
  • IP核之FIFO实验

    FIFO 的英文全称是 First In First Out 即先进先出 FPGA 使用的 FIFO 一般指的是对数据的存储具有先进先出特性的一个缓存器 常被用于数据的缓存 或者高速异步数据的交互也即所谓的跨时钟域信号传递 它与 FPGA
  • Python配置清华镜像源

    Python配置清华镜像源 1 前言 使用pip 安装服务器在国外的python 库时 下载需要很长时间 在配置文件中设置国内镜像可以提高速度 清华镜像源就是其中之一 2 pypi 镜像使用帮助 网址 https mirrors tuna
  • 将cookie字符串转化为json对象

    先看一下cookie长啥样 在控制台输入查看document cookie 如下图 分析可以看出cookie是以 key value key2 value2 的结构 好 接下来我们就将其转为json对象 function cookieToJ
  • base64 加密解密

    1 str lt gt bytes str bytes bytes s encoding utf8 bytes str str b encoding utf 8 此外还可通过编码解码的形式对二者进行转换 str 编码成 bytes 格式 s
  • Spring cloud+Zuul+JWT实现无状态统一身份认证和分布式限流

    本文主旨搭建一个无状态统一身份认证的系统 基于Spring cloud微服务架构 Eureka 实现服务的注册与发现 Zuul网关实现服务路由 请求过滤和限流功能 使用JWT规范实现客户登陆信息的服务端无状态话 相关文章参考 Spring
  • localStorage sessionStorage cookie的区别

    文章转载自 http blog csdn net cwzhsi article details 49557879 一 基本概念 Cookie cookie比较小 大小限制在4kb左右 是网景公司的前雇员 LouMontulli 在1993年
  • tilemap 菱形_【cocos3.x+tilemap】制作rpg小游戏(二)遮挡与碰撞

    前面制作了地图 现在就可以在工程中使用了 现在只实现了遮挡与碰撞 后续再实现点击屏幕移动 寻路算法 npc交互等 实现遮挡与碰撞 都需要解决一个核心问题 当前角色到底在哪一块瓦片上 也就是cocos坐标如何转化为TileMap瓦片坐标 这个