ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenGL-实战篇--Breakout--CollisionDetection--49

2021-11-08 13:58:31  阅读:249  来源: 互联网

标签:实战篇 CollisionDetection glm ResourceManager -- two ball vec2 position


学习链接:中文------英语原文

这一节在上一节的基础上添加了碰撞检测:有两种形状的检测:方形和方形,方形和圆形
具体理论看上面链接。

Game.cpp:

#include "ResourceManager.h"
#include "Game.h"
#include "SpriteRenderer.h"
#include "BallObject.h"

SpriteRenderer* renderer;

Game::Game(GLuint w, GLuint h) :state(GAME_ACTIVE), keys(), width(w), height(h)
{
}

Game::~Game()
{
}

//player
const glm::vec2 PLAYER_SIZE(100, 20);
const GLfloat PLAYER_VELOCITY(500.0f);
GameObject* player;


//ball init velocity
const glm::vec2 INITIAL_BALL_VELOCITY(100.0f, -350.0f);
//ball radius
const GLfloat BALL_RADIUS = 12.5f;

BallObject* ball;

void Game::Init()
{
	//load shader
	ResourceManager::LoadShader("Shaders/Breakout/Sprite.vs", "Shaders/Breakout/Sprite.fs", nullptr, "sprite");
	//config shader
	glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(this->width), static_cast<GLfloat>(this->height), 0.0f, -1.0f, 1.0f);
	ResourceManager::GetShader("sprite").Use().SetInteger("image", 0);
	ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);
	//setup render control
	renderer = new SpriteRenderer(ResourceManager::GetShader("sprite"));
	//load texture
	ResourceManager::LoadTexture("Breakout/Images/background.jpg", GL_TRUE, "background");
	ResourceManager::LoadTexture("Breakout/Images/block.png", GL_FALSE, "block");
	ResourceManager::LoadTexture("Breakout/Images/block_solid.png", GL_FALSE, "block_solid");
	ResourceManager::LoadTexture("Breakout/paddle.png", true, "paddle");//player
	ResourceManager::LoadTexture("Breakout/face.png", true, "ball");//ball
	//load levels
	GameLevel one; one.Load("Breakout/Levels/1.lvl", this->width, this->height * 0.5);
	GameLevel two; two.Load("Breakout/Levels/2.lvl", this->width, this->height * 0.5);
	GameLevel three; three.Load("Breakout/Levels/3.lvl", this->width, this->height * 0.5);
	GameLevel four; four.Load("Breakout/Levels/4.lvl", this->width, this->height * 0.5);

	this->levels.push_back(one);
	this->levels.push_back(two);
	this->levels.push_back(three);
	this->levels.push_back(four);
	this->currentLevel = 0;

	//player init
	glm::vec2 playerPos = glm::vec2(this->width / 2 - PLAYER_SIZE.x / 2, this->height - PLAYER_SIZE.y);
	player = new GameObject(playerPos, PLAYER_SIZE, ResourceManager::GetTexture("paddle"));

	//ball init    原点位置是左上角
	glm::vec2 ballPos = playerPos + glm::vec2(PLAYER_SIZE.x / 2 - BALL_RADIUS, -BALL_RADIUS * 2);
	ball = new BallObject(ballPos, BALL_RADIUS, INITIAL_BALL_VELOCITY, ResourceManager::GetTexture("ball"));
}

void Game::ProcessInput(GLfloat dt)
{
	if (this->state == GAME_ACTIVE)
	{
		GLfloat velocity = PLAYER_VELOCITY * dt;
		//移动挡板
		if (this->keys[GLFW_KEY_A])
		{
			if (player->position.x >= 0)
			{
				player->position.x -= velocity;

				if (ball->stuck)
					ball->position.x -= velocity;
			}
		}
		if (this->keys[GLFW_KEY_D])
		{
			if (player->position.x <= this->width - player->size.x)
			{
				player->position.x += velocity;
				if (ball->stuck)
					ball->position.x += velocity;
			}
		}
		if (this->keys[GLFW_KEY_SPACE])
			ball->stuck = false;
	}
}

void Game::Update(GLfloat dt)
{
	//update ball
	ball->Move(dt, this->width);

	//collision detection
	this->DoCollisions();
}

void Game::Render()
{
	if (this->state == GAME_ACTIVE)
	{
		//绘制背景
		renderer->DrawSprite(ResourceManager::GetTexture("background"), glm::vec2(0, 0), glm::vec2(this->width, this->height), 0.0f);

		//绘制关卡
		this->levels[this->currentLevel].Draw(*renderer);

		//绘制玩家挡板
		player->Draw(*renderer);

		//绘制球
		ball->Draw(*renderer);
	}
}

//碰撞检测::AABB
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;
}

//碰撞检测:方形和圆形
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 加上clampled这样就得到了碰撞箱上距离最近点closest
	glm::vec2 closest=aabb_center+clamped;
	//获得圆心center和最近点closest的矢量,并判断是否length<=radius
	difference=closest-center;
	return glm::length(difference)<one.radius;	
}

void Game::DoCollisions()
{
	for (GameObject& box : this->levels[this->currentLevel].bricks)
	{
		if (!box.destroyed)
		{
			if (CheckCollision(*ball,box))
			{
				if (!box.isSoild)
					box.destroyed = GL_TRUE;
			}
		}
	}
}

标签:实战篇,CollisionDetection,glm,ResourceManager,--,two,ball,vec2,position
来源: https://blog.csdn.net/weixin_41155760/article/details/121206134

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有