[Lua][Love Engine] 有效碰撞处理の类别与位掩码 | fixture:setFilterData
有效的碰撞处理
只用IF判断
假设在一个物理世界,不希望两个同类实体发生碰撞,那么
local begin_contact_callback = function(fixture_a, fixture_b)
local entity_a_type = fixture_a:getUserData()
local entity_b_type = fixture_b:getUserData()
-- 如果碰撞的两个实体不同
if entity_a_type ~= entity_b_type then
--
end
end
但是如果新加了可互动元素,如一种道具,只能跟玩家实体碰撞,那么
local begin_contact_callback = function(fixture_a, fixture_b)
local a = fixture_a:getUserData()
local b = fixture_b:getUserData()
if (a == 'powerup' and b == 'player') or (a == 'player' and b == 'powerup') then
--
elseif a ~= b and a ~= 'powerup' and b~= 'powerup' then
--
end
end
如果再加上其他东西,比如只有玩家可以推动的方块,代码量会飞速膨胀
使用二进制和位掩码
假设游戏已经有几十种实体,我们可以根据实体在游戏内的作用归为五类,给每种实体绑定类别和位掩码
| 实体类别 | 类别对应的二进制 | 位掩码 |
|---|---|---|
| 场景(如云、花) | 0000 | 0000 |
| 玩家 | 0001 | 1110 |
| 道具 | 0010 | 1001 |
| 敌人 | 0100 | 1001 |
| 墙体 | 1000 | 1111 |
比如玩家实体和敌人实体,在函数中我们提取玩家的类别和敌人的位掩码做位与运算
0001 玩家 类别
1001 敌人 位掩码
----
0001 不为0 发生碰撞
再举个例子,敌人碰撞到了道具
0100 敌人 类别
1001 道具 位掩码
----
0000 为0 不发生碰撞
因此,在上面表格的情况下
- 场景实体没有被分配类别(要保证某1位为1),不会和任何实体发生碰撞
- 玩家实体不能相互碰撞,能与道具、敌人、墙体发生碰撞
- 道具实体能跟墙体、玩家发生碰撞
- 敌人实体能跟墙体、玩家发生碰撞
- 墙体实体能跟所有类别发生碰撞(除场景)
注:如果实体不能跟墙体发生碰撞,那么一旦生成就会直接无限坠落至无底洞
绑定到实体
先生成实体的类别二进制和位掩码,比如在squre.lua中,创建了一个实体squre
某种情况下,实体可以属于多个类别,比如
1011,这个实体既是墙体也是敌人、玩家,虽然逻辑上是不可能的,但相应的碰撞处理均会发生两个苹果,第一个苹果可以只是场景摆件,仅与地形碰撞;第二个苹果可以是道具,与地形和玩家均可碰撞
square.category = tonumber('0001', 2)
square.mask = tonumber('1110', 2)
square.group = 0
绑定到fixture上,由于设置了类别和位掩码,组号填0意味着没有组别
square.fixture:setFilterData(square.category, square.mask, square.group)
-- Fixture:setCategory, Fixture:setMask or Fixture:setGroupIndex
LOVE 引擎最多支持16位二进制的类别和位掩码,即0000000000000000
fixture创建时默认类别为1D,位掩码为65535D,组别均为0
代码与效果
-- entities/block.lua
local world = require 'world'
return function(x, y, width, height, rigidbody, category, bitmask, group)
e = {}
e.body = love.physics.newBody(world, x, y, rigidbody)
e.body:setMass(32)
e.shape = love.physics.newRectangleShape(width, height)
e.fixture = love.physics.newFixture(e.body, e.shape)
e.fixture:setFilterData(category, bitmask, group)
function e:draw()
love.graphics.polygon('line', self.body:getWorldPoints(self.shape:getPoints()))
local x, y = self.body:getPosition()
love.graphics.print({{0, 1, 0}, (category .. '+' .. bitmask) or group}, x, y, nil)
end
return e
end
下面我们定义了两个类别,分别是001和010
local entities = {block(400, 400, 300, 10, 'static', '001', '011', 0),
block(400, 300, 50, 50, 'dynamic', '011', '011', 0),
block(400, 200, 40, 40, 'dynamic', '010', '011', 0),
block(400, 100, 30, 30, 'dynamic', '010', '011', 0)}

