[Lua][Love] 有效碰撞处理の类别与位掩码 | fixture:setFilterData

这篇具有很好参考价值的文章主要介绍了[Lua][Love] 有效碰撞处理の类别与位掩码 | 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

下面我们定义了两个类别,分别是001010

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,即使算出来要发生碰撞,由于相同组且是负数,永远也不会碰撞文章来源地址https://www.toymoban.com/news/detail-667238.html

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] 有效碰撞处理の类别与位掩码 | fixture:setFilterData的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Cargo.toml配置:所有有效的类别Slugs

    Rust 笔记 Cargo.toml 配置:所有有效的类别Slugs 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/130884330 【介绍】:本文记录 rust 项目配置文件中,可用的类别。 上一节:《 开发环境

    2024年02月06日
    浏览(30)
  • 无类别域间路由(Classless Inter-Domain Routing, CIDR):理解IP网络和子网划分(传统的IP地址类ABCDE:分类网络)子网掩码

    1 无类别域间路由(Classless Inter-Domain Routing, CIDR)是一种用于在互联网上创建独立的IP地址分配策略的方法。这种方法允许更细粒度的IP地址分配,从而提供了比传统的IP地址类A、B、C更高效的使用 2 。 在早期的互联网历史中,IP地址被分为五个类别:A、B、C、D和E。每一种类别都

    2024年02月07日
    浏览(39)
  • 【华为机试真题详解JAVA实现】—识别有效的IP地址和掩码并进行分类统计

        目录 一、题目描述 二、解题代码 请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。 所有的IP地址划分为 A,B,C,D,E五类 A类地址从1.0.0.0到126.255.255.255; B类地址从128.0.0.0到191.255.255.255; C类地址从192.0.0.0到223.255.255.255;

    2023年04月09日
    浏览(43)
  • 用于无监督视频异常检测的合成伪异常:一种简单有效的基于掩码自动编码器的框架 论文阅读

    论文标题:SYNTHETIC PSEUDO ANOMALIES FOR UNSUPERVISED VIDEO ANOMALY DETECTION: A SIMPLE YET EFFICIENT FRAMEWORK BASED ON MASKED AUTOENCODER 文章信息: 发表于:ICASSP 2023(CCF B) 原文链接:https://arxiv.org/abs/2303.05112 源码:无 由于用于训练的异常样本的可用性有限,视频异常检测通常被视为一类分类问题

    2024年02月04日
    浏览(52)
  • 高基数类别特征预处理:平均数编码

    对于一个类别特征,如果这个特征的取值非常多,则称它为高基数(high-cardinality)类别特征。在深度学习场景中,对于类别特征我们一般采用Embedding的方式,通过预训练或直接训练的方式将类别特征值编码成向量。在经典机器学习场景中,对于有序类别特征,我们可以使用

    2024年02月11日
    浏览(44)
  • 【机器学习6】数据预处理(三)——处理类别数据(有序数据和标称数据)

    在【机器学习4】构建良好的训练数据集——数据预处理(一)处理缺失值及异常值这一篇文章中,主要说明热数据预处理的重要性以及如何处理缺失值及异常值这些数值特征。然而,在现实生活中遇到的数据集往往不仅仅只会包含 数值型特征 ,还会包含一个或者多个 类别特征

    2024年02月12日
    浏览(46)
  • 高基数类别特征预处理:平均数编码 | 京东云技术团队

    对于一个类别特征,如果这个特征的取值非常多,则称它为高基数(high-cardinality)类别特征。在深度学习场景中,对于类别特征我们一般采用Embedding的方式,通过预训练或直接训练的方式将类别特征值编码成向量。在经典机器学习场景中,对于有序类别特征,我们可以使用

    2024年02月10日
    浏览(49)
  • Go语言中,如何做到数据按类别分发给特定的协程处理

    在 Go 语言中,如果你想按类别将数据分配给特定的协程(goroutine)进行处理,可以使用几种策略。下面我将提供一些方法和示例,说明如何根据数据类别将任务分配给不同的协程来处理。 使用通道(Channel)分发数据 使用映射函数和协程池 使用单一分发器(Dispatcher) 方法

    2024年04月28日
    浏览(29)
  • 【Python】数据预处理之将类别数据转换为数值的方法(含Python代码分析)

    在进行Python数据分析的时候,首先要进行数据预处理。但是有时候不得不处理一些非数值类别的数据,遇到这类问题时该怎么解决呢? 目前为止,总结了三种方法,这里分享给大家。 这种方法是属于映射字典将类标转换为整数,不过这种方法适用范围有限。 我们首先创建一

    2024年02月09日
    浏览(59)
  • DOTS Unity.Physics物理引擎碰撞事件处理

    最近DOTS发布了正式的版本,同时基于DOTS的理念实现了一套高性能的物理引擎,今天我们给大家分享和介绍一下这个物理引擎的碰撞事件处理以及核心相关概念。 Unity.Physics 物理引擎的主要流程与P ipeline   Unity.Physics物理引擎做仿真迭代计算的时候主要通过以下步骤来执行:   

    2024年01月18日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包