This commit is contained in:
MarcEricMartel 2021-12-07 18:59:50 -05:00
parent 078cb33c27
commit 8e2169420e
16 changed files with 204 additions and 36 deletions

View File

@ -23,6 +23,7 @@
<ClInclude Include="array3d.h" />
<ClInclude Include="audio.h" />
<ClInclude Include="blockinfo.h" />
<ClInclude Include="bullet.h" />
<ClInclude Include="chunk.h" />
<ClInclude Include="define.h" />
<ClInclude Include="engine.h" />
@ -43,6 +44,7 @@
<ItemGroup>
<ClCompile Include="audio.cpp" />
<ClCompile Include="blockinfo.cpp" />
<ClCompile Include="bullet.cpp" />
<ClCompile Include="chunk.cpp" />
<ClCompile Include="engine.cpp" />
<ClCompile Include="main.cpp" />

View File

@ -71,6 +71,9 @@
<ClInclude Include="perlin.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="bullet.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="blockinfo.cpp">
@ -121,5 +124,8 @@
<ClCompile Include="perlin.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="bullet.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -29,7 +29,7 @@ void Audio::Update3DAudio(Vector3f pos, Vector3f dir, Vector3f vel) {
}
void Audio::Create3DAudioObj(irrklang::ISound* sound, const char* name, Vector3f& pos, Vector3f& vel, float volume = 1) {
sound = m_engine->play3D(name, irrklang::vec3df(pos.x, pos.y, pos.z), true, false, true, irrklang::ESM_NO_STREAMING, true);
sound = m_engine->play3D(name, irrklang::vec3df(pos.x, pos.y, pos.z), false, false, true, irrklang::ESM_NO_STREAMING, true);
sound->setVelocity(irrklang::vec3df(vel.x, vel.y, vel.z));
sound->setVolume(volume);
}

32
SQCSim2021/bullet.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "bullet.h"
#include "world.h"
Bullet::Bullet(Player& player) {
m_startpos = m_currentpos = player.GetPOV() + player.GetDirection();
m_velocity = player.GetDirection();
}
Bullet::~Bullet() {}
bool Bullet::Update(World* world, Transformation& tran, float elapsedtime) {
for (int x = 0; x < 1000; ++x) {
m_currentpos += m_velocity * elapsedtime;
if (!world->ChunkAt(m_currentpos))
return true;
else if (world->BlockAt(m_currentpos) != BTYPE_AIR) {
world->ChangeBlockAtPosition(BTYPE_AIR, m_currentpos);
return true;
}
else if ((m_currentpos - m_startpos).Length() > VIEW_DISTANCE) return true;
}
return false;
}
void Bullet::Transpose(int& x, int& z) {
m_currentpos.x -= x * CHUNK_SIZE_X;
m_currentpos.z -= z * CHUNK_SIZE_Z;
m_startpos.x -= x * CHUNK_SIZE_X;
m_startpos.z -= z * CHUNK_SIZE_Z;
}

27
SQCSim2021/bullet.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef BULLET_H__
#define BULLET_H__
#include "audio.h"
#include "player.h"
#include "vertexbuffer.h"
#include "texture.h"
class World;
class Bullet {
public:
Bullet(Player& player);
~Bullet();
bool Update(World* world, Transformation& tran, float elapsedtime);
void Transpose(int& x, int& z);
private:
Vector3f m_startpos;
Vector3f m_currentpos;
Vector3f m_velocity;
};
#endif // BULLET_H__

View File

@ -27,6 +27,7 @@
#define VIEW_DISTANCE 128
#define TEXTURE_SIZE 32
#define MAX_BULLETS 64
#endif
#ifdef NDEBUG
@ -39,6 +40,7 @@
#define VIEW_DISTANCE 1024
#define TEXTURE_SIZE 512
#define MAX_BULLETS 512
#endif

View File