修改第二个和第三个方块的位掩码
local entities = {block(400, 400, 300, 10, 'static', '001', '011', 0),
block(400, 300, 50, 50, 'dynamic', '011', '000', 0),
block(400, 200, 40, 40, 'dynamic', '010', '001', 0),
block(400, 100, 30, 30, 'dynamic', '010', '011', 0)}

组别
我们可以为各个实体设置组别,同组别将直接无视类别与位掩码的计算结果,同组别且正数总是会碰撞,同组别且负数总不会碰撞。
e.fixture:setFilterData( xx , xx , group)
-- e.fixture:setGroupIndex(group)
考虑如下代码
local entities = {block(400, 400, 300, 10, 'static', '001', '011', 0),
block(400, 300, 50, 50, 'dynamic', '010', '001', 0),
block(400, 200, 40, 40, 'dynamic', '010', '001', 0)}
第二个方块跟第三个方块不会碰撞,设置组别为1
local entities = {block(400, 400, 300, 10, 'static', '001', '011', 0),
block(400, 300, 50, 50, 'dynamic', '010', '001', 1),
block(400, 200, 40, 40, 'dynamic', '010', '001', 1)}

再考虑如下代码,
local entities = {block(400, 400, 300, 10, 'static', '001', '011', 0),
block(400, 300, 50, 50, 'dynamic', '010', '011', 1),
block(400, 200, 40, 40, 'dynamic', '010', '011', 1)}
第二个方块跟第三个方块会碰撞,将组别设置为-1,即使算出来要发生碰撞,由于相同组且是负数,永远也不会碰撞
local entities = {block(400, 400, 300, 10, 'static', '001', '011', 0),
block(400, 300, 50, 50, 'dynamic', '010', '011', -1),
block(400, 200, 40, 40, 'dynamic', '010', '011', -1)}

