有效的碰撞处理

只用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的更多相关文章

  1. C/C++ Lua Parsing Engine

    catalog . Lua语言简介 . 使用 Lua 编写可嵌入式脚本 . VS2010编译Lua . 嵌入和扩展: C/C++中执行Lua脚本 . 将C++函数导出到Lua引擎中: 在Lua脚本中执 ...

  2. SpriteKit 关于categoryBitMask collisionBitMask contactTestBitMask 遇到的一些问题

    手写copy一下官方解释 首先是categoryBitMask /** 定义了这个物理刚体是属于哪个类别的掩码 .在一个场景中的每个物理刚体可以分配给达到 32 不同的类别(参数 int bitmas ...

  3. 永不消逝的电波(三):低功耗蓝牙(BLE)入门之如何调戏别人的小米手环

    0×00 前言 蓝牙(Bluetooth),一种无线技术标准,用来让固定与移动设备,在短距离间交换数据,以形成个人局域网(PAN).其使用短波特高频(UHF)无线电波,经由2.4至2.485 GHz的 ...

  4. cocos2d-x lua脚本开发 1

    自从开始关注OpenResty之后,逐渐关注Lua语言,发现这个语言真真是容易让人喜爱的语言.偶然间发现了cocos2d-x,还支持lua,所以果断尝试一下. 这里是在cocos2d-x官方网站下载了 ...

  5. Lua的工具资源3

    [LuaSrcDiet] (5.0.2) - 通过删除不必要的空白和注释缩减Lua文件的大小. [LuaProfiler] (5.0) - 一个用来查找Lua应用瓶颈的工具time profiler ...

  6. Lua 学习笔记(二)语法、类型、值

    首先Lua执行的每一段代码都称之为“程序块”,一个程序块也就是一连串的语句或命令,例如一个源码文件或一行代码.Lua语句之间并不需要分隔符,如代码中的换行就不起任何作用,当然为了养成编码习惯当两条或者 ...

  7. Lua 5.1 参考手册

    Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes 云风 译 www.codingno ...

  8. Mac 下纯lua(一)

    Lua 介绍 什么是lua - lua是一种跨平台开发脚本语言. Lua 历史 学校 University of Rio de Janeiro 国家 巴西 作者 Roberto Ierusalimsc ...

  9. Lua中的类型与值

    [基础介绍] Lua是一种动态类型的语言.在语言中没有类型定义的语法,每个值都带有其自身的类型信息.在Lua中有8中基本类型,分别是: nil(空)类型 boolean(布尔)类型 number(数字 ...

  10. lua 语言笔记

    Lua语言基础汇总(1) -- 类型与值 基础介绍 Lua是一种动态类型的语言.在语言中没有类型定义的语法,每个值都带有其自身的类型信息.在Lua中有8种基本类型,分别是: nil(空)类型 bool ...

随机推荐

  1. Requested setting LOGGING_CONFIG, but settings are not configured

  2. 【工作随手记】deaklock排查

    生产环境当中还没真正遇到过死锁的问题.有些疑似死锁的问题,后来经过排查也只是其它问题导致的.所以通过jstack到底怎样排查死锁问题有点疏忽了.这里作个记录. 模拟一个死锁 顺便复习一下. 死锁的产生 ...

  3. 非极大值抑制(NMS)算法详解

    NMS(non maximum suppression)即非极大值抑制,广泛应用于传统的特征提取和深度学习的目标检测算法中. NMS原理是通过筛选出局部极大值得到最优解. 在2维边缘提取中体现在提取边 ...

  4. < Python全景系列-7 > 提升Python编程效率:模块与包全面解读

    欢迎来到我们的系列博客<Python全景系列>!在这个系列中,我们将带领你从Python的基础知识开始,一步步深入到高级话题,帮助你掌握这门强大而灵活的编程语法.无论你是编程新手,还是有一 ...

  5. LINIUX 查询命令的 区别 chich whereis locate fing

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which  查看可执行文件的位置. whereis 查看文件的位置. locate   配合数据库查看文件位置 ...

  6. celery笔记一之celery介绍、启动和运行结果跟踪

    本文首发于公众号:Hunter后端 原文链接:celery笔记一之celery介绍.启动和运行结果跟踪 本篇笔记内容如下: celery 介绍 celery 准备 celery 启动和异步任务的运行 ...

  7. 使用containerd从0搭建k8s(kubernetes)集群

    准备环境 准备两台服务器节点,如果需要安装虚拟机,可以参考<wmware和centos安装过程> 机器名 IP 角色 CPU 内存 centos01 192.168.109.130 mas ...

  8. Go语言中的结构体:灵活性与可扩展性的重要角色

    1. 引言 结构体是Go语言中重要且灵活的概念之一.结构体的使用使得我们可以定义自己的数据类型,并将不同类型的字段组合在一起,实现更灵活的数据结构.本文旨在深入介绍Go语言中的结构体,揭示其重要性和灵 ...

  9. GPT3的应用领域:机器翻译、文本生成、文本摘要

    目录 1. 引言 2. 技术原理及概念 3. 实现步骤与流程 3.1 准备工作:环境配置与依赖安装 3.2 核心模块实现 3.3 集成与测试 4. 应用示例与代码实现讲解 4.1 机器翻译 4.2 文 ...

  10. MySQL-this is incompatible with sql_mode=only_full_group_by 错误解决

    MySQL-this is incompatible with sql_mode=only_full_group_by 错误解决 编辑配置文件 Linux 中 :my.cnf Windows中 : m ...