版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.01.20 |
前言
OpenGL 圖形庫項目中一直也沒用過惠呼,最近也想學(xué)著使用這個圖形庫漱贱,感覺還是很有意思妇垢,也就自然想著好好的總結(jié)一下易迹,希望對大家能有所幫助宰衙。下面內(nèi)容來自歡迎來到OpenGL的世界。
1. OpenGL 圖形庫使用(一) —— 概念基礎(chǔ)
2. OpenGL 圖形庫使用(二) —— 渲染模式睹欲、對象菩浙、擴展和狀態(tài)機
3. OpenGL 圖形庫使用(三) —— 著色器、數(shù)據(jù)類型與輸入輸出
4. OpenGL 圖形庫使用(四) —— Uniform及更多屬性
5. OpenGL 圖形庫使用(五) —— 紋理
6. OpenGL 圖形庫使用(六) —— 變換
7. OpenGL 圖形庫的使用(七)—— 坐標(biāo)系統(tǒng)之五種不同的坐標(biāo)系統(tǒng)(一)
8. OpenGL 圖形庫的使用(八)—— 坐標(biāo)系統(tǒng)之3D效果(二)
9. OpenGL 圖形庫的使用(九)—— 攝像機(一)
10. OpenGL 圖形庫的使用(十)—— 攝像機(二)
11. OpenGL 圖形庫的使用(十一)—— 光照之顏色
12. OpenGL 圖形庫的使用(十二)—— 光照之基礎(chǔ)光照
13. OpenGL 圖形庫的使用(十三)—— 光照之材質(zhì)
14. OpenGL 圖形庫的使用(十四)—— 光照之光照貼圖
15. OpenGL 圖形庫的使用(十五)—— 光照之投光物
16. OpenGL 圖形庫的使用(十六)—— 光照之多光源
17. OpenGL 圖形庫的使用(十七)—— 光照之復(fù)習(xí)總結(jié)
18. OpenGL 圖形庫的使用(十八)—— 模型加載之Assimp
19. OpenGL 圖形庫的使用(十九)—— 模型加載之網(wǎng)格
20. OpenGL 圖形庫的使用(二十)—— 模型加載之模型
21. OpenGL 圖形庫的使用(二十一)—— 高級OpenGL之深度測試
22. OpenGL 圖形庫的使用(二十二)—— 高級OpenGL之模板測試Stencil testing
23. OpenGL 圖形庫的使用(二十三)—— 高級OpenGL之混合Blending
24. OpenGL 圖形庫的使用(二十四)—— 高級OpenGL之面剔除Face culling
25. OpenGL 圖形庫的使用(二十五)—— 高級OpenGL之幀緩沖Framebuffers
26. OpenGL 圖形庫的使用(二十六)—— 高級OpenGL之立方體貼圖Cubemaps
27. OpenGL 圖形庫的使用(二十七)—— 高級OpenGL之高級數(shù)據(jù)Advanced Data
28. OpenGL 圖形庫的使用(二十八)—— 高級OpenGL之高級GLSL Advanced GLSL
29. OpenGL 圖形庫的使用(二十九)—— 高級OpenGL之幾何著色器Geometry Shader
30. OpenGL 圖形庫的使用(三十)—— 高級OpenGL之實例化Instancing
31. OpenGL 圖形庫的使用(三十一)—— 高級OpenGL之抗鋸齒Anti Aliasing
32. OpenGL 圖形庫的使用(三十二)—— 高級光照之高級光照Advanced Lighting
33. OpenGL 圖形庫的使用(三十三)—— 高級光照之Gamma校正Gamma Correction
34. OpenGL 圖形庫的使用(三十四)—— 高級光照之陰影 - 陰影映射Shadow Mapping
35. OpenGL 圖形庫的使用(三十五)—— 高級光照之陰影 - 點陰影Point Shadows
36. OpenGL 圖形庫的使用(三十六)—— 高級光照之法線貼圖Normal Mapping
37. OpenGL 圖形庫的使用(三十七)—— 高級光照之視差貼圖Parallax Mapping
38. OpenGL 圖形庫的使用(三十八)—— 高級光照之HDR
39. OpenGL 圖形庫的使用(三十九)—— 高級光照之泛光
40. OpenGL 圖形庫的使用(四十)—— 高級光照之延遲著色法Deferred Shading
41. OpenGL 圖形庫的使用(四十一)—— 高級光照之SSAO
42. OpenGL 圖形庫的使用(四十二)—— PBR之理論Theory
43. OpenGL 圖形庫的使用(四十三)—— PBR之光照Lighting
44. OpenGL 圖形庫的使用(四十四)—— PBR之幾篇沒有翻譯的英文原稿
45. OpenGL 圖形庫的使用(四十五)—— 實戰(zhàn)之調(diào)試Debugging
46. OpenGL 圖形庫的使用(四十六)—— 實戰(zhàn)之文本渲染Text Rendering
47. OpenGL 圖形庫的使用(四十七)—— 實戰(zhàn)之2D游戲 - Breakout
48. OpenGL 圖形庫的使用(四十八)—— 實戰(zhàn)之2D游戲 - 準(zhǔn)備工作
49. OpenGL 圖形庫的使用(四十九)—— 實戰(zhàn)之2D游戲 - 渲染精靈
50. OpenGL 圖形庫的使用(五十)—— 實戰(zhàn)之2D游戲 - 關(guān)卡
球
此時我們已經(jīng)有了一個包含有很多磚塊和玩家的一個擋板的關(guān)卡句伶。與經(jīng)典的Breakout內(nèi)容相比還差一個球劲蜻。游戲的目的是讓球撞擊所有的磚塊,直到所有的可銷毀磚塊都被銷毀考余,但同時也要滿足條件:球不能碰觸屏幕的下邊緣先嬉。
除了通用的游戲?qū)ο蠼M件,球還需要有半徑和一個布爾值楚堤,該布爾值用于指示球被固定(stuck)在玩家擋板上還是被允許自由運動的狀態(tài)疫蔓。當(dāng)游戲開始時含懊,球被初始固定在玩家擋板上,直到玩家按下任意鍵開始游戲衅胀。
由于球只是一個附帶了一些額外屬性的GameObject
岔乔,所以按照常規(guī)需要創(chuàng)建BallObject類作為GameObject的子類。
class BallObject : public GameObject
{
public:
// 球的狀態(tài)
GLfloat Radius;
GLboolean Stuck;
BallObject();
BallObject(glm::vec2 pos, GLfloat radius, glm::vec2 velocity, Texture2D sprite);
glm::vec2 Move(GLfloat dt, GLuint window_width);
void Reset(glm::vec2 position, glm::vec2 velocity);
};
BallObject
的構(gòu)造函數(shù)不但初始化了其自身的值滚躯,而且實際上也潛在地初始化了GameObject雏门。BallObject類擁有一個Move函數(shù),該函數(shù)用于根據(jù)球的速度來移動球掸掏,并檢查它是否碰到了場景的任何邊界茁影,如果碰到的話就會反轉(zhuǎn)球的速度:
glm::vec2 BallObject::Move(GLfloat dt, GLuint window_width)
{
// 如果沒有被固定在擋板上
if (!this->Stuck)
{
// 移動球
this->Position += this->Velocity * dt;
// 檢查是否在窗口邊界以外,如果是的話反轉(zhuǎn)速度并恢復(fù)到正確的位置
if (this->Position.x <= 0.0f)
{
this->Velocity.x = -this->Velocity.x;
this->Position.x = 0.0f;
}
else if (this->Position.x + this->Size.x >= window_width)
{
this->Velocity.x = -this->Velocity.x;
this->Position.x = window_width - this->Size.x;
}
if (this->Position.y <= 0.0f)
{
this->Velocity.y = -this->Velocity.y;
this->Position.y = 0.0f;
}
}
return this->Position;
}
除了反轉(zhuǎn)球的速度之外丧凤,我們還需要把球沿著邊界重新放置回來募闲。只有在沒有被固定時球才能夠移動。
因為如果球碰觸到底部邊界時玩家會結(jié)束游戲(或失去一條命)愿待,所以在底部邊界沒有代碼來控制球反彈浩螺。我們稍后需要在代碼中某些地方實現(xiàn)這一邏輯。
你可以在下邊看到BallObject
的代碼:
/******************************************************************
** This code is part of Breakout.
**
** Breakout is free software: you can redistribute it and/or modify
** it under the terms of the CC BY 4.0 license as published by
** Creative Commons, either version 4 of the License, or (at your
** option) any later version.
******************************************************************/
#include "ball_object.h"
BallObject::BallObject()
: GameObject(), Radius(12.5f), Stuck(true) { }
BallObject::BallObject(glm::vec2 pos, GLfloat radius, glm::vec2 velocity, Texture2D sprite)
: GameObject(pos, glm::vec2(radius * 2, radius * 2), sprite, glm::vec3(1.0f), velocity), Radius(radius), Stuck(true) { }
glm::vec2 BallObject::Move(GLfloat dt, GLuint window_width)
{
// If not stuck to player board
if (!this->Stuck)
{
// Move the ball
this->Position += this->Velocity * dt;
// Then check if outside window bounds and if so, reverse velocity and restore at correct position
if (this->Position.x <= 0.0f)
{
this->Velocity.x = -this->Velocity.x;
this->Position.x = 0.0f;
}
else if (this->Position.x + this->Size.x >= window_width)
{
this->Velocity.x = -this->Velocity.x;
this->Position.x = window_width - this->Size.x;
}
if (this->Position.y <= 0.0f)
{
this->Velocity.y = -this->Velocity.y;
this->Position.y = 0.0f;
}
}
return this->Position;
}
// Resets the ball to initial Stuck Position (if ball is outside window bounds)
void BallObject::Reset(glm::vec2 position, glm::vec2 velocity)
{
this->Position = position;
this->Velocity = velocity;
this->Stuck = true;
}
首先我們在游戲中添加球仍侥。與玩家擋板相似年扩,我們創(chuàng)建一個球?qū)ο蟛⑶叶x兩個用來初始化球的常量。對于球的紋理访圃,我們會使用在LearnOpenGL Breakout游戲中完美適用的一張圖片:球紋理。
// 初始化球的速度
const glm::vec2 INITIAL_BALL_VELOCITY(100.0f, -350.0f);
// 球的半徑
const GLfloat BALL_RADIUS = 12.5f;
BallObject *Ball;
void Game::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("face"));
}
然后我們在每幀中調(diào)用游戲代碼中Update函數(shù)里的Move函數(shù)來更新球的位置:
void Game::Update(GLfloat dt)
{
Ball->Move(dt, this->Width);
}
除此之外相嵌,由于球初始是固定在擋板上的腿时,我們必須讓玩家能夠從固定的位置重新移動它。我們選擇使用空格鍵來從擋板釋放球饭宾。這意味著我們必須稍微修改ProcessInput
函數(shù):
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;
}
}
現(xiàn)在如果玩家按下了空格鍵批糟,球的Stuck
值會設(shè)置為false。我們還需要更新ProcessInput
函數(shù)看铆,當(dāng)球被固定的時候徽鼎,會跟隨擋板的位置來移動球。
最后我們需要渲染球弹惦,此時這應(yīng)該很顯而易見了:
void Game::Render()
{
if (this->State == GAME_ACTIVE)
{
[...]
Ball->Draw(*Renderer);
}
}
結(jié)果就是球會跟隨著擋板否淤,并且當(dāng)我們按下空格鍵時球開始自由運動。球會在左側(cè)棠隐、右側(cè)和頂部邊界合理地反彈石抡,但看起來不會撞擊任何的磚塊,就像我們可以在下邊的視頻中看到的那樣:
我們要做的就是創(chuàng)建一個或多個函數(shù)用于檢查球?qū)ο笫欠褡矒絷P(guān)卡中的任何磚塊助泽,如果撞擊的話就銷毀磚塊啰扛。這些所謂的碰撞檢測(collision detection
)功能將是我們下一個教程的重點嚎京。
后記
本篇已結(jié)束,后面更精彩~~~