Compare commits

..

2 Commits

8 changed files with 59 additions and 17 deletions

View File

@ -12,7 +12,7 @@ public:
Player* add_player(BettolaLib::Network::TCPSocket* socket); Player* add_player(BettolaLib::Network::TCPSocket* socket);
void remove_player(unsigned int player_id); void remove_player(unsigned int player_id);
void send_initial_chunks(Player* player); void update_player_chunks(void);
void process_udp_message(const char* buffer, size_t size, const sockaddr_in& from_addr); void process_udp_message(const char* buffer, size_t size, const sockaddr_in& from_addr);
void broadcast_game_state(BettolaLib::Network::UDPSocket& udp_socket); void broadcast_game_state(BettolaLib::Network::UDPSocket& udp_socket);
@ -21,6 +21,8 @@ public:
Player* get_player_by_id(unsigned int id); Player* get_player_by_id(unsigned int id);
private: private:
void _send_chunks_around(Player* player, int chunk_x, int chunk_z);
std::vector<Player*> _players; std::vector<Player*> _players;
World _world; World _world;
}; };

View File

@ -0,0 +1,22 @@
#include <cmath>
#include "game.h"
#include "bettola/game/chunk.h"
void Game::update_player_chunks(void) {
const int chunk_width = BettolaLib::Game::CHUNK_WIDTH - 1;
const int chunk_height = BettolaLib::Game::CHUNK_HEIGHT - 1;
for(Player* player : _players) {
const auto& pos = player->get_position();
/* Calculate player's current chunk coords. */
int chunk_x = floor(pos.x / chunk_width);
int chunk_z = floor(pos.z / chunk_height);
/* If they have moved into a new chunk, send them the new surrounding chunks. */
if(chunk_z != player->get_chunk_x() || chunk_z != player->get_chunk_z()) {
player->set_chunk_pos(chunk_x, chunk_z);
_send_chunks_around(player, chunk_x, chunk_z);
}
}
}

View File

