阿里云 网站备案,商业空间设计师岗位职责,wordpress 分类目录 图像描述,公司查询网全国企业信息查询官网完整代码见#xff1a;zaizai77/OpenGLTo2DGame: 基于OpenGL制作2D游戏
物体本身的数据来检测碰撞会很复杂#xff0c;一半使用重叠在物体上的更简单的外形来检测。
AABB - AABB 碰撞
AABB代表的是轴对齐碰撞箱(Axis-aligned Bounding Box)#xff0c;碰撞箱是指与场景基…完整代码见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 texCoordsout 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