[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 ...
随机推荐
- 2021-02-28:给定一个整型数组arr,和一个整数num。某个arr中的子数组sub,如果想达标,必须满足:sub中最大值 – sub中最小值 <= num,返回arr中达标子数组的数量。
2021-02-28:给定一个整型数组arr,和一个整数num.某个arr中的子数组sub,如果想达标,必须满足:sub中最大值 – sub中最小值 <= num,返回arr中达标子数组的数量. ...
- 2022-03-30:有m个同样的苹果,认为苹果之间无差别, 有n个同样的盘子,认为盘子之间也无差别, 还有,比如5个苹果如果放进3个盘子, 那么1、3、1和1、1、3和3、1、1的放置方法,也认为是
2022-03-30:有m个同样的苹果,认为苹果之间无差别, 有n个同样的盘子,认为盘子之间也无差别, 还有,比如5个苹果如果放进3个盘子, 那么1.3.1和1.1.3和3.1.1的放置方法,也认为是 ...
- 2022-03-23:在k进制下,最小多小的num,可以让1~num范围的数拥有1的个数不少于n个? 腾讯音乐2022校园招聘。
2022-03-23:在k进制下,最小多小的num,可以让1~num范围的数拥有1的个数不少于n个? 腾讯音乐2022校园招聘. 答案2022-03-23: 二分法. 代码用golang编写.代码如下 ...
- Java 网络编程 —— 非阻塞式编程
线程阻塞概述 在生活中,最常见的阻塞现象是公路上汽车的堵塞.汽车在公路上快速行驶,如果前方交通受阻,就只好停下来等待,等到公路顺畅,才能恢复行驶. 线程在运行中也会因为某些原因而阻塞.所有处于阻塞状态 ...
- pandas 数据处理 一些常用操作
读取csv文件,打印列名称: import pandas as pd # data = pd.read_csv("guba_fc_result_20230413.csv") dat ...
- 从零开始使用 Astro 的实用指南
在这个实用的Astro指南中,我将指导你完成设置过程,并告诉你如何构造你的文件.你将学习如何添加页面.交互式组件,甚至是markdown文章.我还会告诉你如何从服务器上获取数据,创建布局,并使用van ...
- .Net使用第三方onnx或ModelBuilder轻松接入AI模型
ML.Net - 开源的跨平台机器学习框架 支持CPU/GPU训练 轻松简洁的预测代码 可扩展其他的机器学习平台 跨平台 1.使用Visual Studio的Model Builder训练和使用模型 ...
- JAVA 23种设计模式(小白进阶必经之路)
如今几乎所有程序都遵循万物皆对象的开发理念,然在写程序中我们用的最多的应该是封装(encapsulation).继承(inheritance).多态(Polymorphism)开发模式:而更高一个境界 ...
- 在asp.net core web api中添加efcore使用codefirst
首先创建webapi项目,我这里使用的版本是.net6 在nuget中添加对应的工具包 红框标出来的是对应的数据库扩展包,mysql用mysql版,sqlserver用sqlserver版,选择正确的 ...
- 10 款 VS Code 插件神器,第 7 款超级实用!
VS Code 是这两年非常热门的一款 IDE,它不仅有提升开发体验的界面.轻量化的编辑器,还有丰富而强大的插件,这些优秀的插件使得 VS Code 生态体系更加吸引人,让开发效率大大提升.本文来介绍 ...