732 lines
22 KiB
C++
Executable File
732 lines
22 KiB
C++
Executable File
#include "../H/engine.h"
|
||
#include "../H/transformation.h"
|
||
#include <algorithm>
|
||
#include <cmath>
|
||
#include <iostream>
|
||
#include <fstream>
|
||
|
||
Engine::Engine() : m_p1(Vector3f(VIEW_DISTANCE,20,VIEW_DISTANCE)), m_textureAtlas(BTYPE_LAST), m_chunks(Array2d<Chunk*>(VIEW_DISTANCE * 2 / CHUNK_SIZE_X, VIEW_DISTANCE * 2 / CHUNK_SIZE_Z)), m_currentBlock(Vector4f(0,0,0,0)), m_currentMob(Vector3f(0,0,0),0,0)
|
||
{
|
||
}
|
||
|
||
Engine::~Engine()
|
||
{
|
||
SaveGame();
|
||
}
|
||
|
||
void Engine::LoadGame(std::ifstream SaveFile){
|
||
std::cout << "LOADING THE GAME" << std::endl;
|
||
if (SaveFile.is_open())
|
||
{
|
||
std::string Block;
|
||
|
||
while (std::getline(SaveFile, Block))
|
||
{
|
||
int notdigit = 0;
|
||
std::string x,y,z,t;
|
||
for (int i = 0; i < Block.length(); i++)
|
||
{
|
||
if (isdigit(Block[i]))
|
||
{
|
||
if (notdigit < 2)
|
||
x += Block[i];
|
||
else if (notdigit < 3)
|
||
y += Block[i];
|
||
else if (notdigit < 4)
|
||
z += Block[i];
|
||
else if (notdigit < 5)
|
||
t += Block[i];
|
||
}
|
||
else
|
||
notdigit++;
|
||
}
|
||
Vector4f Bloc(stoi(x), stoi(y), stoi(z), stoi(t));
|
||
m_ModifiedBlocks.push_front(Bloc);
|
||
SetBlockAt(stoi(x), stoi(y), stoi(z), stoi(t));
|
||
}
|
||
|
||
std::cout << "GAME LOADED" << std::endl;
|
||
SaveFile.close();
|
||
}
|
||
else
|
||
std::cout << "Problem opening the save file :(" << std::endl;
|
||
}
|
||
|
||
void Engine::SaveGame(){
|
||
std::cout << "SAVING THE GAME" << std::endl;
|
||
|
||
std::ofstream SaveFile("SaveFile");
|
||
if(SaveFile.is_open()){
|
||
for (size_t i = 0; i < m_ModifiedBlocks.size() + 1; i++)
|
||
{
|
||
if (m_ModifiedBlocks.front().x >= 0 && m_ModifiedBlocks.front().y >= 0 && m_ModifiedBlocks.front().z >= 0){
|
||
SaveFile << "{" << m_ModifiedBlocks.front().x << ";" << m_ModifiedBlocks.front().y << ";" << m_ModifiedBlocks.front().z << ";" << m_ModifiedBlocks.front().t << "}" << std::endl;
|
||
}
|
||
m_ModifiedBlocks.pop_front();
|
||
}
|
||
SaveFile.close();
|
||
std::cout << "GAME SAVED" << std::endl;
|
||
}
|
||
else
|
||
std::cout << "Problem writing to the save file :(" << std::endl;
|
||
}
|
||
|
||
void Engine::Init()
|
||
{
|
||
//glEnable(GL_CULL_FACE);
|
||
|
||
// Initialize GLEW
|
||
GLenum glewErr = glewInit();
|
||
if ( glewErr != GLEW_OK )
|
||
{
|
||
std :: cerr << " ERREUR GLEW : " << glewGetErrorString(glewErr) << std :: endl ;
|
||
abort();
|
||
}
|
||
|
||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||
glEnable(GL_TEXTURE_2D);
|
||
|
||
glMatrixMode(GL_PROJECTION);
|
||
glLoadIdentity();
|
||
gluPerspective(45.0f, (float)Width() / (float)Height(), 0.0001f, 1000.0f);
|
||
glEnable(GL_DEPTH_TEST);
|
||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||
glShadeModel(GL_SMOOTH);
|
||
glEnable(GL_LIGHTING);
|
||
glEnable(GL_LINE_SMOOTH);
|
||
|
||
// Light
|
||
GLfloat light0Pos[4] = { 0.0f, CHUNK_SIZE_Y, 0.0f, 1.0f };
|
||
GLfloat light0Amb[4] = { 0.9f, 0.9f, 0.9f, 1.0f };
|
||
GLfloat light0Diff[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||
GLfloat light0Spec[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||
|
||
glEnable(GL_LIGHT0);
|
||
glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
|
||
glLightfv(GL_LIGHT0, GL_AMBIENT, light0Amb);
|
||
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diff);
|
||
glLightfv(GL_LIGHT0, GL_SPECULAR, light0Spec);
|
||
|
||
CenterMouse();
|
||
HideCursor();
|
||
}
|
||
|
||
void Engine::DeInit()
|
||
{
|
||
}
|
||
|
||
void Engine::LoadResource()
|
||
{
|
||
LoadTexture(m_textureCrosshair, TEXTURE_PATH "cross.bmp");
|
||
LoadTexture(m_textureFont, TEXTURE_PATH "font.bmp");
|
||
LoadTexture(m_textureMob, TEXTURE_PATH "mob.png");
|
||
TextureAtlas::TextureIndex texDarkIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "dark.png");
|
||
TextureAtlas::TextureIndex texDarkerIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "darker.png");
|
||
TextureAtlas::TextureIndex texLightIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "light.png");
|
||
TextureAtlas::TextureIndex texLighterIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "lighter.png");
|
||
|
||
float u,v,w,h;
|
||
m_textureAtlas.TextureIndexToCoord(texDarkerIndex, u,v,w,h);
|
||
m_bi[BTYPE_DARKER].SetUVWH(u, v, w, h);
|
||
m_textureAtlas.TextureIndexToCoord(texDarkIndex, u,v,w,h);
|
||
m_bi[BTYPE_DARK].SetUVWH(u, v, w, h);
|
||
m_textureAtlas.TextureIndexToCoord(texLighterIndex, u,v,w,h);
|
||
m_bi[BTYPE_LIGHTER].SetUVWH(u, v, w, h);
|
||
m_textureAtlas.TextureIndexToCoord(texLightIndex, u,v,w,h);
|
||
m_bi[BTYPE_LIGHT].SetUVWH(u, v, w, h);
|
||
|
||
if(!m_textureAtlas.Generate(1024, false))
|
||
{
|
||
std::cout << "Unable to generate texture atlas ..." << std::endl;
|
||
abort();
|
||
}
|
||
|
||
std::cout << "Loading and compiling shaders ..." << std::endl;
|
||
if (!m_shader01.Load(SHADER_PATH "shader01.vert", SHADER_PATH "shader01.frag", true))
|
||
{
|
||
std::cout << " Failed to load shader " << std::endl;
|
||
exit(1);
|
||
}
|
||
|
||
for (int x = 0; x < (VIEW_DISTANCE * 2 / CHUNK_SIZE_X); x++)
|
||
{
|
||
for (int z = 0; z < (VIEW_DISTANCE * 2 / CHUNK_SIZE_Z); z++)
|
||
{
|
||
m_chunks.Set(x, z, new Chunk(x * CHUNK_SIZE_X, z * CHUNK_SIZE_Z));
|
||
}
|
||
}
|
||
m_chunks.Set(15, 15, new Chunk(15 * CHUNK_SIZE_X, 15 * CHUNK_SIZE_Z));
|
||
|
||
LoadGame(std::ifstream("SaveFile"));
|
||
}
|
||
|
||
void Engine::UnloadResource()
|
||
{
|
||
}
|
||
|
||
void Engine::Render(float elapsedTime)
|
||
{
|
||
static float gameTime = elapsedTime;
|
||
|
||
gameTime += elapsedTime;
|
||
|
||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||
|
||
// Transformations initiales
|
||
glMatrixMode(GL_MODELVIEW);
|
||
glLoadIdentity();
|
||
|
||
Transformation player_move;
|
||
bool OnGround = false;
|
||
Vector3f pos = m_p1.Position();
|
||
Vector3f delta = m_p1.SimulateMove(m_keyW, m_keyS, m_keyA, m_keyD, m_shift, elapsedTime);
|
||
delta.y = -0.1;
|
||
float jumpvalue = 0;
|
||
BlockType bt1, bt2, bt3;
|
||
|
||
bt1 = BlockAt(pos.x, pos.y - 1.7f, pos.z, BTYPE_DARK);
|
||
if (bt1 != BTYPE_AIR)
|
||
OnGround = true;
|
||
|
||
bt2 = BlockAt(pos.x, pos.y + delta.y, pos.z, BTYPE_DARK);
|
||
if (bt2 != BTYPE_AIR)
|
||
m_jumpsize = 1.6;
|
||
|
||
m_jumpsize += m_p1.SimulateJump(m_space, m_InJump, jumpvalue, OnGround, m_jumpsize);
|
||
|
||
//Collisions for x:
|
||
bt1 = BlockAt(pos.x + delta.x, pos.y, pos.z, BTYPE_AIR);
|
||
bt2 = BlockAt(pos.x + delta.x, pos.y - 0.9f, pos.z, BTYPE_AIR);
|
||
bt3 = BlockAt(pos.x + delta.x, pos.y - 1.6f, pos.z, BTYPE_AIR);
|
||
if(bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR)
|
||
delta.x = 0;
|
||
|
||
// Collisions for y
|
||
bt1 = BlockAt(pos.x, pos.y - 1.7f, pos.z, BTYPE_DARK);
|
||
if(bt1 != BTYPE_AIR){
|
||
delta.y = 0;
|
||
}
|
||
|
||
//Colisions for z
|
||
bt1 = BlockAt(pos.x, pos.y, pos.z + delta.z, BTYPE_AIR);
|
||
bt2 = BlockAt(pos.x, pos.y - 0.9f, pos.z + delta.z, BTYPE_AIR);
|
||
bt3 = BlockAt(pos.x, pos.y - 1.6f, pos.z + delta.z, BTYPE_AIR);
|
||
if(bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR)
|
||
delta.z = 0;
|
||
|
||
pos.y += jumpvalue;
|
||
pos += delta;
|
||
m_p1.SetPosition(pos);
|
||
|
||
m_p1.ApplyTransformation(player_move);
|
||
player_move.Use();
|
||
m_textureAtlas.Bind();
|
||
|
||
//translation
|
||
player_move.ApplyTranslation(0.5f,0.5f,0.5f);
|
||
|
||
//use the above
|
||
player_move.Use();
|
||
m_shader01.Use();
|
||
|
||
for (int x = 0; x < (VIEW_DISTANCE * 2 / CHUNK_SIZE_X); x++)
|
||
{
|
||
for (int z = 0; z < (VIEW_DISTANCE * 2 / CHUNK_SIZE_Z); z++)
|
||
{
|
||
if (m_chunks.Get(x,z)->IsDirty())
|
||
m_chunks.Get(x,z)->Update(m_bi);
|
||
m_chunks.Get(x,z)->Render();
|
||
}
|
||
}
|
||
Shader::Disable();
|
||
|
||
m_textureMob.Bind();
|
||
for (int i = 0; i < m_mobs.size(); i++)
|
||
{
|
||
if (m_mobs[i].Health() <= 0)
|
||
m_mobs.erase(m_mobs.begin() + i);
|
||
|
||
Vector3f posMob = m_mobs[i].Position();
|
||
if ((posMob.x <= pos.x + 0.1 && posMob.x >= pos.x - 0.1) && (posMob.y <= pos.y + 0.1 && posMob.y >= pos.y - 0.1) && (posMob.z <= pos.z + 0.1 && posMob.z >= pos.z - 0.1))
|
||
{
|
||
m_mobs[i].Damage(m_p1);
|
||
m_mobs[i].SetPosition(Vector3f(posMob.x - 5, posMob.y + 5, posMob.z - 5));
|
||
}
|
||
m_mobs[i].Move(m_p1);
|
||
m_mobs[i].RenderMob();
|
||
}
|
||
|
||
m_points = m_mobs.size() * 100;
|
||
|
||
if(m_wireframe)
|
||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||
DrawHud(elapsedTime);
|
||
if(m_wireframe)
|
||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||
|
||
if (m_p1.Health() <= 0)
|
||
{
|
||
SaveGame();
|
||
Stop();
|
||
}
|
||
}
|
||
|
||
void Engine::KeyPressEvent(unsigned char key)
|
||
{
|
||
switch(key)
|
||
{
|
||
case 36: // ESC
|
||
SaveGame();
|
||
Stop();
|
||
break;
|
||
case 94: // F10
|
||
SetFullscreen(!IsFullscreen());
|
||
break;
|
||
case 38: // Shift
|
||
m_shift = true;
|
||
m_run = true;
|
||
break;
|
||
case 22: // W
|
||
m_keyW = true;
|
||
m_walk = true;
|
||
break;
|
||
case 0: // A
|
||
m_keyA = true;
|
||
m_walk = true;
|
||
break;
|
||
case 18: // S
|
||
m_keyS = true;
|
||
m_walk = true;
|
||
break;
|
||
case 3: // D
|
||
m_keyD = true;
|
||
m_walk = true;
|
||
break;
|
||
case 57: // spacebar
|
||
m_space = true;
|
||
break;
|
||
case 60: //tab
|
||
if (m_selectedbloc <= BTYPE_LIGHTER)
|
||
m_selectedbloc++;
|
||
else
|
||
m_selectedbloc = BTYPE_DARK;
|
||
|
||
break;
|
||
default:
|
||
std::cout << "Unhandled key: " << (int)key << std::endl;
|
||
}
|
||
}
|
||
|
||
void Engine::KeyReleaseEvent(unsigned char key)
|
||
{
|
||
switch(key)
|
||
{
|
||
case 38: // Shift
|
||
m_shift = false;
|
||
m_run = false;
|
||
break;
|
||
case 22: // W
|
||
m_keyW = false;
|
||
if (!m_keyW && !m_keyS && !m_keyD && !m_keyA)
|
||
m_walk = false;
|
||
break;
|
||
case 0: // A
|
||
m_keyA = false;
|
||
if (!m_keyW && !m_keyS && !m_keyD && !m_keyA)
|
||
m_walk = false;
|
||
break;
|
||
case 18: // S
|
||
m_keyS = false;
|
||
if (!m_keyW && !m_keyS && !m_keyD && !m_keyA)
|
||
m_walk = false;
|
||
break;
|
||
case 3: // D
|
||
m_keyD = false;
|
||
if (!m_keyW && !m_keyS && !m_keyD && !m_keyA)
|
||
m_walk = false;
|
||
break;
|
||
case 57: // spacebar
|
||
m_space = false;
|
||
break;
|
||
case 24: // Y
|
||
m_wireframe = !m_wireframe;
|
||
if(m_wireframe)
|
||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||
else
|
||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||
break;
|
||
}
|
||
}
|
||
|
||
void Engine::MouseMoveEvent(int x, int y)
|
||
{
|
||
// Centrer la souris seulement si elle n'est pas d<>j<EFBFBD> centr<74>e
|
||
// Il est n<>cessaire de faire la v<>rification pour <20>viter de tomber
|
||
// dans une boucle infinie o<> l'appel <20> CenterMouse g<>n<EFBFBD>re un
|
||
// MouseMoveEvent, qui rapelle CenterMouse qui rapelle un autre
|
||
// MouseMoveEvent, etc
|
||
if(x == (Width() / 2) && y == (Height() / 2))
|
||
return;
|
||
|
||
MakeRelativeToCenter(x, y);
|
||
//m_p1.TurnLeftRight(y);
|
||
//m_p1.TurnTopBottom(x);
|
||
m_p1.TurnCamera(x, y);
|
||
CenterMouse();
|
||
}
|
||
|
||
void Engine::MousePressEvent(const MOUSE_BUTTON& button, int x, int y)
|
||
{
|
||
switch (button)
|
||
{
|
||
case 1:
|
||
if(!m_currentMob.isNull())
|
||
HitMob();
|
||
else
|
||
DestroyBlocGenerateMob();
|
||
break;
|
||
case 4:
|
||
CreateBloc();
|
||
break;
|
||
default:
|
||
std::cout << "Unhandled mouse action" << std::endl;
|
||
break;
|
||
}
|
||
}
|
||
|
||
void Engine::MouseReleaseEvent(const MOUSE_BUTTON& button, int x, int y)
|
||
{
|
||
}
|
||
|
||
bool Engine::LoadTexture(Texture& texture, const std::string& filename, bool stopOnError)
|
||
{
|
||
texture.Load(filename);
|
||
if(!texture.IsValid())
|
||
{
|
||
std::cerr << "Unable to load texture (" << filename << ")" << std::endl;
|
||
if(stopOnError)
|
||
Stop();
|
||
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
int Engine::GetFps(float elapsedTime){
|
||
return 1 / elapsedTime;
|
||
}
|
||
|
||
void Engine::DrawHud(float elapsedTime)
|
||
{
|
||
// Set the blend func, all that is black will be transparent
|
||
glDisable(GL_LIGHTING);
|
||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||
glBlendFunc(GL_SRC_ALPHA , GL_ONE);
|
||
glEnable(GL_BLEND);
|
||
glDisable(GL_DEPTH_TEST);
|
||
glMatrixMode(GL_PROJECTION);
|
||
glPushMatrix();
|
||
glLoadIdentity();
|
||
glOrtho(0, Width (), 0, Height (), -1, 1);
|
||
glMatrixMode(GL_MODELVIEW);
|
||
glPushMatrix();
|
||
|
||
// Font
|
||
m_textureFont.Bind();
|
||
std::ostringstream ss;
|
||
|
||
for (int i = 0; i < m_mobs.size(); i++)
|
||
{
|
||
ss << "Mob#" << i << " health: " << m_mobs[i].Health();
|
||
PrintText(10, Height () - 40 - (i * 10), ss.str());
|
||
ss.str("");
|
||
}
|
||
|
||
ss << "Score:" << m_points;
|
||
PrintText(Width() / 2, Height () - 25, ss.str());
|
||
ss.str("");
|
||
ss << "Health:" << m_p1.Health();
|
||
PrintText(Width() / 2, Height () - 35, ss.str());
|
||
ss.str("");
|
||
ss << "Fps: " << GetFps(elapsedTime);
|
||
PrintText(10, Height () - 25, ss.str());
|
||
ss.str("");
|
||
ss << "Selected bloc type: " << m_selectedbloc;
|
||
PrintText(10, 20, ss.str());
|
||
ss.str("");
|
||
ss << "Position: " << m_p1.Position();
|
||
PrintText (10, 10, ss.str());
|
||
|
||
// Crosshair
|
||
m_textureCrosshair.Bind();
|
||
static const int crossSize = 32;
|
||
glLoadIdentity();
|
||
glTranslated(Width () / 2 - crossSize / 2, Height () / 2 - crossSize / 2, 0);
|
||
glBegin(GL_QUADS);
|
||
glTexCoord2f(0, 0);
|
||
glVertex2i(0, 0);
|
||
glTexCoord2f(1, 0);
|
||
glVertex2i(crossSize, 0);
|
||
glTexCoord2f(1, 1);
|
||
glVertex2i(crossSize, crossSize);
|
||
glTexCoord2f(0, 1);
|
||
glVertex2i(0, crossSize);
|
||
glEnd();
|
||
|
||
glEnable(GL_LIGHTING);
|
||
glDisable(GL_BLEND);
|
||
glEnable(GL_DEPTH_TEST);
|
||
glMatrixMode(GL_PROJECTION);
|
||
glPopMatrix();
|
||
glMatrixMode(GL_MODELVIEW);
|
||
glPopMatrix();
|
||
}
|
||
|
||
void Engine::PrintText(unsigned int x, unsigned int y, const std::string& t)
|
||
{
|
||
glLoadIdentity();
|
||
glTranslated(x, y, 0);
|
||
for(unsigned int i = 0; i<t.length(); ++i)
|
||
{
|
||
float left = (float)((t[i] - 32) % 16) / 16.0f;
|
||
float top = (float)((t[i] - 32) / 16) / 16.0f;
|
||
top += 0.5f;
|
||
glBegin(GL_QUADS);
|
||
glTexCoord2f(left, 1.0f - top - 0.0625f);
|
||
glVertex2f(0, 0);
|
||
glTexCoord2f(left + 0.0625f, 1.0f - top - 0.0625f);
|
||
glVertex2f(12, 0);
|
||
glTexCoord2f(left + 0.0625f, 1.0f - top);
|
||
glVertex2f(12, 12);
|
||
glTexCoord2f(left, 1.0f - top);
|
||
glVertex2f(0, 12);
|
||
glEnd();
|
||
glTranslated(8, 0, 0);
|
||
}
|
||
}
|
||
|
||
Chunk* Engine::ChunkAt(float x, float y, float z) const
|
||
{
|
||
int cx = (int)x / CHUNK_SIZE_X;
|
||
int cz = (int)z / CHUNK_SIZE_Z;
|
||
if (cx > VIEW_DISTANCE * 2 / CHUNK_SIZE_X || cz > VIEW_DISTANCE * 2 / CHUNK_SIZE_Z || cx < 0 || cz < 0)
|
||
{
|
||
std::cout << "WRONG CHUNK POSITION" << std::endl;
|
||
return nullptr;
|
||
}
|
||
|
||
|
||
return m_chunks.Get(cx, cz);
|
||
}
|
||
|
||
Chunk* Engine::ChunkAt(const Vector3<float>& pos) const
|
||
{
|
||
return ChunkAt(pos.x, pos.y, pos.z);
|
||
}
|
||
|
||
BlockType Engine::BlockAt(float x, float y, float z, BlockType defaultBlockType) const
|
||
{
|
||
Chunk* c = ChunkAt(x, y, z);
|
||
|
||
if(!c)
|
||
return defaultBlockType;
|
||
|
||
int bx = (int)x % CHUNK_SIZE_X;
|
||
int by = (int)y % CHUNK_SIZE_Y;
|
||
int bz = (int)z % CHUNK_SIZE_Z;
|
||
|
||
return c->GetBlock(bx, by, bz);
|
||
}
|
||
|
||
void Engine::SetBlockAt(float x, float y, float z, BlockType BlockToSet) const{
|
||
Chunk* c = ChunkAt(x, y, z);
|
||
|
||
int bx = (int)x % CHUNK_SIZE_X;
|
||
int by = (int)y % CHUNK_SIZE_Y;
|
||
int bz = (int)z % CHUNK_SIZE_Z;
|
||
|
||
c->SetBlock(bx, by, bz, BlockToSet);
|
||
}
|
||
|
||
bool Engine::IsWalking(){
|
||
if (m_keyA || m_keyD || m_keyS || m_keyW)
|
||
return true;
|
||
else
|
||
return false;
|
||
}
|
||
|
||
static bool EqualWithEpsilon(const float& v1, const float& v2, float epsilon = float(0.0001))
|
||
{
|
||
return (fabs(v2 - v1) < epsilon);
|
||
}
|
||
|
||
static bool InRangeWithEpsilon(const float& v, const float& vinf, const float& vsup, float epsilon = float(0.0001))
|
||
{
|
||
return (v >= vinf - epsilon && v <= vsup + epsilon);
|
||
}
|
||
|
||
void Engine::GetBlocAtCursor()
|
||
{
|
||
int x = Width() / 2;
|
||
int y = Height() / 2;
|
||
|
||
GLint viewport[4];
|
||
GLdouble modelview[16];
|
||
GLdouble projection[16];
|
||
GLfloat winX, winY, winZ;
|
||
GLdouble posX, posY, posZ;
|
||
|
||
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
|
||
glGetDoublev(GL_PROJECTION_MATRIX, projection);
|
||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||
|
||
winX = (float)x;
|
||
winY = (float)viewport[3] - (float)y;
|
||
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
|
||
|
||
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
|
||
|
||
posX += .5f;
|
||
posY += .5f;
|
||
posZ += .5f;
|
||
|
||
// Le cast vers int marche juste pour les valeurs entiere, utiliser une fonction de la libc si besoin
|
||
// de valeurs negatives
|
||
int px = (int)(posX);
|
||
int py = (int)(posY);
|
||
int pz = (int)(posZ);
|
||
|
||
bool found = false;
|
||
|
||
if((m_p1.Position() - Vector3f((float)posX, (float)posY, (float)posZ)).Length() < MAX_SELECTION_DISTANCE)
|
||
{
|
||
// Apres avoir determine la position du bloc en utilisant la partie entiere du hit
|
||
// point retourne par opengl, on doit verifier de chaque cote du bloc trouve pour trouver
|
||
// le vrai bloc. Le vrai bloc peut etre different a cause d'erreurs de precision de nos
|
||
// nombres flottants (si z = 14.999 par exemple, et qu'il n'y a pas de blocs a la position
|
||
// 14 (apres arrondi vers l'entier) on doit trouver et retourner le bloc en position 15 s'il existe
|
||
// A cause des erreurs de precisions, ils arrive que le cote d'un bloc qui doit pourtant etre a la
|
||
// position 15 par exemple nous retourne plutot la position 15.0001
|
||
for(int x = px - 1; !found && x <= px + 1; ++x)
|
||
{
|
||
for(int y = py - 1; !found && x >= 0 && y <= py + 1; ++y)
|
||
{
|
||
for(int z = pz - 1; !found && y >= 0 && z <= pz + 1; ++z)
|
||
{
|
||
if(z >= 0)
|
||
{
|
||
Mob mob = MobAt((float)x,(float)y, (float)z);
|
||
if (!mob.isNull())
|
||
m_currentMob = mob;
|
||
|
||
BlockType bt = BlockAt((float)x,(float)y, (float)z, BTYPE_AIR);
|
||
if(bt == BTYPE_AIR)
|
||
continue;
|
||
|
||
// Skip water blocs
|
||
//if(bloc->Type == BT_WATER)
|
||
// continue;
|
||
|
||
m_currentBlock.x = x;
|
||
m_currentBlock.y = y;
|
||
m_currentBlock.z = z;
|
||
m_currentBlock.t = bt;
|
||
|
||
if(InRangeWithEpsilon((float)posX, (float)x, (float)x + 1.f, 0.05f) && InRangeWithEpsilon((float)posY, (float)y, (float)y + 1.f, 0.05f) && InRangeWithEpsilon((float)posZ, (float)z, (float)z + 1.f, 0.05f))
|
||
{
|
||
found = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(!found)
|
||
{
|
||
m_currentBlock.x = -1;
|
||
}
|
||
else
|
||
{
|
||
// Find on which face of the bloc we got an hit
|
||
m_currentFaceNormal.Zero();
|
||
|
||
const float epsilon = 0.09f;
|
||
|
||
// Front et back:
|
||
if(EqualWithEpsilon((float)posZ, (float)m_currentBlock.z, epsilon))
|
||
m_currentFaceNormal.z = -1;
|
||
else if(EqualWithEpsilon((float)posZ, (float)m_currentBlock.z + 1.f, epsilon))
|
||
m_currentFaceNormal.z = 1;
|
||
else if(EqualWithEpsilon((float)posX, (float)m_currentBlock.x, epsilon))
|
||
m_currentFaceNormal.x = -1;
|
||
else if(EqualWithEpsilon((float)posX, (float)m_currentBlock.x + 1.f, epsilon))
|
||
m_currentFaceNormal.x = 1;
|
||
else if(EqualWithEpsilon((float)posY, (float)m_currentBlock.y, epsilon))
|
||
m_currentFaceNormal.y = -1;
|
||
else if(EqualWithEpsilon((float)posY, (float)m_currentBlock.y + 1.f, epsilon))
|
||
m_currentFaceNormal.y = 1;
|
||
}
|
||
}
|
||
|
||
void Engine::CreateBloc(){
|
||
GetBlocAtCursor();
|
||
|
||
Vector4f Bloc(m_currentBlock.x + m_currentFaceNormal.x, m_currentBlock.y + m_currentFaceNormal.y, m_currentBlock.z + m_currentFaceNormal.z, m_selectedbloc);
|
||
m_ModifiedBlocks.push_front(Bloc);
|
||
|
||
SetBlockAt(m_currentBlock.x + m_currentFaceNormal.x, m_currentBlock.y + m_currentFaceNormal.y, m_currentBlock.z + m_currentFaceNormal.z, m_selectedbloc);
|
||
}
|
||
|
||
void Engine::DestroyBloc(){
|
||
GetBlocAtCursor();
|
||
|
||
Vector4f Bloc(m_currentBlock.x, m_currentBlock.y, m_currentBlock.z, BTYPE_AIR);
|
||
m_ModifiedBlocks.push_front(Bloc);
|
||
|
||
SetBlockAt(m_currentBlock.x, m_currentBlock.y, m_currentBlock.z, BTYPE_AIR);
|
||
}
|
||
|
||
void Engine::DestroyBlocGenerateMob(){
|
||
GetBlocAtCursor();
|
||
|
||
Vector4f Bloc(m_currentBlock.x, m_currentBlock.y, m_currentBlock.z, BTYPE_AIR);
|
||
m_ModifiedBlocks.push_front(Bloc);
|
||
|
||
SetBlockAt(m_currentBlock.x, m_currentBlock.y, m_currentBlock.z, BTYPE_AIR);
|
||
|
||
Vector3f v(m_currentBlock.x, m_currentBlock.y, m_currentBlock.z);
|
||
int dmg;
|
||
if(m_currentBlock.t == BTYPE_AIR)
|
||
dmg = 1000;
|
||
else
|
||
dmg = m_currentBlock.t;
|
||
|
||
Mob NewMob(v, dmg, dmg);
|
||
m_mobs.push_back(NewMob);
|
||
}
|
||
|
||
void Engine::HitMob(){
|
||
GetBlocAtCursor();
|
||
|
||
for (int i = 0; i < m_mobs.size(); i++)
|
||
{
|
||
if(m_mobs[i].isEqual(m_currentMob))
|
||
{
|
||
m_p1.Damage(m_mobs[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
Mob Engine::MobAt(int x, int y, int z){
|
||
for (int i = 0; i < m_mobs.size(); i++)
|
||
{
|
||
Vector3f posMob = m_mobs[i].Position();
|
||
if((posMob.x <= x + 0.5f && posMob.x >= x - 0.5f) && (posMob.y <= y + 0.5f && posMob.y >= y - 0.5f) && (posMob.z <= z + 0.5f && posMob.z >= z - 0.5f))
|
||
{
|
||
return m_mobs[i];
|
||
}
|
||
}
|
||
return Mob(Vector3f(0,0,0), 0, 0);
|
||
} |