@ -8,7 +8,7 @@ Engine::Engine() { }
Engine::~Engine() {
m_world.CleanUpWorld(m_renderCount, true);
for (int x = 0; x < WORLD_SIZE_X; ++x) // Les destructeurs de Chunks ont de la misère, je les aide un peu!
for (int x = 0; x < WORLD_SIZE_X; ++x)
for (int y = 0; y < WORLD_SIZE_Y; ++y)
if (m_world.GetChunks().Get(x, y))
m_world.GetChunks().Get(x, y)->~Chunk();
@ -45,6 +45,10 @@ void Engine::Init() {
// Objet de musique!
m_audio.ToggleMusicState();
// Array pour les balles.
for (int x = 0; x < MAX_BULLETS; ++x)
m_bullets[x] = nullptr;
// Init Chunks
m_world.GetChunks().Reset(nullptr);
@ -93,7 +97,7 @@ void Engine::LoadResource() {
void Engine::UnloadResource() {}
void Engine::DrawHud(float elapsedTime) {
void Engine::DrawHud(float elapsedTime, BlockType bloc) {
// Setter le blend function , tout ce qui sera noir sera transparent
glDisable(GL_STENCIL_TEST);
glColor4f(1.f, 1.f, 1.f, 1.f);
@ -124,6 +128,12 @@ void Engine::DrawHud(float elapsedTime) {
ss.str("");
ss << " Position : " << m_player.GetPosition();
PrintText(10, 30, ss.str());
ss.str("");
ss << " Block : ";
if (bloc == BTYPE_LAST)
ss << "Weapon.";
else ss << (int)bloc;
PrintText(10, 40, ss.str());
m_textureCrosshair.Bind();
static const int crossSize = 32;
glLoadIdentity();
@ -173,19 +183,26 @@ int Engine::GetFps(float elapsedTime) const { return 1 / elapsedTime; }
void Engine::Render(float elapsedTime) {
static float gameTime = elapsedTime;
static float bulletTime = 0;
static BlockType bloc = 1;
if (elapsedTime > 0.1f) return;
gameTime += elapsedTime;
Transformation all;
Transformation skybox;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Transformations initiales
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
m_player.ApplyPhysics(m_player.GetInput(m_keyW, m_keyS, m_keyA, m_keyD, m_keySpace, m_keylshift, elapsedTime), m_world, elapsedTime);
if (bulletTime > 0.f) bulletTime -= elapsedTime;
if (bulletTime < 0.f) bulletTime = 0.f;
m_player.ApplyPhysics(m_player.GetInput(m_keyW, m_keyS, m_keyA, m_keyD, m_keySpace, (bloc == BTYPE_LAST && bulletTime <= 0.f && m_mouseL), elapsedTime), m_world, elapsedTime, &m_audio);
m_audio.Update3DAudio(m_player.GetPOV(), m_player.GetDirection(), m_player.GetVelocity()); // Ajustement du positionnement 3D avec les coordonnées du joueur et
// son vecteur de vélocité (pour l'effet Doppler)
m_player.ApplyTransformation(all);
@ -193,34 +210,64 @@ void Engine::Render(float elapsedTime) {
m_player.ApplyTransformation(skybox, false); // Version d'ApplyTransformation qui ne tient compte que de la rotation
// (donc l'objet ne bouge pas relativement au joueur, ce qui est pratique pour une skybox!).
static BlockType bloc = 1;
if (m_mouseWU) bloc++;
else if (m_mouseWD) bloc--;
if (bloc == BTYPE_LAST)
bloc = BTYPE_DIRT;
else if (bloc == BTYPE_AIR)
bloc = BTYPE_LAST - 1;
if (bloc == BTYPE_LAST + 1) bloc = BTYPE_AIR + 1;
else if (bloc == BTYPE_AIR) bloc = BTYPE_LAST; // La selection de BTYPE_LAST équipe l'arme.
m_mouseWU = m_mouseWD = false;
if (m_mouseL)
m_world.ChangeBlockAtCursor(bloc, m_player, m_block);
if (m_mouseL) {
if (bloc != BTYPE_LAST)
m_world.ChangeBlockAtCursor(bloc, m_player, m_block);
else if (bulletTime <= 0.f) {
for (int x = 0; x < MAX_BULLETS; ++x) // Ajouter une balle dans l'array (aussi connu sous le nom de "faire pow pow").
if (!m_bullets[x]) {
m_bullets[x] = new Bullet(m_player);
break;
}
else if (x == MAX_BULLETS - 1) { // S'il y a pas d'espace dans l'array, prendre la place de la première balle de l'array.
m_bullets[0]->~Bullet();
m_bullets[0] = new Bullet(m_player);
}
bulletTime = .1f;
m_audio.Create3DAudioObj(m_powpow, AUDIO_PATH "pow.wav", m_player.GetPOV(), m_player.GetDirection() * 10, .5f);
if (m_flash) { // Coupe le rendering et affiche un frame blanc, pour simuler un flash.
glClearColor(.8f, .8f, .8f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClearColor(0.f, 0.f, 0.f, 1.f);
return;
}
}
}
else if (m_mouseR)
m_world.ChangeBlockAtCursor(BTYPE_AIR, m_player, m_block);
m_world.Update(m_renderCount, m_badHitCount, m_player, all, m_shader01, m_textureAtlas, m_perlin, m_blockinfo);
for (int x = 0; x < MAX_BULLETS; ++x) // Array de bullets en jeu.
if (m_bullets[x])
if (m_bullets[x]->Update(&m_world, all, elapsedTime)) {
m_bullets[x]->~Bullet();
m_bullets[x] = nullptr;
}
m_world.Update(m_renderCount, m_bullets, m_player, all, m_shader01, m_textureAtlas, m_perlin, m_blockinfo);
if (m_isSkybox) m_skybox.Render(skybox);
if (m_wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
DrawHud(elapsedTime);
DrawHud(elapsedTime, bloc);
if (m_wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (m_player.GetPosition().y < -20.f)
static bool fell = false;
if (m_player.GetPosition().y < 1.7f && !fell) {
m_audio.Create3DAudioObj(m_scream, AUDIO_PATH "scream.wav", m_player.GetPOV(), m_player.GetVelocity(), 1.f);
fell = true;
}
else if (m_player.GetPosition().y < -20.f) {
m_player = Player(Vector3f(0, CHUNK_SIZE_Y + 1.8f, 0)); // Respawn si le bonho- joueur tombe en bas du monde.
fell = false;
}
}
void Engine::KeyPressEvent(unsigned char key) {
@ -267,6 +314,7 @@ void Engine::KeyPressEvent(unsigned char key) {
m_keySpace = true;
}
break;
case 5: // F - Ignorer
case 24: // Y - Ignorer
case 255: // Fn - Ignorer
case 12: // M - Ignorer
@ -279,6 +327,9 @@ void Engine::KeyPressEvent(unsigned char key) {
void Engine::KeyReleaseEvent(unsigned char key) {
switch (key) {
case 5:
m_flash = !m_flash;
break;
case 12:
m_audio.ToggleMusicState();
break;

View File

@ -14,6 +14,7 @@
#include "array2d.h"
#include "world.h"
#include "perlin.h"
#include "bullet.h"
class Engine : public OpenglContext {
public:
@ -32,7 +33,7 @@ public:
private:
bool LoadTexture(Texture& texture, const std::string& filename, bool stopOnError = true);
void DrawHud(float elapsedTime);
void DrawHud(float elapsedTime, BlockType bloc);
void PrintText(unsigned int x, unsigned int y, const std::string& t);
int GetFps(float elapsedTime) const;
@ -56,8 +57,14 @@ private:
Skybox m_skybox;
Audio m_audio = Audio(AUDIO_PATH "music01.wav");
irrklang::ISound* m_powpow;
irrklang::ISound* m_step;
irrklang::ISound* m_scream;
Player m_player = Player(Vector3f(0, CHUNK_SIZE_Y + 1.8f, 0));
Bullet* m_bullets[MAX_BULLETS];
bool m_keyW = false;
bool m_keyA = false;
bool m_keyS = false;
@ -71,6 +78,7 @@ private:
bool m_mouseWD = false;
bool m_block = false;
bool m_flash = true;
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -18,7 +18,7 @@ void Player::TurnTopBottom(float value) {
else if (m_rotX < -80) m_rotX = -80;
}
Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jump, bool dash, float elapsedTime) {
Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jump, bool shoot, float elapsedTime) {
Vector3f delta = Vector3f(0, 0, 0);
@ -53,16 +53,20 @@ Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jum
delta.x *= .6f;
delta.z *= .6f;
if (jump && !m_airborne) {
delta.y += .32f;
if ((jump || shoot ) && !m_airborne) {
delta.y += jump? .32f: shoot? .1f : 0.f;
m_airborne = true;
}
if (shoot) // Recoil!
TurnTopBottom(-1);
return delta;
}
void Player::ApplyPhysics(Vector3f input, World world, float elapsedTime) {
void Player::ApplyPhysics(Vector3f input, World world, float elapsedTime, Audio* audio) {
static irrklang::ISound* step; // Pour les sons de pas.
static float timing = 0.f;
/* Gestion de collisions */
BlockType bt1, bt2, bt3;
@ -81,6 +85,10 @@ void Player::ApplyPhysics(Vector3f input, World world, float elapsedTime) {
bt1 = world.BlockAt(GetPosition().x, GetPosition().y + .3f, GetPosition().z);
if (bt3 != BTYPE_AIR) {
m_velocity.y = 0;
if (timing == 0.f) {
if (m_airborne) audio->Create3DAudioObj(step, AUDIO_PATH "hit.wav", GetPosition(), GetVelocity(), 1.f);
timing = .3f;
}
m_airborne = false;
}
else if (bt1 != BTYPE_AIR) {
@ -89,6 +97,9 @@ void Player::ApplyPhysics(Vector3f input, World world, float elapsedTime) {
else m_airborne = true;
}
if (timing > 0.f) timing -= elapsedTime;
if (timing < 0.f) timing = 0.f;
bt1 = world.BlockAt(GetPosition().x + input.x, GetPosition().y, GetPosition().z);
bt2 = world.BlockAt(GetPosition().x + input.x, GetPosition().y - 0.9f, GetPosition().z);
bt3 = world.BlockAt(GetPosition().x + input.x, GetPosition().y - 1.7f, GetPosition().z);
@ -137,7 +148,22 @@ void Player::ApplyPhysics(Vector3f input, World world, float elapsedTime) {
m_position += m_velocity;
static float bobbingtime = 0; // Gestion de la caméra
if (bobbingtime <= 360.f) bobbingtime += elapsedTime * 20.f; else bobbingtime = 0;
static bool leftright = false;
static bool isStep = false;
if (bobbingtime <= 360.f)
bobbingtime += elapsedTime * 20.f; else bobbingtime = 0;
if ((sin(bobbingtime) - 0.5f) * (abs(m_velocity.x) + abs(m_velocity.z)) < -.2f && !m_airborne) {
Vector3f vstep;
if (leftright)
vstep = Vector3f(GetPosition().x - GetDirection().x, GetPosition().y, GetPosition().z + GetDirection().z);
else vstep = Vector3f(GetPosition().x + GetDirection().x, GetPosition().y, GetPosition().z - GetDirection().z);
if (!isStep) {
audio->Create3DAudioObj(step, AUDIO_PATH "step.wav", vstep, GetVelocity(), .8f);
}
isStep = true;
}
else isStep = false;
m_POV = m_position.y;
m_POV += m_airborne ? 0 : (sin(bobbingtime) - 0.5f) * (abs(m_velocity.x) + abs(m_velocity.z)) * .2f;
}

View File

@ -2,6 +2,7 @@
#define _PLAYER_H__
#include "vector3.h"
#include "transformation.h"
#include "audio.h"
#include <cmath>
class World;
@ -12,7 +13,7 @@ public:
void TurnLeftRight(float value);
void TurnTopBottom(float value);
Vector3f GetInput(bool front, bool back, bool left, bool right, bool jump, bool dash, float elapsedTime);
void ApplyPhysics(Vector3f input, World world, float elapsedTime);
void ApplyPhysics(Vector3f input, World world, float elapsedTime, Audio* audio);
void ApplyTransformation(Transformation& transformation, bool rel = true) const;
Vector3f GetPosition() const;

View File

@ -38,7 +38,7 @@ BlockType World::BlockAt(const Vector3f& pos, BlockType defaultBlockType) const
return BlockAt(pos.x, pos.y, pos.z, defaultBlockType);
}
void World::TransposeWorld(Player& player) {
void World::TransposeWorld(Player& player, Bullet* bullets[MAX_BULLETS]) {
int x = 0;
int y = 0;
@ -85,6 +85,9 @@ void World::TransposeWorld(Player& player) {
m_center[0] += x; m_center[1] += y;
player.Teleport(x, y);
for (int index = 0; index < MAX_BULLETS; ++index)
if (bullets[index]) bullets[index]->Transpose(x, y);
}
void World::CleanUpWorld(int& deleteframes, bool clear = false) {
@ -106,12 +109,12 @@ void World::GetScope(int& x, int& y) {
y = m_center[1];
}
void World::Update(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
void World::Update(int& rendercount, Bullet* bullets[MAX_BULLETS], Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
glStencilFunc(GL_EQUAL, 1, 0x00);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
atlas.Bind();
RenderWorld(rendercount, badhitcount, player, world, shader);
TransposeWorld(player);
RenderWorld(rendercount, player, world, shader);
TransposeWorld(player, bullets);
UpdateWorld(player, perlin, blockinfo);
shader.Disable();
glStencilFunc(GL_GREATER, 1, 0xFF);
@ -273,10 +276,19 @@ void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block
}
}
void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader) {
void World::ChangeBlockAtPosition(BlockType blockType, Vector3f pos) {
int bx = (int)pos.x % CHUNK_SIZE_X;
int by = (int)pos.y % CHUNK_SIZE_Y;
int bz = (int)pos.z % CHUNK_SIZE_Z;
ChunkAt(pos)->SetBlock(bx, by, bz, blockType, this);
ChunkAt(pos)->MakeModified();
}
void World::RenderWorld(int& rendercount, Player& player, Transformation& world, Shader& shader) {
shader.Use();
rendercount = 0;
badhitcount = 0;
Vector3f angle;
Vector3f cursor;
Vector3f direct = player.GetDirection();
@ -341,10 +353,8 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
int chx, chy;
ChunkAt(cursor)->GetPosition(chx, chy);
for (int index = 0; index < rendercount; ++index) // Permet de vérifier seulement contre celles ajoutées dans la frame, et ne pas avoir à refaire l'array à chaque frame.
if (renderManifest[index].x == chx && renderManifest[index].z == chy) {
if (renderManifest[index].x == chx && renderManifest[index].z == chy)
valide = false;
++badhitcount;
}
if (valide) renderManifest[rendercount++] = Vector3f(chx, (VIEW_DISTANCE - (pos - cursor).Length() * 2.f + 128) / (float)VIEW_DISTANCE, chy);
}

View File

@ -8,6 +8,7 @@
#include "transformation.h"
#include "perlin.h"
#include "shader.h"
#include "bullet.h"
#include "textureatlas.h"
#include <fstream>
#include <string>
@ -15,6 +16,7 @@
class Chunk;
class Player;
class Bullet;
class World {
public:
@ -29,11 +31,12 @@ public:
BlockType BlockAt(float x, float y, float z, BlockType defaultBlockType = BTYPE_AIR) const;
BlockType BlockAt(const Vector3f& pos, BlockType defaultBlockType = BTYPE_AIR) const;
void Update(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
void Update(int& rendercount, Bullet* bullets[MAX_BULLETS], Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
void GetScope(int& x, int& y);
void ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block);
void ChangeBlockAtPosition(BlockType blockType, Vector3f pos);
void CleanUpWorld(int& deleteframes, bool clear);
private:
Array2d<Chunk*> m_chunks = Array2d<Chunk*>(WORLD_SIZE_X, WORLD_SIZE_Y);
@ -43,9 +46,9 @@ private:
bool GenerateChunk(int x, int y, Perlin& perlin);
void UpdateChunk(int& generates, int& updates, int chx, int chy, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
void RenderWorld(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader);
void RenderWorld(int& rendercount, Player& player, Transformation& world, Shader& shader);
void UpdateWorld(Player& player, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
void TransposeWorld(Player& player);
void TransposeWorld(Player& player, Bullet* bullets[MAX_BULLETS]);
};
#endif // WORLD_H__