diff --git a/SQCSim-common/netprotocol.cpp b/SQCSim-common/netprotocol.cpp index c6c25dd..ad1a24b 100644 --- a/SQCSim-common/netprotocol.cpp +++ b/SQCSim-common/netprotocol.cpp @@ -1024,6 +1024,82 @@ std::vector netprot::recvPacks(SOCKET sock, Buffer* buf, Buffer* outbuf) } } +std::vector netprot::recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, Buffer* outbuf) { + std::vector lsPck; + int len = buf->tmp ? buf->tmp - buf->ptr : 0, + end = 0; + char* cursor = buf->tmp ? buf->tmp : nullptr, + * next = buf->tmp ? buf->tmp + 1 : buf->ptr, + * last = buf->tmp ? buf->tmp : buf->ptr; + bool ended = true; + struct pollfd fds[1]; + sockaddr_in sockad = from; + addrlen_t socklen = sizeof(sockad); + + fds[0].fd = sock; + fds[0].events = POLLIN; + + while (true) { + if (!poll(fds, 1, 0)) { + if (ended) + buf->tmp = nullptr; + return lsPck; + } + + int bytes = recvfrom(sock, &buf->ptr[len], buf->len - len, 0, (sockaddr*)&sockad, &socklen); + if (bytes <= 0) { // si recv() retourne -1 ou 0; ça veut dire qu'il y a plus rien a lire qui n'a pas déjà été traité. + if (ended) + buf->tmp = nullptr; + return lsPck; + } + len += bytes; + end = len; + + ended = false; + + while (true) { + int cmp = 0; + + if (cursor) + end -= (cursor - buf->ptr); + + if (end < 0) + break; + + cursor = (char*)memchr(next, '\r', end); + + if (cursor) { + next = cursor; + cursor--; + + cmp = memcmp(cursor, Footer, sizeof(uint32_t)); + if (cmp == 0) { + if (!outbuf) { + lsPck.push_back(last); + cursor += sizeof(uint32_t); + last = cursor; + next = cursor + 1; + } + else { + memcpy(&outbuf->ptr[cursor - last], last, cursor - last); + lsPck.push_back(&outbuf->ptr[cursor - last]); + cursor += sizeof(uint32_t); + last = cursor; + next = cursor + 1; + } + } + } + else { + if (!outbuf) + buf->tmp = last; + cursor = &buf->ptr[len]; + next = cursor + 1; + break; + }; + } + } +} + template <> void netprot::sendPack(SOCKET sock, Packet* pack, Buffer* buf) { switch (pack->type) { diff --git a/SQCSim-common/netprotocol.h b/SQCSim-common/netprotocol.h index 4a6046b..b6f78c9 100644 --- a/SQCSim-common/netprotocol.h +++ b/SQCSim-common/netprotocol.h @@ -177,6 +177,7 @@ namespace netprot { template void sendPackTo(SOCKET sock, T* pack, Buffer* buf, sockaddr_in* sockad); std::vector recvPacks(SOCKET sock, Buffer* buf, Buffer* oufbuf = nullptr); + std::vector recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, Buffer* oufbuf = nullptr); /* Templates */ diff --git a/SQCSim-common/player.cpp b/SQCSim-common/player.cpp index 790507f..faedf2f 100644 --- a/SQCSim-common/player.cpp +++ b/SQCSim-common/player.cpp @@ -192,6 +192,8 @@ void Player::ApplyTransformation(Transformation& transformation, bool rel) const if (rel) transformation.ApplyTranslation(-GetPOV()); } +void Player::SetDirection(Vector3f dir) { m_direction = dir; } + Vector3f Player::GetPosition() const { return Vector3f(m_position.x + CHUNK_SIZE_X * WORLD_SIZE_X / 2, m_position.y, m_position.z + CHUNK_SIZE_Z * WORLD_SIZE_Y / 2); } Vector3f Player::GetVelocity() const { return m_velocity; } diff --git a/SQCSim-common/player.h b/SQCSim-common/player.h index facfc5f..60013d0 100644 --- a/SQCSim-common/player.h +++ b/SQCSim-common/player.h @@ -21,6 +21,7 @@ public: Sound ApplyPhysics(Vector3f input, World* world, float elapsedTime); void ApplyTransformation(Transformation& transformation, bool rel = true) const; + void SetDirection(Vector3f dir); Vector3f GetPosition() const; Vector3f GetDirection() const; Vector3f GetVelocity() const; diff --git a/SQCSim-common/world.cpp b/SQCSim-common/world.cpp index c18c32c..25c5a3b 100644 --- a/SQCSim-common/world.cpp +++ b/SQCSim-common/world.cpp @@ -16,6 +16,9 @@ void World::SetSeed(uint64_t seed) { m_seed = seed; } + + + Chunk* World::ChunkAt(float x, float y, float z) const { int cx = (int)x / CHUNK_SIZE_X; int cz = (int)z / CHUNK_SIZE_Z; @@ -31,6 +34,32 @@ Chunk* World::ChunkAt(float x, float y, float z) const { Chunk* World::ChunkAt(const Vector3f& pos) const { return ChunkAt(pos.x, pos.y, pos.z); } +void World::RemoveChunk(int nbReduit) +{ + for (int x = 0; x < WORLD_SIZE_X; ++x) + for (int y = 0; y < WORLD_SIZE_Y; ++y) + { + Chunk* chk = nullptr; + if (x < nbReduit) + chk = m_chunks.Remove(x, y); + if (y < nbReduit) + chk = m_chunks.Remove(x, y); + if (y > WORLD_SIZE_Y - nbReduit) + chk = m_chunks.Remove(x, y); + if (x > WORLD_SIZE_X - nbReduit) + chk = m_chunks.Remove(x, y); + + // TODO: MakeDirty() les voisins pour qu'ils se redessinent. + + if (!chk) + continue; + + m_tbDeleted.emplace_back(chk); + } + + +} + BlockType World::BlockAt(float x, float y, float z, BlockType defaultBlockType) const { Chunk* c = ChunkAt(x, y, z); diff --git a/SQCSim-common/world.h b/SQCSim-common/world.h index 8a166af..e9b4840 100644 --- a/SQCSim-common/world.h +++ b/SQCSim-common/world.h @@ -28,6 +28,8 @@ public: Chunk* ChunkAt(float x, float y, float z) const; Chunk* ChunkAt(const Vector3f& pos) const; + void RemoveChunk(int nbReduit); + BlockType BlockAt(float x, float y, float z, BlockType defaultBlockType = BTYPE_AIR) const; BlockType BlockAt(const Vector3f& pos, BlockType defaultBlockType = BTYPE_AIR) const; diff --git a/SQCSim-srv/connection.cpp b/SQCSim-srv/connection.cpp index 079b0fb..4ac9968 100644 --- a/SQCSim-srv/connection.cpp +++ b/SQCSim-srv/connection.cpp @@ -47,6 +47,70 @@ PlayerInfo* Connection::getInfo() const { return (PlayerInfo*)&m_playinfo; } sockaddr_in* Connection::getAddr() const { return (sockaddr_in*)&m_addr; } +void Connection::getPacks(SOCKET sock) { + std::vector lsPck; + Input in; + while (true) { + lsPck = recvPacksFrom(sock, &m_buf, m_addr); + + for (auto& pck : lsPck) { + uint32_t bsize = m_buf.len - (pck - m_buf.ptr); + switch (netprot::getType(pck, 1)) { + using enum netprot::PACKET_TYPE; + case INPUT: + if (Deserialize(&in, pck, &bsize)) + m_input_manifest[in.timestamp] = in; + break; + default: break; + } + } + lsPck.clear(); + } +} + +void Connection::sendPacks(SOCKET sock, std::unordered_map conns) { + while (m_last_out < m_output_manifest.size()) { + Output out = m_output_manifest.at(m_last_out++); + + for (auto& [key, conn] : conns) { + if (m_playinfo.id == conn->GetHash(true)) + continue; + sendPackTo(sock, &out, &m_bufout, conn->getAddr()); + } + } +} + +void Connection::Run(World* world) { + Input in, last; + Output out; + float el; + + if (m_input_manifest.size() < 2) + return; + + while (m_last_in < m_input_manifest.size()) { + in = m_input_manifest.at(m_last_in + 1); + last = m_input_manifest.at(m_last_in); + + el = (float)(in.timestamp - last.timestamp) / 1000.; + player.get()->SetDirection(in.direction); + player.get()->ApplyPhysics(player.get()->GetInput(in.keys.forward, + in.keys.backward, + in.keys.left, + in.keys.right, + in.keys.jump, false, el), world, el); + + out.position = player.get()->GetPosition(); + out.direction = in.direction; + out.timestamp = in.timestamp; + out.id = m_playinfo.id; + + m_output_manifest[out.timestamp] = out; + + ++m_last_in; + } +} + void Connection::CleanInputManifest(Timestamp time) { auto wat = m_input_manifest.find(time); diff --git a/SQCSim-srv/connection.h b/SQCSim-srv/connection.h index 9233273..af9c2df 100644 --- a/SQCSim-srv/connection.h +++ b/SQCSim-srv/connection.h @@ -6,6 +6,7 @@ #include "../SQCSim-common/player.h" #include "../SQCSim-common/vector3.h" #include "../SQCSim-common/netprotocol.h" +#include "../SQCSim-common/world.h" #include "define.h" using namespace netprot; @@ -32,6 +33,11 @@ public: PlayerInfo* getInfo() const; sockaddr_in* getAddr() const; + void getPacks(SOCKET sock); + void sendPacks(SOCKET sock, std::unordered_map conns); + + void Run(World* world); + void CleanInputManifest(Timestamp time); private: std::unordered_map m_input_manifest; @@ -43,5 +49,11 @@ private: LoginInfo m_loginfo; PlayerInfo m_playinfo; + Timestamp m_startsync; + + uint64_t m_last_in = 0, + m_last_out = 0; + Buffer m_buf, + m_bufout; }; #endif diff --git a/SQCSim-srv/server.cpp b/SQCSim-srv/server.cpp index fc2184e..e724269 100644 --- a/SQCSim-srv/server.cpp +++ b/SQCSim-srv/server.cpp @@ -155,7 +155,7 @@ int Server::Ready() { play.tid = log->tid; sendPack(sock, &m_game, &m_buf); - std::unique_ptr conn = std::make_unique(sock, sockad, *log, play); + Connection* conn = new Connection(sock, sockad, *log, play); for (auto& [key, player] : m_players) { sendPack(player->getSock(), &play, &m_buf); // Envoyer les infos de joueur distant aux joueurs d�j� connect�s @@ -175,17 +175,20 @@ int Server::Ready() { } void Server::Run() { + bool endgame = false; Input in; sockaddr_in sockad; addrlen_t socklen = sizeof(sockad); Log("Debut de la partie...", false, false); - m_world = std::make_unique(); + int players = m_players.size(); + + m_world = new World(); m_world->SetSeed(m_game.seed); m_world->GetChunks().Reset(nullptr); m_world->BuildWorld(); - + for (auto& [key, conn] : m_players) { // Creation des instances de joueurs et premier sync. conn->player = std::make_unique(Vector3f(8.5f, CHUNK_SIZE_Y + 1.8f, 8.5f)); Sync sync; @@ -198,32 +201,41 @@ void Server::Run() { sendPack(conn->getSock(), &sync, &m_buf); } - while (true) { - if (recvfrom(m_sock_udp, m_buf.ptr, m_buf.len, 0, (sockaddr*)&sockad, &socklen) > 0) { - Packet pck = getPack(&m_buf); - switch (pck.type) { - using enum netprot::PACKET_TYPE; - case ERR: std::puts("ERROR!"); break; - case INPUT: std::puts("INPUT!"); break; - case OUTPUT: std::puts("OUTPUT!"); break; - case SYNC: std::puts("SYNC!"); break; - case TEAMINF: std::puts("TEAMINF!"); break; - case SELFINF: std::puts("SELFINF!"); break; - case PLAYINF: std::puts("PLAYINF!"); break; - case LOGINF: std::puts("LOGINF!"); break; - case CHUNKMOD: std::puts("CHUNKMOD!"); break; - case PLAYERMOD: std::puts("PLAYERMOD!"); break; - case PICKUPMOD: std::puts("PICKUPMOD!"); break; - case GAMEINFO: std::puts("GAMEINFO!"); break; - case ENDINFO: std::puts("ENDINFO!"); break; - case CHAT: std::puts("CHAT!"); break; - case ERRLOG: std::puts("ERRLOG!"); break; - case LAST_PACK: [[falltrough]]; - default: std::puts("wtf?!"); break; - } - netprot::emptyPack(pck); - } + while (!endgame) { + for (auto& [key, conn] : m_players) { + conn->getPacks(m_sock_udp); + conn->Run(m_world); + conn->sendPacks(m_sock_udp, m_players); + } } + + //while (true) { + // if (recvfrom(m_sock_udp, m_buf.ptr, m_buf.len, 0, (sockaddr*)&sockad, &socklen) > 0) { + // Packet pck = getPack(&m_buf); + // switch (pck.type) { + // using enum netprot::PACKET_TYPE; + // case ERR: std::puts("ERROR!"); break; + // case INPUT: std::puts("INPUT!"); break; + // case OUTPUT: std::puts("OUTPUT!"); break; + // case SYNC: std::puts("SYNC!"); break; + // case TEAMINF: std::puts("TEAMINF!"); break; + // case SELFINF: std::puts("SELFINF!"); break; + // case PLAYINF: std::puts("PLAYINF!"); break; + // case LOGINF: std::puts("LOGINF!"); break; + // case CHUNKMOD: std::puts("CHUNKMOD!"); break; + // case PLAYERMOD: std::puts("PLAYERMOD!"); break; + // case PICKUPMOD: std::puts("PICKUPMOD!"); break; + // case GAMEINFO: std::puts("GAMEINFO!"); break; + // case ENDINFO: std::puts("ENDINFO!"); break; + // case CHAT: std::puts("CHAT!"); break; + // case ERRLOG: std::puts("ERRLOG!"); break; + // case LAST_PACK: [[falltrough]]; + // default: std::puts("wtf?!"); break; + // } + // netprot::emptyPack(pck); + // } + //} + } inline std::string Server::LogTimestamp() { diff --git a/SQCSim-srv/server.h b/SQCSim-srv/server.h index ee14723..dd5a397 100644 --- a/SQCSim-srv/server.h +++ b/SQCSim-srv/server.h @@ -36,12 +36,12 @@ private: Buffer m_buf; - std::unordered_map> m_players; + std::unordered_map m_players; std::unordered_map m_chatlog; std::vector m_ids; GameInfo m_game; - std::unique_ptr m_world = nullptr; + World* m_world = nullptr; const bool m_manual_setup = SRV_MANUAL_SETUP; std::string LogTimestamp(); diff --git a/SQCSim2021/engine.cpp b/SQCSim2021/engine.cpp index 6fcf7b0..81afefa 100644 --- a/SQCSim2021/engine.cpp +++ b/SQCSim2021/engine.cpp @@ -276,9 +276,46 @@ void Engine::DrawMenu() ShowCursor(); } -void Engine::Init() { +void Engine::DrawPause() +{ + static const int sTitle = 400; + static const int sButton = 225; + + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, Width(), 0, Height(), -1, 1); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + PauseBGTexture.Bind(); + glLoadIdentity(); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2i(0, 0); + glTexCoord2f(1, 0); + glVertex2i(800, 0); + glTexCoord2f(1, 1); + glVertex2i(800, 600); + glTexCoord2f(0, 1); + glVertex2i(0, 600); + glEnd(); + + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + ShowCursor(); +} + +void Engine::Init() { GLenum glewErr = glewInit(); if (glewErr != GLEW_OK) { @@ -307,6 +344,10 @@ void Engine::Init() { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_SUBTRACT); + if (m_istarted) + return; + else m_istarted = true; + // // Objet de skybox avec sa propre texture et son propre shader! m_skybox.Init(0.2f); @@ -396,15 +437,12 @@ void Engine::LoadResource() { LoadTexture(MenuTitleTexture, TEXTURE_PATH "BrouillonbackgroundMenu.png"); LoadTexture(MenuBGTexture, TEXTURE_PATH "BrouillonbackgroundMenu.png"); + LoadTexture(PauseBGTexture, TEXTURE_PATH "BrouillonbackgroundMenu.png"); LoadTexture(SplachScreenTexture, TEXTURE_PATH "sc2.png"); LoadTexture(MenuQuitTexture, MENU_ITEM_PATH "BasicQuit.png"); LoadTexture(MenuOptionsTexture, MENU_ITEM_PATH "test.png"); LoadTexture(MenuStartTexture, MENU_ITEM_PATH "BasicPlay.png"); - - - - TextureAtlas::TextureIndex texDirtIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "metal3.png"); TextureAtlas::TextureIndex texIceIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "metal2.png"); TextureAtlas::TextureIndex texGrassIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "grass.png"); @@ -895,7 +933,13 @@ void Engine::DrawHud(float elapsedTime, BlockType bloc) { glPushMatrix(); int timer = GetCountdown(elapsedTime); - + for (int i = 1; i < WORLD_SIZE_X; i++) + { + if (timer <= COUNTDOWN - m_timerReductionChunk * i) { + m_world.RemoveChunk(m_nbReductionChunk * i); + m_renderer.RemoveChunk(m_nbReductionChunk * i); + } + } if (m_keyK) { SystemNotification(m_messageNotification); m_keyK = false; @@ -960,12 +1004,13 @@ void Engine::PrintText(float x, float y, const std::string& t, float charSizeMul } } - int Engine::GetFps(float elapsedTime) const { return 1 / elapsedTime; } int Engine::GetCountdown(float elapsedTime) { if (m_resetcountdown) { + m_nbReductionChunk = 4; + m_timerReductionChunk = 30; m_countdown = m_time + COUNTDOWN; m_resetcountdown = false; } @@ -1001,7 +1046,6 @@ void Engine::Render(float elapsedTime) { Transformation all; Transformation skybox; - Transformation remotePlayer; Vector3f vstep; // Transformations initiales @@ -1032,16 +1076,15 @@ void Engine::Render(float elapsedTime) { pollTime = 0; } - RenderRemotePlayers(m_remotePlayer, pollTime); - m_player.ApplyTransformation(all); + 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!). + - - - + + //m_remotePlayer.ApplyTransformation(all); if (m_mouseWU) bloc++; else if (m_mouseWD) bloc--; @@ -1097,16 +1140,15 @@ void Engine::Render(float elapsedTime) { } } - m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas); + if (m_isSkybox) m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas); m_world.Update(m_bullets, m_player.GetPosition(), m_blockinfo); m_renderer.UpdateMesh(&m_world, m_player.GetPosition(), m_blockinfo); + m_remotePlayer.Render(m_textureAtlas, m_shader01, elapsedTime); if (m_isSkybox) m_skybox.Render(skybox); - - - DrawHud(elapsedTime, bloc); - DisplayPovGun(); + if (m_isSkybox) DrawHud(elapsedTime, bloc); + if (m_isSkybox) DisplayPovGun(); ProcessNotificationQueue(); if (m_damage) { @@ -1122,14 +1164,26 @@ void Engine::Render(float elapsedTime) { fell = false; } - if (m_networkgame) { + if (m_networkgame) { // Pour se gerer le paquet. using namespace std::chrono; using namespace netprot; + Timestamp tstamp = duration_cast(high_resolution_clock::now() - m_startTime).count(); Input input; + Sync sync; + uint64_t id = m_conn.getId(); + static std::vector lsPck; - input.sid = m_conn.getId(); + if (false) { // TODO: Faire un checkup pour chaque ~1000ms. + sync.sid = id; + sync.timestamp = tstamp; + sync.position = m_player.GetPosition(); + sync.hp = m_player.GetHP(); + // TODO: Garrocher ca quelque-part. + } + + input.sid = id; input.direction = m_player.GetDirection(); - input.timestamp = duration_cast(high_resolution_clock::now() - m_startTime).count(); + input.timestamp = tstamp; input.keys.forward = m_keyW; input.keys.backward = m_keyS; input.keys.left = m_keyA; @@ -1138,13 +1192,38 @@ void Engine::Render(float elapsedTime) { input.keys.block = m_mouseR; input.keys.shoot = m_mouseL; - sendPackTo(m_conn.m_sock_udp, &input, &m_buf, &m_conn.m_srvsockaddr); - - // TODO: Faire la gestion de la réception de paquets. + sendPackTo(m_conn.m_sock_udp, &input, &m_bufout, &m_conn.m_srvsockaddr); + lsPck = recvPacks(m_conn.m_sock_udp, &m_buf); + char* prevptr = nullptr; + for (auto& pck : lsPck) { // We could make a few threads out of this. + Sync sync; + Output out; + if (!prevptr) + prevptr = m_buf.ptr; + uint32_t bsize = m_buf.len - (pck - prevptr); + prevptr = pck; + switch (getType(pck, 1)) { + using enum PACKET_TYPE; + case SYNC: + if (Deserialize(&sync, pck, &bsize)) { + if (sync.sid != m_conn.getId()) + break; + // TODO: Vérifier si les positions concordent au sync local. + } + break; + case OUTPUT: + if (Deserialize(&out, pck, &bsize)) { + RemotePlayer* r = (RemotePlayer*)m_players[out.id]; + r->Feed(out); + } + break; + default: + break; + } + } + lsPck.clear(); } - - } else if (m_gamestate == GameState::MAIN_MENU || m_gamestate == GameState::OPTIONS) { @@ -1155,11 +1234,12 @@ void Engine::Render(float elapsedTime) { DrawMenu(); } } + else if (m_gamestate == GameState::PAUSE) + { + DrawPause(); + } else if (m_gamestate == GameState::QUIT) Stop(); - - - } void Engine::KeyPressEvent(unsigned char key) { @@ -1185,7 +1265,14 @@ void Engine::KeyPressEvent(unsigned char key) { } break; case 36: // ESC - Quitter - m_gamestate = GameState::MAIN_MENU; + if (m_gamestate == GameState::PLAY) + { + m_gamestate = GameState::PAUSE; + } + else if (m_gamestate == GameState::PAUSE) + { + m_gamestate = GameState::PLAY; + } //Stop(); break; case 57: // Space - Sauter @@ -1420,7 +1507,3 @@ bool Engine::LoadTexture(Texture& texture, const std::string& filename, bool use return true; } -void Engine::RenderRemotePlayers(RemotePlayer& remoteplayer, float elapsedTime) -{ - remoteplayer.Render(m_textureAtlas, m_shader01, elapsedTime); -} diff --git a/SQCSim2021/engine.h b/SQCSim2021/engine.h index 962e15d..88697e6 100644 --- a/SQCSim2021/engine.h +++ b/SQCSim2021/engine.h @@ -29,6 +29,7 @@ public: Engine(); virtual ~Engine(); virtual void DrawMenu(); + virtual void DrawPause(); virtual void DrawSplachScreen(); virtual void Init(); virtual void DeInit(); @@ -94,17 +95,18 @@ private: Bullet* m_bullets[MAX_BULLETS]; std::unordered_map m_players; - netprot::Buffer m_buf; + netprot::Buffer m_buf, m_bufout; std::chrono::high_resolution_clock::time_point m_startTime; //Menu - enum class GameState: uint8_t { MAIN_MENU, OPTIONS, QUIT, NEWG, PLAY }; + enum class GameState: uint8_t { MAIN_MENU, OPTIONS, QUIT, NEWG, PLAY, PAUSE }; GameState m_gamestate = GameState::MAIN_MENU; Texture MenuTitleTexture; Texture MenuBGTexture; Texture MenuStartTexture; Texture MenuQuitTexture; Texture MenuOptionsTexture; + Texture PauseBGTexture; Texture SplachScreenTexture; @@ -118,6 +120,8 @@ private: int m_renderCount = 0; int m_countdown = COUNTDOWN; + int m_nbReductionChunk = 4; + int m_timerReductionChunk = 30; bool m_damage = false; @@ -131,7 +135,7 @@ private: bool m_resetcountdown = false; bool m_soloMultiChoiceMade = false; bool m_stopcountdown = false; - + bool m_keyK = false; bool m_keyL = false; bool m_keyW = false; diff --git a/SQCSim2021/mesh.cpp b/SQCSim2021/mesh.cpp index 04294af..c6f6b9b 100644 --- a/SQCSim2021/mesh.cpp +++ b/SQCSim2021/mesh.cpp @@ -9,7 +9,7 @@ Mesh::~Mesh() { void Mesh::FlushMeshToVBO() { m_vertexBuffer.SetMeshData(m_vd, m_vcount); m_vcount = 0; - //delete[] m_vd; + delete[] m_vd; } void Mesh::FlushVBO() { diff --git a/SQCSim2021/mesh.h b/SQCSim2021/mesh.h index 0a070ff..138d0e2 100644 --- a/SQCSim2021/mesh.h +++ b/SQCSim2021/mesh.h @@ -15,7 +15,7 @@ private: Chunk* m_chunk; // NE PAS DÉTRUIRE ICI. void AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType bt, int x, int y, int z, float u, float v, float s, World* world); - + void RemoveChunk(int nbReduit); public: Mesh(Chunk* chunk); ~Mesh(); diff --git a/SQCSim2021/openglcontext.cpp b/SQCSim2021/openglcontext.cpp index 7a61b07..6284446 100644 --- a/SQCSim2021/openglcontext.cpp +++ b/SQCSim2021/openglcontext.cpp @@ -15,7 +15,7 @@ bool OpenglContext::Start(const std::string& title, int width, int height, bool m_title = title; m_fullscreen = fullscreen; InitWindow(width, height); - + Init(); LoadResource(); diff --git a/SQCSim2021/openglcontext.h b/SQCSim2021/openglcontext.h index 3825b26..2718540 100644 --- a/SQCSim2021/openglcontext.h +++ b/SQCSim2021/openglcontext.h @@ -52,6 +52,8 @@ protected: void HideCursor(); void ShowCrossCursor() const; + bool m_istarted = false; + private: void InitWindow(int width, int height); MOUSE_BUTTON ConvertMouseButton(sf::Mouse::Button button) const; diff --git a/SQCSim2021/remoteplayer.cpp b/SQCSim2021/remoteplayer.cpp index abfb33e..1ef4cd1 100644 --- a/SQCSim2021/remoteplayer.cpp +++ b/SQCSim2021/remoteplayer.cpp @@ -71,101 +71,20 @@ void RemotePlayer::Feed(const netprot::Output out) { void RemotePlayer::Render(TextureAtlas& atlas, Shader& shader, float elapsedTime) { - m_texture_front.Bind(); shader.Use(); + //m_texture_front.Bind(); - //float x = current.position.x; - //float y = current.position.y; - //float z = current.position.z; - float x = 128.0f; - float y = 21.0f; - float z = 128.0f; - - float quadSize = 300.0f; + float u, v, w, h; + atlas.Bind(); + atlas.TextureIndexToCoord(0, u, v, w, h); glBegin(GL_QUADS); - glNormal3f(0, 0, 1); - - // Face avant - glTexCoord2f(0, 0); - glVertex3f(x - quadSize / 2, y - quadSize / 2, z + quadSize / 2); - - glTexCoord2f(1, 0); - glVertex3f(x + quadSize / 2, y - quadSize / 2, z + quadSize / 2); - - glTexCoord2f(1, 1); - glVertex3f(x + quadSize / 2, y + quadSize / 2, z + quadSize / 2); - - glTexCoord2f(0, 1); - glVertex3f(x - quadSize / 2, y + quadSize / 2, z + quadSize / 2); - - // Face arrière - glTexCoord2f(0, 0); - glVertex3f(x + quadSize / 2, y - quadSize / 2, z - quadSize / 2); - - glTexCoord2f(1, 0); - glVertex3f(x - quadSize / 2, y - quadSize / 2, z - quadSize / 2); - - glTexCoord2f(1, 1); - glVertex3f(x - quadSize / 2, y + quadSize / 2, z - quadSize / 2); - - glTexCoord2f(0, 1); - glVertex3f(x + quadSize / 2, y + quadSize / 2, z - quadSize / 2); - - // Face droite - glTexCoord2f(0, 0); - glVertex3f(x + quadSize / 2, y - quadSize / 2, z + quadSize / 2); - - glTexCoord2f(1, 0); - glVertex3f(x + quadSize / 2, y - quadSize / 2, z - quadSize / 2); - - glTexCoord2f(1, 1); - glVertex3f(x + quadSize / 2, y + quadSize / 2, z - quadSize / 2); - - glTexCoord2f(0, 1); - glVertex3f(x + quadSize / 2, y + quadSize / 2, z + quadSize / 2); - - // Face gauche - glTexCoord2f(0, 0); - glVertex3f(x - quadSize / 2, y - quadSize / 2, z - quadSize / 2); - - glTexCoord2f(1, 0); - glVertex3f(x - quadSize / 2, y - quadSize / 2, z + quadSize / 2); - - glTexCoord2f(1, 1); - glVertex3f(x - quadSize / 2, y + quadSize / 2, z + quadSize / 2); - - glTexCoord2f(0, 1); - glVertex3f(x - quadSize / 2, y + quadSize / 2, z - quadSize / 2); - - // Face supérieure - glTexCoord2f(0, 0); - glVertex3f(x - quadSize / 2, y + quadSize / 2, z + quadSize / 2); - - glTexCoord2f(1, 0); - glVertex3f(x + quadSize / 2, y + quadSize / 2, z + quadSize / 2); - - glTexCoord2f(1, 1); - glVertex3f(x + quadSize / 2, y + quadSize / 2, z - quadSize / 2); - - glTexCoord2f(0, 1); - glVertex3f(x - quadSize / 2, y + quadSize / 2, z - quadSize / 2); - - // Face inférieure - glTexCoord2f(0, 0); - glVertex3f(x - quadSize / 2, y - quadSize / 2, z - quadSize / 2); - - glTexCoord2f(1, 0); - glVertex3f(x + quadSize / 2, y - quadSize / 2, z - quadSize / 2); - - glTexCoord2f(1, 1); - glVertex3f(x + quadSize / 2, y - quadSize / 2, z + quadSize / 2); - - glTexCoord2f(0, 1); - glVertex3f(x - quadSize / 2, y - quadSize / 2, z + quadSize / 2); - + glTexCoord2f(u, v); glVertex3f(0, 50., 0); + glTexCoord2f(u+w, v); glVertex3f(50., 50., 0); + glTexCoord2f(u+w, v+h); glVertex3f(50., 0, 0); + glTexCoord2f(u, v+h); glVertex3f(0, 0, 0); glEnd(); - + shader.Disable(); } bool RemotePlayer::LoadTexture(Texture& texture, const std::string& filename, bool useMipmaps, bool stopOnError) diff --git a/SQCSim2021/renderer.cpp b/SQCSim2021/renderer.cpp index b4c8f91..b430b34 100644 --- a/SQCSim2021/renderer.cpp +++ b/SQCSim2021/renderer.cpp @@ -7,6 +7,32 @@ Renderer::Renderer() { Renderer::~Renderer() { } +void Renderer::RemoveChunk(int nbReduit) +{ + for (int x = 0; x < WORLD_SIZE_X; ++x) + for (int y = 0; y < WORLD_SIZE_Y; ++y) + { + Mesh* chk = nullptr; + if (x < nbReduit) + chk = m_meshes.Remove(x, y); + if (y < nbReduit) + chk = m_meshes.Remove(x, y); + if (y > WORLD_SIZE_Y - nbReduit) + chk = m_meshes.Remove(x, y); + if (x > WORLD_SIZE_X - nbReduit) + chk = m_meshes.Remove(x, y); + + // TODO: MakeDirty() les voisins pour qu'ils se redessinent. + + if (!chk) + continue; + + delete chk; + } + + +} + void Renderer::RenderWorld(World* origin, int& rendercount, const Vector3f& player_pos, const Vector3f& player_dir, Transformation& world, Shader& shader, TextureAtlas& atlas) const { rendercount = 0; Vector3f angle; diff --git a/SQCSim2021/renderer.h b/SQCSim2021/renderer.h index 8afdc3b..4c8e9dd 100644 --- a/SQCSim2021/renderer.h +++ b/SQCSim2021/renderer.h @@ -21,6 +21,8 @@ public: Renderer(); ~Renderer(); + void RemoveChunk(int nbReduit); + void UpdateMesh(World* origin, const Vector3f& player, BlockInfo* blockinfo[BTYPE_LAST]); void RenderWorld(World* origin, int& rendercount, const Vector3f& player_pos, const Vector3f& player_dir, Transformation& world, Shader& shader, TextureAtlas& atlas) const;