LearnOpenGL学习(碰撞检测,粒子)
完整代码见:zaizai77/OpenGLTo2DGame: 基于OpenGL制作2D游戏
物体本身的数据来检测碰撞会很复杂,一半使用重叠在物体上的更简单的外形来检测。
AABB - AABB 碰撞
AABB代表的是轴对齐碰撞箱(Axis-aligned Bounding Box),碰撞箱是指与场景基础坐标轴(2D中的是x和y轴)对齐的长方形的碰撞外形。
获取左上角和右下角点的位置。
检查两个物体的水平边界是否重合以及垂直边界是否重合。如果水平边界和垂直边界都有重叠那么我们就检测到一次碰撞。
将这一概念转化为代码也是很直白的。我们对两个轴都检测是否重叠,如果都重叠就返回碰撞:
GLboolean CheckCollision(GameObject &one, GameObject &two) // AABB - AABB collision
{// x轴方向碰撞?bool collisionX = one.Position.x + one.Size.x >= two.Position.x &&two.Position.x + two.Size.x >= one.Position.x;// y轴方向碰撞?bool collisionY = one.Position.y + one.Size.y >= two.Position.y &&two.Position.y + two.Size.y >= one.Position.y;// 只有两个轴向都有碰撞时才碰撞return collisionX && collisionY;
}
这样子检测确实有用,但是不是非常准确
AABB - 圆碰撞检测
使用圆形碰撞对于圆球来说更合理
定义球的矢量和半径
我们会找到AABB上距离圆最近的一个点,如果圆到这一点的距离小于它的半径,那么就产生了碰撞。
GLboolean CheckCollision(BallObject &one, GameObject &two) // AABB - Circle collision
{// 获取圆的中心 glm::vec2 center(one.Position + one.Radius);// 计算AABB的信息(中心、半边长)glm::vec2 aabb_half_extents(two.Size.x / 2, two.Size.y / 2);glm::vec2 aabb_center(two.Position.x + aabb_half_extents.x, two.Position.y + aabb_half_extents.y);// 获取两个中心的差矢量glm::vec2 difference = center - aabb_center;glm::vec2 clamped = glm::clamp(difference, -aabb_half_extents, aabb_half_extents);// AABB_center加上clamped这样就得到了碰撞箱上距离圆最近的点closestglm::vec2 closest = aabb_center + clamped;// 获得圆心center和最近点closest的矢量并判断是否 length <= radiusdifference = closest - center;return glm::length(difference) < one.Radius;
}
粒子
一个微粒,从OpenGL的角度看就是一个总是面向摄像机方向且(通常)包含一个大部分区域是透明的纹理的小四边形。一个微粒本身主要就是一个精灵(sprite)
一个粒子通常有下面的属性:
struct Particle {glm::vec2 Position, Velocity;glm::vec4 Color;GLfloat Life;Particle() : Position(0.0f), Velocity(0.0f), Color(1.0f), Life(0.0f) { }
};
渲染粒子的着色器:
#shader vertex#version 330 core
layout(location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>out vec2 TexCoords;
out vec4 ParticleColor;uniform mat4 projection;
uniform vec2 offset;
uniform vec4 color;void main()
{float scale = 10.0f;TexCoords = vertex.zw;ParticleColor = color;gl_Position = projection * vec4((vertex.xy * scale) + offset, 0.0, 1.0);
}#shader fragment#version 330 core
in vec2 TexCoords;
in vec4 ParticleColor;
out vec4 color;uniform sampler2D sprite;void main()
{color = (texture(sprite, TexCoords) * ParticleColor);
}
粒子循环函数:
GLuint nr_new_particles = 2;
// Add new particles
for (GLuint i = 0; i < nr_new_particles; ++i)
{int unusedParticle = FirstUnusedParticle();RespawnParticle(particles[unusedParticle], object, offset);
}
// Update all particles
for (GLuint i = 0; i < nr_particles; ++i)
{Particle &p = particles[i];p.Life -= dt; // reduce lifeif (p.Life > 0.0f){ // particle is alive, thus updatep.Position -= p.Velocity * dt;p.Color.a -= dt * 2.5;}
}
GLuint lastUsedParticle = 0;
GLuint FirstUnusedParticle()
{// Search from last used particle, this will usually return almost instantlyfor (GLuint i = lastUsedParticle; i < nr_particles; ++i){if (particles[i].Life <= 0.0f){lastUsedParticle = i;return i;}}// Otherwise, do a linear searchfor (GLuint i = 0; i < lastUsedParticle; ++i){if (particles[i].Life <= 0.0f){lastUsedParticle = i;return i;}}// Override first particle if all others are alivelastUsedParticle = 0;return 0;
}
如果是最后一种情况(返回0),就意味着你粒子的生命值太长了,在每一帧里面需要产生更少的粒子,或者你只是没有保留足够的粒子,
更新消亡的粒子:
void RespawnParticle(Particle &particle, GameObject &object, glm::vec2 offset)
{GLfloat random = ((rand() % 100) - 50) / 10.0f;GLfloat rColor = 0.5 + ((rand() % 100) / 100.0f);particle.Position = object.Position + random + offset;particle.Color = glm::vec4(rColor, rColor, rColor, 1.0f);particle.Life = 1.0f;particle.Velocity = object.Velocity * 0.1f;
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
particleShader.Use();
for (Particle particle : particles)
{if (particle.Life > 0.0f){particleShader.SetVector2f("offset", particle.Position);particleShader.SetVector4f("color", particle.Color);particleTexture.Bind();glBindVertexArray(particleVAO);glDrawArrays(GL_TRIANGLES, 0, 6);glBindVertexArray(0);}
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
这里将glBlendFunc中的因子替换,将 GL_ONE_MINUS_SRC_ALPHA 替换为 GL_ONE
,产生粒子叠加在一起的平滑的发热效果(比如火焰粒子)。
参考:碰撞检测 - LearnOpenGL CN
相关文章:

LearnOpenGL学习(碰撞检测,粒子)
完整代码见:zaizai77/OpenGLTo2DGame: 基于OpenGL制作2D游戏 物体本身的数据来检测碰撞会很复杂,一半使用重叠在物体上的更简单的外形来检测。 AABB - AABB 碰撞 AABB代表的是轴对齐碰撞箱(Axis-aligned Bounding Box),碰撞箱是指与场景基…...

操作系统(24)提高磁盘I/O速度的途径
前言 操作系统提高磁盘I/O速度的途径多种多样,这些途径旨在减少磁盘访问的延迟和开销,提高数据传输的效率。 一、磁盘高速缓存(Disk Cache) 磁盘高速缓存是一种在内存中为磁盘数据设置的缓冲区,用于存储磁盘中某些盘块…...
C/C++基础知识复习(45)
1) C 中面向对象编程如何实现数据隐藏? 在 C 中,数据隐藏是通过将类的成员变量和方法的访问权限控制起来实现的。通常,数据隐藏是通过使用 访问控制 机制来实现的,C 提供了三种访问控制修饰符: private: 使成员变量和…...
现代C++锁介绍
文章目录 场景描述🐞 初始实现: 非线程安全版本互斥锁: std::mutex使用mutex保护共享资源使用std::lock_guard简化锁的管理 优化读操作: std::shared_mutex多个锁的管理: std::scoped_lock使用std::scoped_lock避免死锁 其他高级锁⏳ 带超时的锁: std::timed_mutex使…...
Squid代理服务器的安装使用
1.简介 Squid代理服务器是一种高效的中间服务器,位于客户端和目标服务器之间,起到了重要的网络中介作用。以下是对Squid代理服务器的详细介绍: 一、功能特点 缓存功能: Squid可以缓存经过它的请求和响应数据。当客户端发起请求时…...

爬虫学习案例8
爬取京东评论信息 采用DrissionPage自动化工具采集,感觉比Selenium工具好,真香。 安装第三方库 pip install DrissionPage pip install pandas pip install pyecharts pip install jieba pip install wordcloud1.安装DrissionPage库 DrissionPage安装…...
深入了解 CouchDB 的 Mango 查询:操作符和限制
CouchDB 是一个基于文档的数据库管理系统,支持 HTTP 协议,拥有强大的同步机制和灵活的数据模型。Mango 查询是 CouchDB 中用于数据检索的现代化查询接口,灵感来自 MongoDB 的查询语法。本文将深入探讨 Mango 查询中的各种操作符和限制,并提供详细的例子和说明,帮助你更好地…...
基于SSM(Spring + Spring MVC + MyBatis)框架搭建一个病人跟踪信息管理系统
基于SSM(Spring Spring MVC MyBatis)框架搭建一个病人治疗跟踪信息系统是一个相对复杂的项目,涉及到多个模块和功能。以下是一个简要的指导步骤。 1. 环境准备 开发环境:确保安装了Java Development Kit (JDK),建议…...

U盘文件名变乱码:原因、恢复与预防全解析
一、U盘文件名变乱码现象描述 在日常使用U盘进行数据传输和存储时,我们有时会遇到一个令人头疼的问题:U盘中的文件名突然变成了乱码,无法正常识别或访问。这些乱码文件名可能包含各种奇怪的字符和符号,使得原本有序的文件管理变得…...

EasyGBS国标GB28181公网平台P2P远程访问故障诊断:云端服务端排查指南
随着信息技术的飞速发展,视频监控领域正经历从传统安防向智能化、网络化安防的深刻转变。EasyGBS平台,作为基于国标GB28181协议的视频流媒体平台,为用户提供了强大的视频监控直播功能。然而,在实际应用中,P2P远程访问可…...

一网多平面
“一网多平面”是一种网络架构概念,具体指的是在一张物理网络之上,逻辑划分出“1N”个平面。以下是对“一网多平面”的详细解释: 定义与构成 01一网多平面 指的是在统一的物理网络基础设施上,通过逻辑划分形成多个独立的网络平面…...

animatediff 模型网盘分享
网盘 一、123网盘,不限速 https://www.123pan.com/s/ueQ8jv-OlzPh.html 网盘 网址 animatediff 国外网址https://huggingface.co/guoyww/animatediff/tree/cd71ae134a27ec6008b968d6419952b0c0494cf2 国内镜像在 https://hf-mirror.com/guoyww/animatediff/t…...
ansible play-book玩法
使用ansible-playbook实现安装nginx_ansible 安装nginx-CSDN博客文章浏览阅读1.5k次,点赞14次,收藏19次。本文详细介绍了如何在Linux环境中准备Ansible环境,包括配置主机、下载和安装Ansible,以及使用yum模块和tar包源码安装Nginx…...

MySQL索引-索引的分类和创建
索引类型 数据类型 B树索引Hash索引FullText全文索引 物理存储 聚簇索引二级索引 字段特性 主键索引唯一索引普通索引前缀索引 字段个数 单列索引联合索引 创建索引 创建表时一同创建创建表后单独创建创建表后通过修改表结构创建 可以通过 SHOW INDEX FROM test_table;查看…...
如何给负载均衡平台做好安全防御
在现代网络架构中,负载均衡(Load Balancing)扮演着至关重要的角色。它不仅负责将流量分配到多个服务器以确保高效的服务交付,还作为第一道防线来抵御外部攻击。为了保护您的应用程序和服务免受潜在威胁,必须对负载均衡…...
HR/TA/HRBP的关系
HR(人力资源)领域包含 TA(人才获取)和 HRBP(人力资源业务伙伴)这两个重要的角色,但它们只是 HR 工作的一部分分支,一般我们说的HR指TA。 1. 人才获取(TA) 定…...
Docker环境下MySQL数据库持久化部署全攻略
概述 在当今的软件开发领域,Docker容器技术已经成为应用部署和管理的新标准。它不仅简化了应用的部署流程,还为数据管理提供了灵活的解决方案。特别是在涉及到MySQL数据库时,数据持久化是一个不可忽视的重要环节。本文将分享如何在Docker中部…...

如何查看pad的console输出,以便我们更好的进行调试,查看并了解实际可能的问题。
1、以下是baidu AI回复: 2、说明: 1)如果小伙伴们经常做android开发的话,这个不陌生,因为调试都是要开启这个开发者模式。并启用USB调试模式。 2)需要连上USB线,有的时候会忘记,然…...
react中使用ResizeObserver来观察元素的size变化
在 React 中使用 ResizeObserver 来观察元素的大小变化,可以通过创建一个自定义 Hook 来封装 ResizeObserver 的逻辑,并在组件中使用这个 Hook。以下是一个完整的示例,展示了如何在 React 中使用 ResizeObserver 来观察元素的大小变化。 自定…...
Linux快速入门-Linux文件系统管理
Linux文件系统管理 1. Linux文件系统概述1.1 文件系统概念1.2 用户权限差异1.3 文件命名规范 2. Linux文件系统分类及特点2.1 ext2(第二扩展文件系统)2.2 ext3(第三扩展文件系统)2.3 ext4(第四扩展文件系统)…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...

密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...

【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验
2024年初,人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目(一款融合大型语言模型能力的云端AI编程IDE)时,技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力,TRAE在WayToAGI等…...