@ -5,14 +5,14 @@
#include "bettola/network/message.h" #include "bettola/network/message.h"
#include "player.h" #include "player.h"
void Game::send_initial_chunks(Player* player) { void Game::_send_chunks_around(Player* player, int center_x, int center_z) {
BettolaLib::Network::MessageHeader header; BettolaLib::Network::MessageHeader header;
header.type = BettolaLib::Network::MessageType::ChunkData; header.type = BettolaLib::Network::MessageType::ChunkData;
header.size = sizeof(BettolaLib::Network::ChunkMessage); header.size = sizeof(BettolaLib::Network::ChunkMessage);
/* Send a 3x3 grid of chunks around the origin. */ /* Send a 3x3 grid of chunks around the player's current chunk. */
for(int x = -1; x <=1; ++x) { for(int x = center_x; x <= center_x+1; ++x) {
for(int z = -1; z <= 1; ++z) { for(int z = center_z-1; z <= center_z+1; ++z) {
BettolaLib::Game::Chunk& chunk = _world.get_chunk(x, z); BettolaLib::Game::Chunk& chunk = _world.get_chunk(x, z);
BettolaLib::Network::ChunkMessage msg; BettolaLib::Network::ChunkMessage msg;

View File

@ -8,7 +8,9 @@
Player::Player(BettolaLib::Network::TCPSocket* socket) : Player::Player(BettolaLib::Network::TCPSocket* socket) :
PlayerBase(), PlayerBase(),
_socket(socket), _socket(socket),
_has_udp_addr(false) { _has_udp_addr(false),
_chunk_x(INT_MAX),
_chunk_z(INT_MAX) {
_last_processed_sequence = 0; _last_processed_sequence = 0;
memset(&_udp_addr, 0, sizeof(_udp_addr)); memset(&_udp_addr, 0, sizeof(_udp_addr));

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <limits.h>
#include <netinet/in.h> #include <netinet/in.h>
#include "bettola/network/tcpsocket.h" #include "bettola/network/tcpsocket.h"
@ -19,9 +20,15 @@ public:
void set_last_processed_sequence(unsigned int sequence) { _last_processed_sequence = sequence; } void set_last_processed_sequence(unsigned int sequence) { _last_processed_sequence = sequence; }
unsigned int get_last_processed_sequence(void) const { return _last_processed_sequence; } unsigned int get_last_processed_sequence(void) const { return _last_processed_sequence; }
int get_chunk_x(void) const { return _chunk_x; }
int get_chunk_z(void) const { return _chunk_z; }
void set_chunk_pos(int x, int z) { _chunk_x = x; _chunk_z = z; }
private: private:
BettolaLib::Network::TCPSocket* _socket; BettolaLib::Network::TCPSocket* _socket;
sockaddr_in _udp_addr; sockaddr_in _udp_addr;
bool _has_udp_addr; bool _has_udp_addr;
unsigned int _last_processed_sequence; unsigned int _last_processed_sequence;
int _chunk_x;
int _chunk_z;
}; };

View File

@ -1,21 +1,29 @@
#include <chrono>
#include "world.h" #include "world.h"
#include "bettola/game/chunk.h" #include "bettola/game/chunk.h"
#include "bettola/noise/fast_noise_lite.h" #include "bettola/noise/fast_noise_lite.h"
World::World(void) { World::World(void) {
m_noise.SetNoiseType(FastNoiseLite::NoiseType_Perlin); _noise.SetSeed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
m_noise.SetFrequency(0.02f); _noise.SetNoiseType(FastNoiseLite::NoiseType_Perlin);
_noise.SetFrequency(0.02f);
_noise.SetFractalType(FastNoiseLite::FractalType_FBm);
_noise.SetFractalOctaves(5);
_noise.SetFractalLacunarity(2.0f);
_noise.SetFractalGain(0.5);
} }
BettolaLib::Game::Chunk& World::get_chunk(int x, int z) { BettolaLib::Game::Chunk& World::get_chunk(int x, int z) {
ChunkPos pos = {x, z}; ChunkPos pos = {x, z};
auto it = m_chunks.find(pos); auto it = _chunks.find(pos);
if(it != m_chunks.end()) { if(it != _chunks.end()) {
return it->second; return it->second;
} }
/* If chunk doesn't exist, generate it. */ /* If chunk doesn't exist, generate it. */
BettolaLib::Game::Chunk& new_chunk = m_chunks[pos]; BettolaLib::Game::Chunk& new_chunk = _chunks[pos];
_generate_chunk(new_chunk, x, z); _generate_chunk(new_chunk, x, z);
return new_chunk; return new_chunk;
} }
@ -27,10 +35,10 @@ void World::_generate_chunk(BettolaLib::Game::Chunk& chunk, int chunk_x, int chu
float world_x = (float)(chunk_x * (BettolaLib::Game::CHUNK_WIDTH - 1) float world_x = (float)(chunk_x * (BettolaLib::Game::CHUNK_WIDTH - 1)
+ (x - BettolaLib::Game::CHUNK_BORDER_SIZE)); + (x - BettolaLib::Game::CHUNK_BORDER_SIZE));
float world_z = (float)(chunk_z * (BettolaLib::Game::CHUNK_HEIGHT - 1) float world_z = (float)(chunk_z * (BettolaLib::Game::CHUNK_HEIGHT - 1)
+ (z + BettolaLib::Game::CHUNK_BORDER_SIZE)); + (z - BettolaLib::Game::CHUNK_BORDER_SIZE));
/* generate noise value. */ /* generate noise value. */
chunk.heightmap[z * BettolaLib::Game::CHUNK_DATA_WIDTH + x] = m_noise.GetNoise(world_x, world_z); chunk.heightmap[z * BettolaLib::Game::CHUNK_DATA_WIDTH + x] = _noise.GetNoise(world_x, world_z);
} }
} }
} }

View File

@ -23,7 +23,7 @@ public:
private: private:
void _generate_chunk(BettolaLib::Game::Chunk& chunk, int chunk_x, int chunk_z); void _generate_chunk(BettolaLib::Game::Chunk& chunk, int chunk_x, int chunk_z);
FastNoiseLite m_noise; FastNoiseLite _noise;
std::map<ChunkPos, BettolaLib::Game::Chunk> m_chunks; std::map<ChunkPos, BettolaLib::Game::Chunk> _chunks;
}; };

View File

@ -112,8 +112,6 @@ int main(void) {
unsigned int id = new_player->get_id(); unsigned int id = new_player->get_id();
client_socket->send(&id, sizeof(id)); client_socket->send(&id, sizeof(id));
game.send_initial_chunks(new_player);
int client_flags = fcntl(client_socket->get_sockfd(), F_GETFL, 0); int client_flags = fcntl(client_socket->get_sockfd(), F_GETFL, 0);
fcntl(client_socket->get_sockfd(), F_SETFL, client_flags | O_NONBLOCK); fcntl(client_socket->get_sockfd(), F_SETFL, client_flags | O_NONBLOCK);
@ -165,6 +163,9 @@ int main(void) {
} }
} }
/* Update dynamic game state, like chunk loading for players. */
game.update_player_chunks();
/* Broadcase game state. */ /* Broadcase game state. */
game.broadcast_game_state(udp_socket); game.broadcast_game_state(udp_socket);