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(第四扩展文件系统)…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