[Lua][Love Engine] 有效碰撞处理の类别与位掩码 | fixture:setFilterData的更多相关文章
- C/C++ Lua Parsing Engine
catalog . Lua语言简介 . 使用 Lua 编写可嵌入式脚本 . VS2010编译Lua . 嵌入和扩展: C/C++中执行Lua脚本 . 将C++函数导出到Lua引擎中: 在Lua脚本中执 ...
- SpriteKit 关于categoryBitMask collisionBitMask contactTestBitMask 遇到的一些问题
手写copy一下官方解释 首先是categoryBitMask /** 定义了这个物理刚体是属于哪个类别的掩码 .在一个场景中的每个物理刚体可以分配给达到 32 不同的类别(参数 int bitmas ...
- 永不消逝的电波(三):低功耗蓝牙(BLE)入门之如何调戏别人的小米手环
0×00 前言 蓝牙(Bluetooth),一种无线技术标准,用来让固定与移动设备,在短距离间交换数据,以形成个人局域网(PAN).其使用短波特高频(UHF)无线电波,经由2.4至2.485 GHz的 ...
- cocos2d-x lua脚本开发 1
自从开始关注OpenResty之后,逐渐关注Lua语言,发现这个语言真真是容易让人喜爱的语言.偶然间发现了cocos2d-x,还支持lua,所以果断尝试一下. 这里是在cocos2d-x官方网站下载了 ...
- Lua的工具资源3
[LuaSrcDiet] (5.0.2) - 通过删除不必要的空白和注释缩减Lua文件的大小. [LuaProfiler] (5.0) - 一个用来查找Lua应用瓶颈的工具time profiler ...
- Lua 学习笔记(二)语法、类型、值
首先Lua执行的每一段代码都称之为“程序块”,一个程序块也就是一连串的语句或命令,例如一个源码文件或一行代码.Lua语句之间并不需要分隔符,如代码中的换行就不起任何作用,当然为了养成编码习惯当两条或者 ...
- Lua 5.1 参考手册
Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes 云风 译 www.codingno ...
- Mac 下纯lua(一)
Lua 介绍 什么是lua - lua是一种跨平台开发脚本语言. Lua 历史 学校 University of Rio de Janeiro 国家 巴西 作者 Roberto Ierusalimsc ...
- Lua中的类型与值
[基础介绍] Lua是一种动态类型的语言.在语言中没有类型定义的语法,每个值都带有其自身的类型信息.在Lua中有8中基本类型,分别是: nil(空)类型 boolean(布尔)类型 number(数字 ...
- lua 语言笔记
Lua语言基础汇总(1) -- 类型与值 基础介绍 Lua是一种动态类型的语言.在语言中没有类型定义的语法,每个值都带有其自身的类型信息.在Lua中有8种基本类型,分别是: nil(空)类型 bool ...
随机推荐
- vue全家桶进阶之路11:计算属性
Vue2 中的计算属性是指在组件中声明的计算属性,它们的值是根据其他数据计算得出的,并且会根据依赖数据的变化而自动更新.计算属性可以在模板中使用,与普通属性一样使用,但是它们具有以下优点: 缓存:计算 ...
- 02-初识Verilog
1.开发环境搭建 需要使用的软件: QuartusII ModelSim Visio Notepad++ 2.初识Verilog 2.1 Verilog HDL简介 Verilog HDL是一种硬件描 ...
- ChatGPT 是否会夺走人们的工作
ChatGPT 是否会夺走人们的工作? 最近,以 ChatGPT 为代表的人工智能项目在自然语言处理这一领域得到了一些突破性的进展,重新引发了人们对于"人工智能会抢走人类工作机会" ...
- Post-Exploitation Basics
开发后基础知识 https://tryhackme.com/room/postexploit 使用 mimikatz.bloodhound.powerview 和 msfvenom 学习后期开发和维护 ...
- CHS、LAB地址
CHS地址 CHS地址指的是柱面(Cylinder).磁头(Head).扇区(Sector)三个参数组成的地址,是用来表示磁盘上每个扇区位置的一种方式. 物理扇区号 = ((柱面号×磁头数) + 磁头 ...
- 「AntV」X6开发实践:踩过的坑与解决方案
长期更新版文档请移步语雀(「AntV」X6开发实践:踩过的坑与解决方案 (yuque.com)) ️ | 如何自定义拖拽源? 相信你们在开发中更多的需求是需要自定义拖拽源,毕竟自定义的功能扩展性高一些 ...
- .netcore中的虚拟文件EmbeddedFile
以前一直比较好奇像swagger,cap,skywalking等组件是如何实现引用一个dll即可在网页上展示界面的,难道这么多html,js,css等都是硬编码写死在代码文件中的?后面接触apb里面也 ...
- Python获取token数据的几种方式
import requestsfrom urllib import requestimport re# 一.从响应头中获取token# 登录url = 'http://xxx.nhf.cn/api/b ...
- CANoe学习笔记(六):如何实现LIN和CAN的多帧传输-----LIN
内容: 1.实现LIN的多帧传输 一.新建一个基于LIN的CANoe工程 二.接下来创建一些工程用得上的变量.文件: 2.1 LDF文件: 这部分注意:包含三个调度表,①3C诊断请求帧②3D诊断响应帧 ...
- .NET 5 的烦恼
由于微软工程师的辛勤脑洞和劳作,.NET 生态如何演变完全看他们的决策,其中包含社区吸纳内容.团队讨论结果等等,不乏一些工程师.架构师偏好,很难摸得准. 就比如这一次未来规划,他们希望将 .NET ...