Merge branch 'net-map'
This commit is contained in:
@@ -62,7 +62,7 @@ void ClientApplication::Init() {
|
|||||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
throw(std::runtime_error("Failed to initialize SDL"));
|
throw(std::runtime_error("Failed to initialize SDL"));
|
||||||
}
|
}
|
||||||
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"), 0, (config.Bool("screen.f")) ? SDL_HWSURFACE|SDL_DOUBLEBUF : SDL_HWSURFACE);
|
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"), 0, (config.Bool("screen.f")) ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||||
|
|
||||||
//initialize SDL_net
|
//initialize SDL_net
|
||||||
if (SDLNet_Init()) {
|
if (SDLNet_Init()) {
|
||||||
@@ -77,7 +77,7 @@ void ClientApplication::Proc() {
|
|||||||
//prepare the time system
|
//prepare the time system
|
||||||
typedef std::chrono::steady_clock Clock;
|
typedef std::chrono::steady_clock Clock;
|
||||||
|
|
||||||
Clock::duration delta(16 * Clock::duration::period::den / std::milli::den);
|
std::chrono::duration<int, std::milli> delta(16);
|
||||||
Clock::time_point simTime = Clock::now();
|
Clock::time_point simTime = Clock::now();
|
||||||
Clock::time_point realTime;
|
Clock::time_point realTime;
|
||||||
|
|
||||||
@@ -95,15 +95,12 @@ void ClientApplication::Proc() {
|
|||||||
//simulate game time
|
//simulate game time
|
||||||
while (simTime < realTime) {
|
while (simTime < realTime) {
|
||||||
//call each user defined function
|
//call each user defined function
|
||||||
activeScene->RunFrame(double(delta.count()) / Clock::duration::period::den);
|
activeScene->RunFrame(double(delta.count()) / std::chrono::duration<int, std::milli>::period::den);
|
||||||
simTime += delta;
|
simTime += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw the game to the screen
|
//draw the game to the screen
|
||||||
activeScene->RenderFrame();
|
activeScene->RenderFrame();
|
||||||
|
|
||||||
//give the computer a break
|
|
||||||
SDL_Delay(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UnloadScene();
|
UnloadScene();
|
||||||
@@ -121,7 +118,6 @@ void ClientApplication::Quit() {
|
|||||||
|
|
||||||
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
void ClientApplication::LoadScene(SceneList sceneIndex) {
|
||||||
UnloadScene();
|
UnloadScene();
|
||||||
|
|
||||||
switch(sceneIndex) {
|
switch(sceneIndex) {
|
||||||
//add scene creation calls here
|
//add scene creation calls here
|
||||||
case SceneList::FIRST:
|
case SceneList::FIRST:
|
||||||
@@ -143,7 +139,6 @@ void ClientApplication::LoadScene(SceneList sceneIndex) {
|
|||||||
case SceneList::INCOMBAT:
|
case SceneList::INCOMBAT:
|
||||||
activeScene = new InCombat();
|
activeScene = new InCombat();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw(std::logic_error("Failed to recognize the scene index"));
|
throw(std::logic_error("Failed to recognize the scene index"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
|
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const dest) { sprite.DrawTo(dest, position.x, position.y); }
|
void DrawTo(SDL_Surface* const dest, int camX, int camY) { sprite.DrawTo(dest, position.x - camX, position.y - camY); }
|
||||||
|
|
||||||
//clunky code results in smooth movement and controls
|
//clunky code results in smooth movement and controls
|
||||||
void AdjustDirection(Direction);
|
void AdjustDirection(Direction);
|
||||||
|
|||||||
+180
-9
@@ -23,8 +23,15 @@
|
|||||||
|
|
||||||
#include "channels.hpp"
|
#include "channels.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Public access members
|
//Public access members
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -55,6 +62,14 @@ InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNet
|
|||||||
disconnectButton.SetText("Disconnect");
|
disconnectButton.SetText("Disconnect");
|
||||||
shutDownButton.SetText("Shut Down");
|
shutDownButton.SetText("Shut Down");
|
||||||
|
|
||||||
|
//load the tilesheet
|
||||||
|
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||||
|
|
||||||
|
//setup the map object
|
||||||
|
mapPager.SetRegionWidth(REGION_WIDTH);
|
||||||
|
mapPager.SetRegionHeight(REGION_HEIGHT);
|
||||||
|
mapPager.SetRegionDepth(REGION_DEPTH);
|
||||||
|
|
||||||
//create the server-side player object
|
//create the server-side player object
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
packet.meta.type = NetworkPacket::Type::PLAYER_NEW;
|
packet.meta.type = NetworkPacket::Type::PLAYER_NEW;
|
||||||
@@ -73,6 +88,9 @@ InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNet
|
|||||||
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE;
|
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE;
|
||||||
serialize(&packet, buffer);
|
serialize(&packet, buffer);
|
||||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
// RequestRegion(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
InWorld::~InWorld() {
|
InWorld::~InWorld() {
|
||||||
@@ -88,29 +106,59 @@ void InWorld::FrameStart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InWorld::Update(double delta) {
|
void InWorld::Update(double delta) {
|
||||||
//suck in all waiting packets
|
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
|
|
||||||
|
//suck in all waiting packets
|
||||||
while(network.Receive()) {
|
while(network.Receive()) {
|
||||||
deserialize(&packet, network.GetInData());
|
deserialize(&packet, network.GetInData());
|
||||||
packet.meta.srcAddress = network.GetInPacket()->address;
|
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||||
HandlePacket(packet);
|
HandlePacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//update the characters
|
||||||
for (auto& it : playerCharacters) {
|
for (auto& it : playerCharacters) {
|
||||||
it.second.Update(delta);
|
it.second.Update(delta);
|
||||||
}
|
}
|
||||||
|
//TODO: sort the players and entities by Y position
|
||||||
|
|
||||||
|
//update the camera
|
||||||
|
if(localCharacter) {
|
||||||
|
camera.x = localCharacter->GetPosition().x - camera.marginX;
|
||||||
|
camera.y = localCharacter->GetPosition().y - camera.marginY;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check the map
|
||||||
|
UpdateMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InWorld::FrameEnd() {
|
void InWorld::FrameEnd() {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InWorld::RenderFrame() {
|
||||||
|
// SDL_FillRect(GetScreen(), 0, 0);
|
||||||
|
Render(GetScreen());
|
||||||
|
SDL_Flip(GetScreen());
|
||||||
|
}
|
||||||
|
|
||||||
void InWorld::Render(SDL_Surface* const screen) {
|
void InWorld::Render(SDL_Surface* const screen) {
|
||||||
for (auto& it : playerCharacters) {
|
//draw the map
|
||||||
it.second.DrawTo(screen);
|
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); it++) {
|
||||||
|
tileSheet.DrawRegionTo(screen, *it, camera.x, camera.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//draw characters
|
||||||
|
for (auto& it : playerCharacters) {
|
||||||
|
it.second.DrawTo(screen, camera.x, camera.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw UI
|
||||||
disconnectButton.DrawTo(screen);
|
disconnectButton.DrawTo(screen);
|
||||||
shutDownButton.DrawTo(screen);
|
shutDownButton.DrawTo(screen);
|
||||||
|
|
||||||
|
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||||
|
|
||||||
|
fps.Calculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -212,24 +260,27 @@ void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Network handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
void InWorld::HandlePacket(NetworkPacket packet) {
|
void InWorld::HandlePacket(NetworkPacket packet) {
|
||||||
switch(packet.meta.type) {
|
switch(packet.meta.type) {
|
||||||
case NetworkPacket::Type::DISCONNECT:
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
HandleDisconnect(packet);
|
HandleDisconnect(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_NEW:
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
HandlePlayerNew(packet);
|
HandlePlayerNew(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_DELETE:
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
HandlePlayerDelete(packet);
|
HandlePlayerDelete(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
HandlePlayerUpdate(packet);
|
HandlePlayerUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
case NetworkPacket::Type::REGION_CONTENT:
|
||||||
|
HandleRegionContent(packet);
|
||||||
|
break;
|
||||||
//handle errors
|
//handle errors
|
||||||
default:
|
default:
|
||||||
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||||
@@ -257,6 +308,12 @@ void InWorld::HandlePlayerNew(NetworkPacket packet) {
|
|||||||
if (packet.playerInfo.clientIndex == clientIndex && !localCharacter) {
|
if (packet.playerInfo.clientIndex == clientIndex && !localCharacter) {
|
||||||
playerIndex = packet.playerInfo.playerIndex;
|
playerIndex = packet.playerInfo.playerIndex;
|
||||||
localCharacter = &playerCharacters[playerIndex];
|
localCharacter = &playerCharacters[playerIndex];
|
||||||
|
//setup the camera
|
||||||
|
camera.width = GetScreen()->w;
|
||||||
|
camera.height = GetScreen()->h;
|
||||||
|
//center on the player's character
|
||||||
|
camera.marginX = (GetScreen()->w / 2 - localCharacter->GetSprite()->GetImage()->GetClipW() / 2);
|
||||||
|
camera.marginY = (GetScreen()->h / 2 - localCharacter->GetSprite()->GetImage()->GetClipH() / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,6 +345,28 @@ void InWorld::HandlePlayerUpdate(NetworkPacket packet) {
|
|||||||
playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
|
playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InWorld::HandleRegionContent(NetworkPacket packet) {
|
||||||
|
//replace existing regions
|
||||||
|
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
|
||||||
|
mapPager.UnloadRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||||
|
}
|
||||||
|
mapPager.PushRegion(packet.regionInfo.region);
|
||||||
|
packet.regionInfo.region = nullptr;
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
cout << "Received region: " << packet.regionInfo.x << ", " << packet.regionInfo.y << endl;
|
||||||
|
if (mapPager.FindRegion(packet.regionInfo.x, packet.regionInfo.y)) {
|
||||||
|
cout << "Success" << endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cout << "Failure" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Server control
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
void InWorld::SendState() {
|
void InWorld::SendState() {
|
||||||
NetworkPacket packet;
|
NetworkPacket packet;
|
||||||
char buffer[PACKET_BUFFER_SIZE];
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
@@ -296,8 +375,6 @@ void InWorld::SendState() {
|
|||||||
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||||
packet.playerInfo.clientIndex = clientIndex;
|
packet.playerInfo.clientIndex = clientIndex;
|
||||||
packet.playerInfo.playerIndex = playerIndex;
|
packet.playerInfo.playerIndex = playerIndex;
|
||||||
// snprintf(packet.playerInfo.handle, PACKET_STRING_SIZE, "%s", config["player.handle"].c_str());
|
|
||||||
// snprintf(packet.playerInfo.avatar, PACKET_STRING_SIZE, "%s", config["player.avatar"].c_str());
|
|
||||||
packet.playerInfo.position = localCharacter->GetPosition();
|
packet.playerInfo.position = localCharacter->GetPosition();
|
||||||
packet.playerInfo.motion = localCharacter->GetMotion();
|
packet.playerInfo.motion = localCharacter->GetMotion();
|
||||||
|
|
||||||
@@ -326,3 +403,97 @@ void InWorld::RequestShutDown() {
|
|||||||
serialize(&packet, buffer);
|
serialize(&packet, buffer);
|
||||||
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InWorld::RequestRegion(int x, int y) {
|
||||||
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//pack the region's data
|
||||||
|
packet.meta.type = NetworkPacket::Type::REGION_REQUEST;
|
||||||
|
packet.regionInfo.x = x;
|
||||||
|
packet.regionInfo.y = y;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Utilities
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
int InWorld::CheckBufferDistance(Region* const region) {
|
||||||
|
/* DOCUMENTATION
|
||||||
|
* This algorithm is extremely complex and involed, but initial tests show
|
||||||
|
* that it gives the right answers. The purpose is to determine how far off screen
|
||||||
|
* a certain region is, so that it can be unloaded when necessary.
|
||||||
|
*
|
||||||
|
* If the region is actually onscreen, then there's no reason to run the rest, so
|
||||||
|
* the algorithm corrects for the camera's location, before checking the bounds of
|
||||||
|
* the screen.
|
||||||
|
*
|
||||||
|
* The next part is tricky. If X or Y is negative, then it is divided by the
|
||||||
|
* graphical size of the regions, resulting in a usable integer, representing how
|
||||||
|
* far from the screen it is in "region units". If, however, X or Y is larger than
|
||||||
|
* 0, than first, the size of the screen is subtracted from that variable, before
|
||||||
|
* it is then divided by the graphical size of a region. Finally, to compensate for
|
||||||
|
* the off by one error, 1 is added at the end.
|
||||||
|
*
|
||||||
|
* Since only the magnitude of the distance in either direction is needed, this
|
||||||
|
* method returns the largest absolute value of X or Y.
|
||||||
|
*
|
||||||
|
* The final result of this algorithm is an integer representing how far, rounded
|
||||||
|
* up, a certain region is from the screen's edges in any direction, measured in
|
||||||
|
* "region units". This algorithm may be flawed, in which case, I recommend simply
|
||||||
|
* replacing it with a boolean check, to see if the region's distance from the player
|
||||||
|
* is larger than a certain value. This algorithm lacks the advantages I initially
|
||||||
|
* expected, so that may be beneficial at some point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//locations relative to the camera
|
||||||
|
int x = region->GetX() - camera.x;
|
||||||
|
int y = region->GetY() - camera.y;
|
||||||
|
|
||||||
|
//if the region is visible, return -1
|
||||||
|
if (x >= -mapPager.GetRegionWidth() * tileSheet.GetTileW() && x < camera.width &&
|
||||||
|
y >= -mapPager.GetRegionHeight() * tileSheet.GetTileH() && y < camera.height) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//prune the screen's area from the algorithm; get the pseudo-indexes
|
||||||
|
if (x < 0) x /= (mapPager.GetRegionWidth() * tileSheet.GetTileW());
|
||||||
|
if (y < 0) y /= (mapPager.GetRegionHeight() * tileSheet.GetTileH());
|
||||||
|
if (x > 0) x = (x - camera.width) / (mapPager.GetRegionWidth() * tileSheet.GetTileW()) + 1;
|
||||||
|
if (y > 0) y = (y - camera.height) / (mapPager.GetRegionHeight() * tileSheet.GetTileH()) + 1;
|
||||||
|
|
||||||
|
//return the pseudo-index with the greatest magnitude
|
||||||
|
return std::max(abs(x), abs(y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::UpdateMap() {
|
||||||
|
//prune distant regions
|
||||||
|
for (auto it = mapPager.GetContainer()->begin(); it != mapPager.GetContainer()->end(); /* EMPTY */) {
|
||||||
|
if (CheckBufferDistance(*it) > 2) {
|
||||||
|
//debugging
|
||||||
|
cout << "unloading: " << (*it)->GetX() << ", " << (*it)->GetY() << endl;
|
||||||
|
|
||||||
|
mapPager.UnloadRegion((*it)->GetX(), (*it)->GetY());
|
||||||
|
|
||||||
|
//reset
|
||||||
|
it = mapPager.GetContainer()->begin();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: make the region units official
|
||||||
|
int regionUnitX = mapPager.GetRegionWidth() * tileSheet.GetTileW();
|
||||||
|
int regionUnitY = mapPager.GetRegionHeight() * tileSheet.GetTileH();
|
||||||
|
|
||||||
|
//request empty regions, including buffers (-1 & +1 region unit)
|
||||||
|
for (int i = snapToBase(regionUnitX, camera.x - regionUnitX); i <= snapToBase(regionUnitX, camera.x + camera.width + regionUnitX); i += regionUnitX) {
|
||||||
|
for (int j = snapToBase(regionUnitY, camera.y - regionUnitY); j <= snapToBase(regionUnitY, camera.y + camera.height + regionUnitY); j += regionUnitY) {
|
||||||
|
if (!mapPager.FindRegion(i, j)) {
|
||||||
|
RequestRegion(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,9 +36,11 @@
|
|||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
#include "raster_font.hpp"
|
#include "raster_font.hpp"
|
||||||
#include "button.hpp"
|
#include "button.hpp"
|
||||||
|
#include "tile_sheet.hpp"
|
||||||
|
|
||||||
//common
|
//common
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
|
#include "frame_rate.hpp"
|
||||||
|
|
||||||
//client
|
//client
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
@@ -58,6 +60,7 @@ protected:
|
|||||||
void FrameStart();
|
void FrameStart();
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
void FrameEnd();
|
void FrameEnd();
|
||||||
|
void RenderFrame();
|
||||||
void Render(SDL_Surface* const);
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
//Event handlers
|
//Event handlers
|
||||||
@@ -68,24 +71,34 @@ protected:
|
|||||||
void KeyDown(SDL_KeyboardEvent const&);
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
void KeyUp(SDL_KeyboardEvent const&);
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
|
//Network handlers
|
||||||
void HandlePacket(NetworkPacket);
|
void HandlePacket(NetworkPacket);
|
||||||
void HandleDisconnect(NetworkPacket);
|
void HandleDisconnect(NetworkPacket);
|
||||||
void HandlePlayerNew(NetworkPacket);
|
void HandlePlayerNew(NetworkPacket);
|
||||||
void HandlePlayerDelete(NetworkPacket);
|
void HandlePlayerDelete(NetworkPacket);
|
||||||
void HandlePlayerUpdate(NetworkPacket);
|
void HandlePlayerUpdate(NetworkPacket);
|
||||||
|
void HandleRegionContent(NetworkPacket);
|
||||||
|
|
||||||
|
//Server control
|
||||||
void SendState();
|
void SendState();
|
||||||
void RequestDisconnect();
|
void RequestDisconnect();
|
||||||
void RequestShutDown();
|
void RequestShutDown();
|
||||||
|
void RequestRegion(int x, int y);
|
||||||
|
|
||||||
|
//utilities
|
||||||
|
int CheckBufferDistance(Region* const);
|
||||||
|
void UpdateMap();
|
||||||
|
|
||||||
//globals
|
//globals
|
||||||
ConfigUtility& config;
|
ConfigUtility& config;
|
||||||
|
FrameRate fps;
|
||||||
UDPNetworkUtility& network;
|
UDPNetworkUtility& network;
|
||||||
int& clientIndex;
|
int& clientIndex;
|
||||||
|
|
||||||
//graphics
|
//graphics
|
||||||
Image buttonImage;
|
Image buttonImage;
|
||||||
RasterFont font;
|
RasterFont font;
|
||||||
|
TileSheet tileSheet;
|
||||||
|
|
||||||
//map
|
//map
|
||||||
RegionPager<BlankGenerator, DummyFormat> mapPager;
|
RegionPager<BlankGenerator, DummyFormat> mapPager;
|
||||||
@@ -95,6 +108,8 @@ protected:
|
|||||||
Button shutDownButton;
|
Button shutDownButton;
|
||||||
struct {
|
struct {
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
int marginX = 0, marginY = 0;
|
||||||
} camera;
|
} camera;
|
||||||
|
|
||||||
//game
|
//game
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
|
*
|
||||||
|
* This software is provided 'as-is', without any express or implied
|
||||||
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
|
* arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
|
* including commercial applications, and to alter it and redistribute it
|
||||||
|
* freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
* claim that you wrote the original software. If you use this software
|
||||||
|
* in a product, an acknowledgment in the product documentation would be
|
||||||
|
* appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
* misrepresented as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source
|
||||||
|
* distribution.
|
||||||
|
*/
|
||||||
|
#ifndef FRAMERATE_HPP_
|
||||||
|
#define FRAMERATE_HPP_
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
class FrameRate {
|
||||||
|
public:
|
||||||
|
typedef std::chrono::high_resolution_clock Clock;
|
||||||
|
|
||||||
|
FrameRate() = default;
|
||||||
|
int Calculate() {
|
||||||
|
frameCount++;
|
||||||
|
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
|
||||||
|
lastFrameRate = frameCount;
|
||||||
|
frameCount = 0;
|
||||||
|
tick = Clock::now();
|
||||||
|
}
|
||||||
|
return lastFrameRate;
|
||||||
|
}
|
||||||
|
int GetFrameRate() { return lastFrameRate; }
|
||||||
|
private:
|
||||||
|
int frameCount = 0;
|
||||||
|
int lastFrameRate = 0;
|
||||||
|
Clock::time_point tick = Clock::now();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#config
|
#config
|
||||||
INCLUDES+=. ..
|
INCLUDES+=. .. ../map
|
||||||
LIBS+=
|
LIBS+=
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|||||||
@@ -34,8 +34,28 @@ void TileSheet::Unload() {
|
|||||||
XCount = YCount = 0;
|
XCount = YCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, int tile) {
|
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile) {
|
||||||
image.SetClipX(tile % XCount * image.GetClipW());
|
//0 is invisible
|
||||||
image.SetClipY(tile / XCount * image.GetClipH());
|
if (tile == 0) return;
|
||||||
|
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||||
|
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||||
image.DrawTo(dest, x, y);
|
image.DrawTo(dest, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileSheet::DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY) {
|
||||||
|
Region::type_t tile = 0;
|
||||||
|
for (register int i = 0; i < region->GetWidth(); ++i) {
|
||||||
|
for (register int j = 0; j < region->GetHeight(); ++j) {
|
||||||
|
for (register int k = 0; k < region->GetDepth(); ++k) {
|
||||||
|
tile = region->GetTile(i, j, k);
|
||||||
|
//0 is invisible
|
||||||
|
if (tile == 0) continue;
|
||||||
|
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||||
|
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||||
|
image.DrawTo(dest,
|
||||||
|
region->GetX() + i * image.GetClipW() - camX,
|
||||||
|
region->GetY() + j * image.GetClipH() - camY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
#ifndef TILESHEET_HPP_
|
#ifndef TILESHEET_HPP_
|
||||||
#define TILESHEET_HPP_
|
#define TILESHEET_HPP_
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -35,7 +37,8 @@ public:
|
|||||||
void Load(std::string fname, int XCount, int YCount);
|
void Load(std::string fname, int XCount, int YCount);
|
||||||
void Unload();
|
void Unload();
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const dest, int x, int y, int tile);
|
void DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile);
|
||||||
|
void DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY);
|
||||||
|
|
||||||
//accessors
|
//accessors
|
||||||
Image* GetImage() { return ℑ }
|
Image* GetImage() { return ℑ }
|
||||||
|
|||||||
@@ -24,11 +24,11 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
void DummyFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
void DummyFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
//TODO
|
//EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
void DummyFormat::Save(Region* const ptr) {
|
void DummyFormat::Save(Region* const ptr) {
|
||||||
//TODO
|
//EMPTY
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
void VerboseFormat::Load(Region** const ptr, int x, int y) {
|
void VerboseFormat::Load(Region** const ptr, int x, int y) {
|
||||||
|
|||||||
@@ -50,15 +50,28 @@ Region* RegionPagerBase::GetRegion(int x, int y) {
|
|||||||
x = snapToBase(regionWidth, x);
|
x = snapToBase(regionWidth, x);
|
||||||
y = snapToBase(regionHeight, y);
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
//get the region by various means
|
||||||
|
|
||||||
|
//TODO: revert this try/catch point
|
||||||
|
Region* ptr = nullptr;
|
||||||
|
ptr = FindRegion(x, y);
|
||||||
|
if (ptr) return ptr;
|
||||||
|
ptr = LoadRegion(x, y);
|
||||||
|
if (ptr) return ptr;
|
||||||
|
return CreateRegion(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* RegionPagerBase::FindRegion(int x, int y) {
|
||||||
//find the region
|
//find the region
|
||||||
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||||
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
//get the region by other means
|
}
|
||||||
Region* ptr = LoadRegion(x, y);
|
|
||||||
if (ptr) return ptr;
|
Region* RegionPagerBase::PushRegion(Region* ptr) {
|
||||||
return CreateRegion(x, y);
|
regionList.push_front(ptr);
|
||||||
|
return regionList.front();
|
||||||
}
|
}
|
||||||
@@ -33,18 +33,23 @@ public:
|
|||||||
RegionPagerBase(int regionWidth, int regionHeight, int regionDepth);
|
RegionPagerBase(int regionWidth, int regionHeight, int regionDepth);
|
||||||
virtual ~RegionPagerBase();
|
virtual ~RegionPagerBase();
|
||||||
|
|
||||||
|
//tile manipulation
|
||||||
Region::type_t SetTile(int x, int y, int z, Region::type_t v);
|
Region::type_t SetTile(int x, int y, int z, Region::type_t v);
|
||||||
Region::type_t GetTile(int x, int y, int z);
|
Region::type_t GetTile(int x, int y, int z);
|
||||||
|
|
||||||
|
//region manipulation
|
||||||
Region* GetRegion(int x, int y);
|
Region* GetRegion(int x, int y);
|
||||||
|
Region* FindRegion(int x, int y);
|
||||||
|
Region* PushRegion(Region*);
|
||||||
|
|
||||||
//interface
|
//interface
|
||||||
virtual Region* LoadRegion(int x, int y) = 0;
|
virtual Region* LoadRegion(int x, int y) = 0;
|
||||||
virtual Region* SaveRegion(int x, int y) = 0;
|
virtual Region* SaveRegion(int x, int y) = 0;
|
||||||
virtual Region* CreateRegion(int x, int y) = 0;
|
virtual Region* CreateRegion(int x, int y) = 0;
|
||||||
virtual void UnloadRegion(int x, int y) = 0;
|
virtual void UnloadRegion(int x, int y) = 0;
|
||||||
|
//TODO: delete?
|
||||||
|
|
||||||
//accessors
|
//accessors & mutators
|
||||||
//NOTE: don't change the sizes mid-program, it will cause issues
|
//NOTE: don't change the sizes mid-program, it will cause issues
|
||||||
int SetRegionWidth(int i) { return regionWidth = i; }
|
int SetRegionWidth(int i) { return regionWidth = i; }
|
||||||
int SetRegionHeight(int i) { return regionHeight = i; }
|
int SetRegionHeight(int i) { return regionHeight = i; }
|
||||||
@@ -53,6 +58,8 @@ public:
|
|||||||
int GetRegionWidth() const { return regionWidth; }
|
int GetRegionWidth() const { return regionWidth; }
|
||||||
int GetRegionHeight() const { return regionHeight; }
|
int GetRegionHeight() const { return regionHeight; }
|
||||||
int GetRegionDepth() const { return regionDepth; }
|
int GetRegionDepth() const { return regionDepth; }
|
||||||
|
|
||||||
|
std::list<Region*>* GetContainer() { return ®ionList; }
|
||||||
protected:
|
protected:
|
||||||
int regionWidth;
|
int regionWidth;
|
||||||
int regionHeight;
|
int regionHeight;
|
||||||
|
|||||||
+10
-3
@@ -61,7 +61,13 @@ EditorScene::EditorScene(ConfigUtility* const arg1):
|
|||||||
pager.SetRegionDepth(REGION_DEPTH);
|
pager.SetRegionDepth(REGION_DEPTH);
|
||||||
|
|
||||||
//debug
|
//debug
|
||||||
tsheet.Load(config["dir.tilesets"] + "sand.bmp", 12, 3);
|
tsheet.Load(config["dir.tilesets"] + "terrain.bmp", 12, 15);
|
||||||
|
for (int i = 0; i < REGION_WIDTH; i++) {
|
||||||
|
for (int j = 0; j < REGION_HEIGHT; j++) {
|
||||||
|
pager.SetTile(i, j, 0, 14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pager.SetTile(5, 10, 1, 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorScene::~EditorScene() {
|
EditorScene::~EditorScene() {
|
||||||
@@ -85,7 +91,8 @@ void EditorScene::FrameEnd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditorScene::Render(SDL_Surface* const screen) {
|
void EditorScene::Render(SDL_Surface* const screen) {
|
||||||
//debug
|
tsheet.DrawRegionTo(screen, pager.GetRegion(0, 0), camera.x, camera.y);
|
||||||
|
/* //debug
|
||||||
for (int i = 0; i < pager.GetRegionWidth()*2; i++) {
|
for (int i = 0; i < pager.GetRegionWidth()*2; i++) {
|
||||||
for (int j = 0; j < pager.GetRegionHeight()*2; j++) {
|
for (int j = 0; j < pager.GetRegionHeight()*2; j++) {
|
||||||
for (int k = 0; k < pager.GetRegionDepth(); k++) {
|
for (int k = 0; k < pager.GetRegionDepth(); k++) {
|
||||||
@@ -99,7 +106,7 @@ void EditorScene::Render(SDL_Surface* const screen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//draw a big bar across the top (hackish)
|
//draw a big bar across the top (hackish)
|
||||||
buttonImage.SetClipY(0);
|
buttonImage.SetClipY(0);
|
||||||
for (int i = 0; i < screen->w; i += buttonImage.GetClipW()) {
|
for (int i = 0; i < screen->w; i += buttonImage.GetClipW()) {
|
||||||
|
|||||||
@@ -2,6 +2,16 @@ print("Lua script check OK (./rsc)")
|
|||||||
|
|
||||||
function Region.Create(r)
|
function Region.Create(r)
|
||||||
print("Region:Create(r", Region.GetX(r), Region.GetY(r), ")")
|
print("Region:Create(r", Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
for i = 1, Region.GetWidth(r) do
|
||||||
|
for j = 1, Region.GetHeight(r) do
|
||||||
|
if math.abs(i) == math.abs(j) then
|
||||||
|
Region.SetTile(r, i, j, 1, 50)
|
||||||
|
else
|
||||||
|
Region.SetTile(r, i, j, 1, 14)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print("done")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Region.Unload(r)
|
function Region.Unload(r)
|
||||||
|
|||||||
@@ -180,6 +180,9 @@ void ServerApplication::HandlePacket(NetworkPacket packet) {
|
|||||||
case NetworkPacket::Type::PLAYER_UPDATE:
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
HandlePlayerUpdate(packet);
|
HandlePlayerUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
case NetworkPacket::Type::REGION_REQUEST:
|
||||||
|
HandleRegionRequest(packet);
|
||||||
|
break;
|
||||||
//handle errors
|
//handle errors
|
||||||
default:
|
default:
|
||||||
throw(runtime_error("Unknown NetworkPacket::Type encountered"));
|
throw(runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||||
@@ -340,6 +343,14 @@ void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) {
|
|||||||
PumpPacket(packet);
|
PumpPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerApplication::HandleRegionRequest(NetworkPacket packet) {
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
packet.meta.type = NetworkPacket::Type::REGION_CONTENT;
|
||||||
|
packet.regionInfo.region = mapPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y);
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
void ServerApplication::PumpPacket(NetworkPacket packet) {
|
void ServerApplication::PumpPacket(NetworkPacket packet) {
|
||||||
//I don't really like this, but it'll do for now
|
//I don't really like this, but it'll do for now
|
||||||
char buffer[PACKET_BUFFER_SIZE];
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ private:
|
|||||||
void HandlePlayerNew(NetworkPacket);
|
void HandlePlayerNew(NetworkPacket);
|
||||||
void HandlePlayerDelete(NetworkPacket);
|
void HandlePlayerDelete(NetworkPacket);
|
||||||
void HandlePlayerUpdate(NetworkPacket);
|
void HandlePlayerUpdate(NetworkPacket);
|
||||||
|
void HandleRegionRequest(NetworkPacket);
|
||||||
|
|
||||||
void PumpPacket(NetworkPacket);
|
void PumpPacket(NetworkPacket);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user