Compare commits
131 Commits
old
..
release-0.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 854dc0eb45 | |||
| e90afb7e4a | |||
| 0453f6becf | |||
| c8a58ab515 | |||
| 553f8dbfa5 | |||
| 2bacdcdab7 | |||
| 99aecbfdbb | |||
| 27bda5dc28 | |||
| 962f3f5dd0 | |||
| 41077b43b3 | |||
| 4410ab892f | |||
| 60000cb0cf | |||
| 66b00255d5 | |||
| a5b68cf1fd | |||
| 4cff57fe71 | |||
| 38b603fc8f | |||
| 47684380a9 | |||
| e4bfbfb906 | |||
| 9db86c19f6 | |||
| d5b551cec3 | |||
| 7e500027e3 | |||
| dd786ba579 | |||
| 5a57888305 | |||
| 706aa5e1d7 | |||
| 19c1b1197d | |||
| 5cf62f5517 | |||
| 56d02ad8d4 | |||
| 006a72174f | |||
| 0cbc9dd9db | |||
| 60c31ff56d | |||
| 6a204643f6 | |||
| 59285d1630 | |||
| a850d6b1af | |||
| f17fa0f345 | |||
| 756d4e770d | |||
| 7bb5e8ce0d | |||
| 975533afba | |||
| 19749f7c87 | |||
| 7703c4b0ad | |||
| dc8f594eec | |||
| 4629b7302b | |||
| 02d83d1f16 | |||
| 91c9cef56d | |||
| f7d4912942 | |||
| eb8674b84f | |||
| ff44e4d916 | |||
| e66540f114 | |||
| 639c0c70e3 | |||
| 37b02352e2 | |||
| 31c8bd7fd2 | |||
| 808fe570a3 | |||
| e706cc9d13 | |||
| eb02cc4b6a | |||
| 31cca61d1c | |||
| 071e0d9021 | |||
| a494bfbb38 | |||
| baadf554cd | |||
| 9df16fede0 | |||
| dd0ad31ac6 | |||
| be26c9d103 | |||
| a448c8fb68 | |||
| de1a6a050f | |||
| 49c9abe91b | |||
| 3b05476689 | |||
| 1c032bfc47 | |||
| 1a7457f650 | |||
| e640eda771 | |||
| fc2b67608f | |||
| a3a990cc01 | |||
| f6a4674a2f | |||
| 865620b4a8 | |||
| 1e0ed350fc | |||
| 6ccc874583 | |||
| ca86dc5fb8 | |||
| e3605e4dc5 | |||
| cb9aef95ec | |||
| 09f97de0e6 | |||
| f5466b9982 | |||
| e176a60d28 | |||
| dc24d1b059 | |||
| fa3fc18ddf | |||
| c2941cd3e8 | |||
| bf15a5d957 | |||
| f01463bab3 | |||
| 54cd26b76f | |||
| 2bd8adaf69 | |||
| 26eba2def6 | |||
| 43852ce755 | |||
| 81fab06e3b | |||
| 77a90f9c0c | |||
| bc32f2a2f0 | |||
| 76bfecd466 | |||
| d4eb1e7b8d | |||
| 2ec307510d | |||
| 0b4e6003d6 | |||
| 7e603ffa89 | |||
| 6fc8570cf4 | |||
| 0bfd916df4 | |||
| 88aee0f4f5 | |||
| 0d3c3243a0 | |||
| 871b1136c2 | |||
| f64c935ffe | |||
| 600ec6789b | |||
| 65a3937592 | |||
| 719c8f49a6 | |||
| 29928c0b92 | |||
| a88a1f7cf7 | |||
| 46efbfbe9a | |||
| 26ff8dcc8f | |||
| 9c91e9d5fd | |||
| 3628d3c1fd | |||
| 6c9406147a | |||
| aae244de39 | |||
| d5b14c2679 | |||
| a54fbfb9e9 | |||
| 9cbbfe77b7 | |||
| 9b64c67068 | |||
| de0227a1cf | |||
| 1dfeabf195 | |||
| 6c5197f3f2 | |||
| 09453cc24e | |||
| 4b62310158 | |||
| 43f2190c3e | |||
| 3225da6b13 | |||
| 0c233b8764 | |||
| 027d0125ef | |||
| e4884c3e18 | |||
| b675f516e7 | |||
| d5f7363c33 | |||
| 7458962ad4 | |||
| 0a0b61287e |
@@ -1,6 +1,6 @@
|
|||||||
#Editor generated files
|
#Editor generated files
|
||||||
#*.sln
|
*.sln
|
||||||
#*.vcproj
|
*.vcproj
|
||||||
*.suo
|
*.suo
|
||||||
*.ncb
|
*.ncb
|
||||||
*.user
|
*.user
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
_This project is currently in it's early prototype stage. You can see other versions in various branches or tagged as prototype-X._
|
The most recent stable windows build can be found [here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
|
||||||
|
|
||||||
Tortuga is a 2D multiplayer role playing game set in a large archipelago occupied by warring pirate clans. The emphasis of this game is on multiplayer cooperation, competition, and server customization. The game runs on highly customizable server software that can support up to 150 simultaneous players or more. The player characters are tied to the server where they are created and are susceptible to permadeath: deletion of a character upon death.
|
Tortuga is an open source 2D multiplayer role playing game featuring permadeath (deletion of a character upon death). The emphasis of this game is on multiplayer cooperation, competition, exploration and customization. The game runs on customizable server software that can support up to 150 simultaneous players or more.
|
||||||
|
|
||||||
## Dependencies
|
This game is inspired by classic 2D RPGs, as well as more modern sandbox MMOs. This project is currently independently created and funded, with the goal of creating a game that will engage user's imagination and inspire a large modding community.
|
||||||
|
|
||||||
* [SDL](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
## External Dependencies
|
||||||
* [SDL_net](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
|
|
||||||
|
|
||||||
## Instructions
|
* [SDL 1.6](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
||||||
|
* [SDL_net 1.2](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension
|
||||||
|
* [lua 5.2](http://www.lua.org/) - The lua programming language
|
||||||
|
* [SQLite3](http://www.sqlite.org/) - A lightweight SQL database engine
|
||||||
|
|
||||||
* This project uses C++11, which is available via GNU (or MinGW) 4.7, or Visual Studio 2012. Personally, I'm using MinGW 4.7.2.
|
## Documentation
|
||||||
* I'm trying to keep this as IDE agnostic as possible, so if you use an IDE, please add it's files to .gitignore.
|
|
||||||
* You can read more details on the Tortuga wiki [here](https://github.com/Ratstail91/Tortuga/wiki).
|
[Tortuga Game Design Document](https://github.com/Ratstail91/Tortuga/blob/docs/design%20doc.docx?raw=true)
|
||||||
|
[Tortuga Technical Document](https://github.com/Ratstail91/Tortuga/blob/docs/technical%20doc.docx?raw=true)
|
||||||
|
|
||||||
## Copyright
|
## Copyright
|
||||||
|
|
||||||
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
|
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
|
||||||
|
|
||||||
Copyright (c) 2013 Kayne Ruse
|
Copyright (c) 2013, 2014 Kayne Ruse
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef CHANNELS_HPP_
|
||||||
|
#define CHANNELS_HPP_
|
||||||
|
|
||||||
|
enum Channels {
|
||||||
|
SERVER = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* arising from the use of this software.
|
* arising from the use of this software.
|
||||||
*
|
*
|
||||||
* Permission is granted to anyone to use this software for any purpose,
|
* Permission is granted to anyone to use this software for any purpose,
|
||||||
* including commercial applications, and to alter it and redistribute it
|
* including commercial ClientApplications, and to alter it and redistribute it
|
||||||
* freely, subject to the following restrictions:
|
* freely, subject to the following restrictions:
|
||||||
*
|
*
|
||||||
* 1. The origin of this software must not be misrepresented; you must not
|
* 1. The origin of this software must not be misrepresented; you must not
|
||||||
@@ -24,17 +24,23 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Static declarations
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
ClientApplication ClientApplication::instance;
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Scene headers
|
//Scene headers
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
//Add the custom scene headers here
|
//Add the custom scene headers here
|
||||||
#include "in_combat.hpp"
|
|
||||||
#include "in_world.hpp"
|
|
||||||
#include "lobby.hpp"
|
|
||||||
#include "main_menu.hpp"
|
|
||||||
#include "option_screen.hpp"
|
|
||||||
#include "splash_screen.hpp"
|
#include "splash_screen.hpp"
|
||||||
|
#include "main_menu.hpp"
|
||||||
|
#include "options_menu.hpp"
|
||||||
|
#include "lobby_menu.hpp"
|
||||||
|
#include "in_world.hpp"
|
||||||
|
#include "in_combat.hpp"
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Public access members
|
//Public access members
|
||||||
@@ -45,60 +51,33 @@ ClientApplication::ClientApplication() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClientApplication::~ClientApplication() {
|
ClientApplication::~ClientApplication() {
|
||||||
UnloadScene();
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ClientApplication::Init()
|
|
||||||
* This function initializes the entire program. There are a number of things
|
|
||||||
* that could go wrong here, which is why there is such an unusual order of
|
|
||||||
* operations.
|
|
||||||
* Important things to note:
|
|
||||||
* The APIs are initiated here.
|
|
||||||
* The global objects are initialized here.
|
|
||||||
* The game's screen is created here, based on information loaded from the config file.
|
|
||||||
* The ConfigUtility's call to Load() also ensures that the "rsc\" folder is in the directory. It's easy to forget it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ClientApplication::Init() {
|
void ClientApplication::Init() {
|
||||||
//load the config file
|
//load the prerequisites
|
||||||
try {
|
config.Load("rsc\\config.cfg");
|
||||||
configUtil->Load("rsc/config.cfg");
|
|
||||||
}
|
|
||||||
catch(std::runtime_error& e) {
|
|
||||||
std::string s = e.what();
|
|
||||||
s += "; Ensure that the \"rsc\" directory is present";
|
|
||||||
throw(std::runtime_error(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
//initialize the APIs
|
//initialize SDL
|
||||||
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_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||||
|
|
||||||
|
//initialize SDL_net
|
||||||
if (SDLNet_Init()) {
|
if (SDLNet_Init()) {
|
||||||
throw(std::runtime_error("Failed to initialize SDL_net"));
|
throw(std::runtime_error("Failed to initialize SDL_net"));
|
||||||
}
|
}
|
||||||
|
network.Open(0, PACKET_BUFFER_SIZE);
|
||||||
//create the screen
|
|
||||||
Uint32 flags = SDL_HWSURFACE | SDL_DOUBLEBUF;
|
|
||||||
flags |= configUtil->Bool("screen.f") ? SDL_FULLSCREEN : 0;
|
|
||||||
|
|
||||||
BaseScene::SetScreen(
|
|
||||||
configUtil->Int("screen.w"),
|
|
||||||
configUtil->Int("screen.h"),
|
|
||||||
SDL_GetVideoInfo()->vfmt->BitsPerPixel,
|
|
||||||
flags);
|
|
||||||
|
|
||||||
//initiate the remaining singletons
|
|
||||||
netUtil->Open(0, sizeof(Packet));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientApplication::Proc() {
|
void ClientApplication::Proc() {
|
||||||
LoadScene(SceneList::FIRST);
|
LoadScene(SceneList::FIRST);
|
||||||
|
|
||||||
//prepare the time system
|
//prepare the time system
|
||||||
typedef std::chrono::high_resolution_clock Clock;
|
typedef std::chrono::steady_clock Clock;
|
||||||
|
|
||||||
Clock::duration delta(5 * 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;
|
||||||
|
|
||||||
@@ -110,15 +89,13 @@ void ClientApplication::Proc() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//update the current time & give the computer as much of a break as possible
|
//update the current time
|
||||||
while ((realTime = Clock::now()) < simTime) {
|
realTime = Clock::now();
|
||||||
SDL_Delay(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,14 +107,7 @@ void ClientApplication::Proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ClientApplication::Quit() {
|
void ClientApplication::Quit() {
|
||||||
//clean up the singletons
|
network.Close();
|
||||||
netUtil->Close();
|
|
||||||
surfaceMgr->FreeAll();
|
|
||||||
|
|
||||||
//clean up the scene
|
|
||||||
UnloadScene();
|
|
||||||
|
|
||||||
//deinitialize the APIs
|
|
||||||
SDLNet_Quit();
|
SDLNet_Quit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
@@ -148,29 +118,27 @@ 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::SPLASHSCREEN:
|
||||||
|
activeScene = new SplashScreen(&config);
|
||||||
|
break;
|
||||||
|
case SceneList::MAINMENU:
|
||||||
|
activeScene = new MainMenu(&config);
|
||||||
|
break;
|
||||||
|
case SceneList::OPTIONSMENU:
|
||||||
|
activeScene = new OptionsMenu(&config);
|
||||||
|
break;
|
||||||
|
case SceneList::LOBBYMENU:
|
||||||
|
activeScene = new LobbyMenu(&config, &network, &clientIndex);
|
||||||
|
break;
|
||||||
|
case SceneList::INWORLD:
|
||||||
|
activeScene = new InWorld(&config, &network, &clientIndex);
|
||||||
|
break;
|
||||||
case SceneList::INCOMBAT:
|
case SceneList::INCOMBAT:
|
||||||
activeScene = new InCombat();
|
activeScene = new InCombat();
|
||||||
break;
|
break;
|
||||||
case SceneList::INWORLD:
|
|
||||||
activeScene = new InWorld();
|
|
||||||
break;
|
|
||||||
case SceneList::LOBBY:
|
|
||||||
activeScene = new Lobby();
|
|
||||||
break;
|
|
||||||
case SceneList::MAINMENU:
|
|
||||||
activeScene = new MainMenu();
|
|
||||||
break;
|
|
||||||
case SceneList::OPTIONSCREEN:
|
|
||||||
activeScene = new OptionScreen();
|
|
||||||
break;
|
|
||||||
case SceneList::FIRST:
|
|
||||||
case SceneList::SPLASHSCREEN:
|
|
||||||
activeScene = new SplashScreen();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw(std::logic_error("Failed to recognize the scene index"));
|
throw(std::logic_error("Failed to recognize the scene index"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,39 +24,34 @@
|
|||||||
|
|
||||||
#include "scene_list.hpp"
|
#include "scene_list.hpp"
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
#include "singleton.hpp"
|
|
||||||
#include "packet.hpp"
|
|
||||||
#include "information_manager.hpp"
|
|
||||||
|
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "surface_manager.hpp"
|
#include "network_packet.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
|
|
||||||
#include "SDL/SDL.h"
|
|
||||||
|
|
||||||
class ClientApplication {
|
class ClientApplication {
|
||||||
public:
|
private:
|
||||||
/* Public access members */
|
|
||||||
ClientApplication();
|
ClientApplication();
|
||||||
~ClientApplication();
|
~ClientApplication();
|
||||||
|
static ClientApplication instance;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ClientApplication* GetInstance() { return &instance; }
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Proc();
|
void Proc();
|
||||||
void Quit();
|
void Quit();
|
||||||
|
|
||||||
ClientApplication(ClientApplication const&) = delete;
|
|
||||||
ClientApplication(ClientApplication const&&) = delete;
|
|
||||||
private:
|
private:
|
||||||
/* Private access members */
|
//Private access members
|
||||||
void LoadScene(SceneList sceneIndex);
|
void LoadScene(SceneList sceneIndex);
|
||||||
void UnloadScene();
|
void UnloadScene();
|
||||||
|
|
||||||
BaseScene* activeScene = nullptr;
|
BaseScene* activeScene = nullptr;
|
||||||
|
|
||||||
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
|
ConfigUtility config;
|
||||||
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
|
UDPNetworkUtility network;
|
||||||
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
|
int clientIndex = -1; //replace with a struct?
|
||||||
InformationManager* infoMgr = Singleton<InformationManager>::Get();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,326 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#include "in_world.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Quick and dirty
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
static std::string itos(int i) {
|
|
||||||
char buffer[20];
|
|
||||||
snprintf(buffer, 20, "%d", i);
|
|
||||||
return std::string(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Public access members
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
InWorld::InWorld() {
|
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "entering InWorld" << endl;
|
|
||||||
#endif
|
|
||||||
cout << "Client Index: " << infoMgr->GetClientIndex() << endl;
|
|
||||||
font.SetSurface(surfaceMgr->Get("font"));
|
|
||||||
|
|
||||||
//debugging
|
|
||||||
Packet p;
|
|
||||||
p.meta.type = Packet::Type::PLAYER_NEW;
|
|
||||||
p.meta.clientIndex = infoMgr->GetClientIndex();
|
|
||||||
|
|
||||||
snprintf(p.playerInfo.handle, PACKET_STRING_SIZE, "%s", configUtil->CString("handle"));
|
|
||||||
snprintf(p.playerInfo.avatar, PACKET_STRING_SIZE, "%s", configUtil->CString("avatar"));
|
|
||||||
p.playerInfo.position.x = 50;
|
|
||||||
p.playerInfo.position.y = 50;
|
|
||||||
p.playerInfo.motion.x = 0;
|
|
||||||
p.playerInfo.motion.y = 0;
|
|
||||||
|
|
||||||
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
|
|
||||||
|
|
||||||
//request a sync
|
|
||||||
p.meta.type = Packet::Type::SYNCHRONIZE;
|
|
||||||
p.meta.clientIndex = infoMgr->GetClientIndex();
|
|
||||||
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
|
|
||||||
}
|
|
||||||
|
|
||||||
InWorld::~InWorld() {
|
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "leaving InWorld" << endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Frame loop
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
void InWorld::FrameStart() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::Update(double delta) {
|
|
||||||
while(HandlePacket(popNetworkPacket()));
|
|
||||||
|
|
||||||
for (auto& it : playerCharacters) {
|
|
||||||
it.second.Update(delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::FrameEnd() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::Render(SDL_Surface* const screen) {
|
|
||||||
clockFrameRate();
|
|
||||||
|
|
||||||
for (auto& it : playerCharacters) {
|
|
||||||
it.second.DrawTo(screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
//since we're using this twice, make a tmp var
|
|
||||||
string fps = itos(getFrameRate());
|
|
||||||
font.DrawStringTo(fps, screen, screen->w - fps.size() * font.GetCharW(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Event handlers
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
void InWorld::QuitEvent() {
|
|
||||||
//ensure that the client is disconnected properly
|
|
||||||
ExitGame();
|
|
||||||
SetNextScene(SceneList::QUIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
|
|
||||||
//general
|
|
||||||
switch(key.keysym.sym) {
|
|
||||||
case SDLK_ESCAPE:
|
|
||||||
ExitGame();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//player movement
|
|
||||||
if (infoMgr->GetPlayerIndex() == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(key.keysym.sym) {
|
|
||||||
case SDLK_w:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::NORTH);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
case SDLK_s:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::SOUTH);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
case SDLK_a:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::WEST);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
case SDLK_d:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::EAST);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
|
||||||
//player movement reversed
|
|
||||||
switch(key.keysym.sym) {
|
|
||||||
case SDLK_w:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::SOUTH);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
case SDLK_s:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::NORTH);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
case SDLK_a:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::EAST);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
case SDLK_d:
|
|
||||||
playerCharacters[infoMgr->GetPlayerIndex()].MoveDirection(CardinalDirection::WEST);
|
|
||||||
SendState();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Utilities
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
int InWorld::HandlePacket(Packet p) {
|
|
||||||
switch(p.meta.type) {
|
|
||||||
case Packet::Type::NONE:
|
|
||||||
//DO NOTHING
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case Packet::Type::PING:
|
|
||||||
//quick pong
|
|
||||||
p.meta.type = Packet::Type::PONG;
|
|
||||||
p.meta.clientIndex = infoMgr->GetClientIndex();
|
|
||||||
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
|
|
||||||
break;
|
|
||||||
case Packet::Type::PONG:
|
|
||||||
//
|
|
||||||
break;
|
|
||||||
// case Packet::Type::BROADCAST_REQUEST:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
// case Packet::Type::BROADCAST_RESPONSE:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
// case Packet::Type::JOIN_REQUEST:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
// case Packet::Type::JOIN_RESPONSE:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
case Packet::Type::DISCONNECT:
|
|
||||||
HandleDisconnection(p);
|
|
||||||
break;
|
|
||||||
// case Packet::Type::SYNCHRONIZE:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
case Packet::Type::PLAYER_NEW:
|
|
||||||
AddPlayer(p);
|
|
||||||
break;
|
|
||||||
case Packet::Type::PLAYER_DELETE:
|
|
||||||
RemovePlayer(p);
|
|
||||||
break;
|
|
||||||
case Packet::Type::PLAYER_UPDATE:
|
|
||||||
UpdatePlayer(p);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type))));
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::Disconnect() {
|
|
||||||
Packet p;
|
|
||||||
|
|
||||||
//delete the player
|
|
||||||
p.meta.type = Packet::Type::PLAYER_DELETE;
|
|
||||||
p.meta.clientIndex = infoMgr->GetClientIndex();
|
|
||||||
p.playerInfo.index = infoMgr->GetPlayerIndex();
|
|
||||||
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
|
|
||||||
|
|
||||||
//disconnect
|
|
||||||
p.meta.type = Packet::Type::DISCONNECT;
|
|
||||||
p.meta.clientIndex = infoMgr->GetClientIndex();
|
|
||||||
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
|
|
||||||
|
|
||||||
netUtil->Unbind(GAME_CHANNEL);
|
|
||||||
|
|
||||||
//reset the client
|
|
||||||
infoMgr->ResetClientIndex();
|
|
||||||
infoMgr->ResetPlayerIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::ExitGame() {
|
|
||||||
Disconnect();
|
|
||||||
SetNextScene(SceneList::MAINMENU);
|
|
||||||
endQueueThread();
|
|
||||||
cout << "The game session has ended" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::HandleDisconnection(Packet& disconnect) {
|
|
||||||
Disconnect();
|
|
||||||
SetNextScene(SceneList::MAINMENU);
|
|
||||||
endQueueThread();
|
|
||||||
cout << "You have been disconnected" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::AddPlayer(Packet& p) {
|
|
||||||
if (playerCharacters.find(p.playerInfo.index) != playerCharacters.end()) {
|
|
||||||
throw(runtime_error("Duplicate players detected"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//position
|
|
||||||
playerCharacters[p.playerInfo.index].SetPosition(p.playerInfo.position);
|
|
||||||
playerCharacters[p.playerInfo.index].SetMotion(p.playerInfo.motion);
|
|
||||||
|
|
||||||
//sprite
|
|
||||||
playerCharacters[p.playerInfo.index].GetSprite()->SetSurface(surfaceMgr->Get(p.playerInfo.avatar), 32, 48);
|
|
||||||
playerCharacters[p.playerInfo.index].FaceDirection();
|
|
||||||
|
|
||||||
//is it this player?
|
|
||||||
if (p.meta.clientIndex == infoMgr->GetClientIndex()) {
|
|
||||||
infoMgr->SetPlayerIndex(p.playerInfo.index);
|
|
||||||
}
|
|
||||||
|
|
||||||
//debugging
|
|
||||||
cout << "New player, index " << p.playerInfo.index << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::RemovePlayer(Packet& p) {
|
|
||||||
if (playerCharacters.find(p.playerInfo.index) == playerCharacters.end()) {
|
|
||||||
throw(runtime_error("Player to delete not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
playerCharacters.erase(p.playerInfo.index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::UpdatePlayer(Packet& p) {
|
|
||||||
if (playerCharacters.find(p.playerInfo.index) == playerCharacters.end()) {
|
|
||||||
AddPlayer(p);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
playerCharacters[p.playerInfo.index].SetPosition(p.playerInfo.position);
|
|
||||||
playerCharacters[p.playerInfo.index].SetMotion(p.playerInfo.motion);
|
|
||||||
playerCharacters[p.playerInfo.index].FaceDirection();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InWorld::SendState() {
|
|
||||||
//send the state of this player's character
|
|
||||||
if (infoMgr->GetPlayerIndex() == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet p;
|
|
||||||
p.meta.type = Packet::Type::PLAYER_UPDATE;
|
|
||||||
p.meta.clientIndex = infoMgr->GetClientIndex();
|
|
||||||
p.playerInfo.index = infoMgr->GetPlayerIndex();
|
|
||||||
p.playerInfo.position = playerCharacters[infoMgr->GetPlayerIndex()].GetPosition();
|
|
||||||
p.playerInfo.motion = playerCharacters[infoMgr->GetPlayerIndex()].GetMotion();
|
|
||||||
|
|
||||||
netUtil->Send(GAME_CHANNEL, &p, sizeof(Packet));
|
|
||||||
}
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#include "lobby.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Quick and dirty
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
static std::string itos(int i) {
|
|
||||||
char buffer[20];
|
|
||||||
snprintf(buffer, 20, "%d", i);
|
|
||||||
return std::string(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Public access members
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
Lobby::Lobby() {
|
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "entering Lobby" << endl;
|
|
||||||
#endif
|
|
||||||
refreshButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Refresh");
|
|
||||||
joinButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Join");
|
|
||||||
backButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3 * 2, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Back");
|
|
||||||
|
|
||||||
font.SetSurface(surfaceMgr->Get("font"));
|
|
||||||
listBox.x = 280;
|
|
||||||
listBox.y = 50;
|
|
||||||
listBox.w = GetScreen()->w - listBox.x - 50;
|
|
||||||
listBox.h = font.GetCharH();
|
|
||||||
|
|
||||||
serverList.push_back({"foo",{0,0}});
|
|
||||||
serverList.push_back({"bar",{0,0}});
|
|
||||||
serverList.push_back({"foobar",{0,0}});
|
|
||||||
|
|
||||||
flushNetworkQueue();
|
|
||||||
beginQueueThread();
|
|
||||||
BroadcastNetwork();
|
|
||||||
}
|
|
||||||
|
|
||||||
Lobby::~Lobby() {
|
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "leaving Lobby" << endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Frame loop
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
void Lobby::FrameStart() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::Update(double delta) {
|
|
||||||
while(HandlePacket(popNetworkPacket()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::FrameEnd() {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::Render(SDL_Surface* const screen) {
|
|
||||||
refreshButton.DrawTo(screen);
|
|
||||||
joinButton.DrawTo(screen);
|
|
||||||
backButton.DrawTo(screen);
|
|
||||||
|
|
||||||
for (int i = 0; i < serverList.size(); i++) {
|
|
||||||
if (selectedServer == &serverList[i]) {
|
|
||||||
//draw the highlight box
|
|
||||||
SDL_Rect r = listBox;
|
|
||||||
r.y += i * font.GetCharH();
|
|
||||||
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39));
|
|
||||||
}
|
|
||||||
font.DrawStringTo(serverList[i].name, screen, listBox.x, listBox.y + i * font.GetCharH());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Event handlers
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
void Lobby::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
|
||||||
refreshButton.MouseMotion(motion);
|
|
||||||
joinButton.MouseMotion(motion);
|
|
||||||
backButton.MouseMotion(motion);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
|
||||||
refreshButton.MouseButtonDown(button);
|
|
||||||
joinButton.MouseButtonDown(button);
|
|
||||||
backButton.MouseButtonDown(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
|
||||||
if (refreshButton.MouseButtonUp(button) == Button::State::HOVER) {
|
|
||||||
BroadcastNetwork();
|
|
||||||
selectedServer = nullptr;
|
|
||||||
}
|
|
||||||
else if (joinButton.MouseButtonUp(button) == Button::State::HOVER) {
|
|
||||||
if (selectedServer) {
|
|
||||||
ConnectToServer(selectedServer);
|
|
||||||
selectedServer = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
|
|
||||||
SetNextScene(SceneList::MAINMENU);
|
|
||||||
endQueueThread();
|
|
||||||
selectedServer = nullptr;
|
|
||||||
}
|
|
||||||
else if (
|
|
||||||
//clicked within bounds TODO: make the damn collision system
|
|
||||||
button.x > listBox.x &&
|
|
||||||
button.y > listBox.y &&
|
|
||||||
button.x < listBox.x + listBox.w &&
|
|
||||||
button.y < listBox.y + (listBox.h * serverList.size())
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//selecting a server
|
|
||||||
selectedServer = &serverList[(button.y - listBox.y) / listBox.h];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//lose focus on a server
|
|
||||||
selectedServer = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::KeyDown(SDL_KeyboardEvent const& key) {
|
|
||||||
switch(key.keysym.sym) {
|
|
||||||
case SDLK_ESCAPE:
|
|
||||||
SetNextScene(SceneList::MAINMENU);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::KeyUp(SDL_KeyboardEvent const& key) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Utilities
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
int Lobby::HandlePacket(Packet p) {
|
|
||||||
switch(p.meta.type) {
|
|
||||||
case Packet::Type::NONE:
|
|
||||||
//DO NOTHING
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case Packet::Type::PING:
|
|
||||||
//quick pong
|
|
||||||
p.meta.type = Packet::Type::PONG;
|
|
||||||
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
|
|
||||||
break;
|
|
||||||
case Packet::Type::PONG:
|
|
||||||
//
|
|
||||||
break;
|
|
||||||
// case Packet::Type::BROADCAST_REQUEST:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
case Packet::Type::BROADCAST_RESPONSE:
|
|
||||||
PushServer(p);
|
|
||||||
break;
|
|
||||||
// case Packet::Type::JOIN_REQUEST:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
case Packet::Type::JOIN_RESPONSE:
|
|
||||||
BeginGame(p);
|
|
||||||
break;
|
|
||||||
// case Packet::Type::DISCONNECT:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
// case Packet::Type::SYNCHRONIZE:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
// case Packet::Type::PLAYER_NEW:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
// case Packet::Type::PLAYER_DELETE:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
// case Packet::Type::PLAYER_UPDATE:
|
|
||||||
// //
|
|
||||||
// break;
|
|
||||||
default:
|
|
||||||
throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type))));
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::BroadcastNetwork() {
|
|
||||||
Packet p;
|
|
||||||
p.meta.type = Packet::Type::BROADCAST_REQUEST;
|
|
||||||
netUtil->Send("255.255.255.255", configUtil->Int("server.port"), &p, sizeof(Packet));
|
|
||||||
serverList.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::PushServer(Packet& bcast) {
|
|
||||||
ServerEntry entry;
|
|
||||||
entry.name = bcast.serverInfo.name;
|
|
||||||
entry.address = bcast.meta.address;
|
|
||||||
serverList.push_back(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::ConnectToServer(ServerEntry* server) {
|
|
||||||
//_attempt_ to connect to a server
|
|
||||||
if (!server) {
|
|
||||||
throw(runtime_error("No server received"));
|
|
||||||
}
|
|
||||||
Packet p;
|
|
||||||
p.meta.type = Packet::Type::JOIN_REQUEST;
|
|
||||||
netUtil->Send(&server->address, reinterpret_cast<void*>(&p), sizeof(Packet));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Lobby::BeginGame(Packet& response) {
|
|
||||||
//should be downloading the resources here as well
|
|
||||||
infoMgr->SetClientIndex(response.meta.clientIndex);
|
|
||||||
netUtil->Bind(&response.meta.address, GAME_CHANNEL);
|
|
||||||
SetNextScene(SceneList::INWORLD);
|
|
||||||
}
|
|
||||||
@@ -27,21 +27,16 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int main(int, char**) {
|
int main(int, char**) {
|
||||||
#ifdef DEBUG
|
cout << "Beginning client" << endl;
|
||||||
cout << "Beginning program" << endl;
|
|
||||||
#endif
|
|
||||||
try {
|
try {
|
||||||
ClientApplication app;
|
ClientApplication::GetInstance()->Init();
|
||||||
app.Init();
|
ClientApplication::GetInstance()->Proc();
|
||||||
app.Proc();
|
ClientApplication::GetInstance()->Quit();
|
||||||
app.Quit();
|
|
||||||
}
|
}
|
||||||
catch(exception& e) {
|
catch(exception& e) {
|
||||||
cerr << "Fatal error: " << e.what() << endl;
|
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "Clean exit" << endl;
|
cout << "Clean exit" << endl;
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
#config
|
#config
|
||||||
LOCALLIBS=../lib/libCommon.a
|
INCLUDES+=. scenes ../common ../common/graphics ../common/map ../common/network ../common/ui
|
||||||
LIB=$(LOCALLIBS) -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL
|
LIBS+=libclient.a ../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
|
||||||
INCLUDES=../common
|
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
#source
|
#source
|
||||||
SRC=$(wildcard *.cpp)
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
#objects
|
#objects
|
||||||
OBJDIR=obj
|
OBJDIR=obj
|
||||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
#output
|
#output
|
||||||
OUTDIR=../out
|
OUTDIR=../out
|
||||||
@@ -17,7 +19,8 @@ OUT=$(addprefix $(OUTDIR)/,client)
|
|||||||
|
|
||||||
#targets
|
#targets
|
||||||
all: $(OBJ) $(OUT)
|
all: $(OBJ) $(OUT)
|
||||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
|
$(MAKE) -C scenes
|
||||||
|
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||||
|
|
||||||
$(OBJ): | $(OBJDIR)
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
@@ -32,6 +35,9 @@ $(OUTDIR):
|
|||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) *.o *.a *.exe
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,10 @@
|
|||||||
*/
|
*/
|
||||||
#include "player_character.hpp"
|
#include "player_character.hpp"
|
||||||
|
|
||||||
|
#define WALKING_SPEED 140
|
||||||
|
|
||||||
void PlayerCharacter::Update(double delta) {
|
void PlayerCharacter::Update(double delta) {
|
||||||
if (limitSpeed) {
|
if (diagonal) {
|
||||||
constexpr double d = 1.0/sqrt(2);
|
constexpr double d = 1.0/sqrt(2);
|
||||||
position += motion * delta * d;
|
position += motion * delta * d;
|
||||||
}
|
}
|
||||||
@@ -32,83 +34,84 @@ void PlayerCharacter::Update(double delta) {
|
|||||||
sprite.Update(delta);
|
sprite.Update(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerCharacter::MoveDirection(CardinalDirection cd) {
|
void PlayerCharacter::AdjustDirection(Direction direction) {
|
||||||
//shift the movement in this direction
|
//shift the movement in this direction
|
||||||
switch(cd) {
|
switch(direction) {
|
||||||
case CardinalDirection::NORTH:
|
case Direction::NORTH:
|
||||||
if (motion.y >= 0) {
|
if (motion.y >= 0) {
|
||||||
motion.y -= WALKING_SPEED;
|
motion.y -= WALKING_SPEED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CardinalDirection::SOUTH:
|
case Direction::SOUTH:
|
||||||
if (motion.y <= 0) {
|
if (motion.y <= 0) {
|
||||||
motion.y += WALKING_SPEED;
|
motion.y += WALKING_SPEED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CardinalDirection::WEST:
|
case Direction::WEST:
|
||||||
if (motion.x >= 0) {
|
if (motion.x >= 0) {
|
||||||
motion.x -= WALKING_SPEED;
|
motion.x -= WALKING_SPEED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CardinalDirection::EAST:
|
case Direction::EAST:
|
||||||
if (motion.x <= 0) {
|
if (motion.x <= 0) {
|
||||||
motion.x += WALKING_SPEED;
|
motion.x += WALKING_SPEED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//face the correct direction
|
//face the correct direction
|
||||||
FaceDirection();
|
ResetDirection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerCharacter::FaceDirection(CardinalDirection cd) {
|
void PlayerCharacter::FaceDirection(Direction direction) {
|
||||||
switch(cd) {
|
//this function depends on the format of the sprite sheets
|
||||||
case CardinalDirection::NORTH:
|
switch(direction) {
|
||||||
sprite.SetCurrentStrip(1);
|
case Direction::NORTH:
|
||||||
|
sprite.SetYIndex(1);
|
||||||
break;
|
break;
|
||||||
case CardinalDirection::SOUTH:
|
case Direction::SOUTH:
|
||||||
sprite.SetCurrentStrip(0);
|
sprite.SetYIndex(0);
|
||||||
break;
|
break;
|
||||||
case CardinalDirection::WEST:
|
case Direction::WEST:
|
||||||
sprite.SetCurrentStrip(2);
|
sprite.SetYIndex(2);
|
||||||
break;
|
break;
|
||||||
case CardinalDirection::EAST:
|
case Direction::EAST:
|
||||||
sprite.SetCurrentStrip(3);
|
sprite.SetYIndex(3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerCharacter::FaceDirection() {
|
void PlayerCharacter::ResetDirection() {
|
||||||
//base the direction on the character's movement
|
//base the direction on the character's movement
|
||||||
if (motion.y < 0) {
|
|
||||||
FaceDirection(CardinalDirection::NORTH);
|
|
||||||
}
|
|
||||||
if (motion.y > 0) {
|
if (motion.y > 0) {
|
||||||
FaceDirection(CardinalDirection::SOUTH);
|
FaceDirection(Direction::SOUTH);
|
||||||
}
|
}
|
||||||
if (motion.x < 0) {
|
else if (motion.y < 0) {
|
||||||
FaceDirection(CardinalDirection::WEST);
|
FaceDirection(Direction::NORTH);
|
||||||
}
|
}
|
||||||
if (motion.x > 0) {
|
else if (motion.x > 0) {
|
||||||
FaceDirection(CardinalDirection::EAST);
|
FaceDirection(Direction::EAST);
|
||||||
}
|
}
|
||||||
CheckSpeed();
|
else if (motion.x < 0) {
|
||||||
|
FaceDirection(Direction::WEST);
|
||||||
|
}
|
||||||
|
ResetSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerCharacter::CheckSpeed() {
|
void PlayerCharacter::ResetSpeed() {
|
||||||
//diagonal
|
//diagonal
|
||||||
if (motion.x != 0 && motion.y != 0) {
|
if (motion.x != 0 && motion.y != 0) {
|
||||||
sprite.SetDelay(0.1);
|
sprite.SetDelay(0.1);
|
||||||
limitSpeed = true;
|
diagonal = true;
|
||||||
}
|
}
|
||||||
//cardinal
|
//cardinal
|
||||||
else if (motion != 0) {
|
else if (motion != 0) {
|
||||||
sprite.SetDelay(0.1);
|
sprite.SetDelay(0.1);
|
||||||
limitSpeed = false;
|
diagonal = false;
|
||||||
}
|
}
|
||||||
//not moving
|
//not moving
|
||||||
else {
|
else {
|
||||||
sprite.SetDelay(0);
|
sprite.SetDelay(0);
|
||||||
sprite.SetCurrentFrame(0);
|
sprite.SetXIndex(0);
|
||||||
limitSpeed = false;
|
diagonal = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,20 +24,25 @@
|
|||||||
|
|
||||||
#include "vector2.hpp"
|
#include "vector2.hpp"
|
||||||
#include "sprite_sheet.hpp"
|
#include "sprite_sheet.hpp"
|
||||||
#include "defines.hpp"
|
|
||||||
|
|
||||||
class PlayerCharacter {
|
class PlayerCharacter {
|
||||||
public:
|
public:
|
||||||
|
enum class Direction {
|
||||||
|
NORTH, SOUTH, EAST, WEST
|
||||||
|
};
|
||||||
|
|
||||||
PlayerCharacter() = default;
|
PlayerCharacter() = default;
|
||||||
~PlayerCharacter() = default;
|
~PlayerCharacter() = default;
|
||||||
|
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
|
|
||||||
void MoveDirection(CardinalDirection);
|
void DrawTo(SDL_Surface* const dest, int camX, int camY) { sprite.DrawTo(dest, position.x - camX, position.y - camY); }
|
||||||
void FaceDirection(CardinalDirection);
|
|
||||||
void FaceDirection();
|
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const dest) { sprite.DrawTo(dest, position.x, position.y); }
|
//clunky code results in smooth movement and controls
|
||||||
|
void AdjustDirection(Direction);
|
||||||
|
void FaceDirection(Direction);
|
||||||
|
void ResetDirection();
|
||||||
|
void ResetSpeed();
|
||||||
|
|
||||||
//accessors and mutators
|
//accessors and mutators
|
||||||
Vector2 SetPosition(Vector2 v) { return position = v; }
|
Vector2 SetPosition(Vector2 v) { return position = v; }
|
||||||
@@ -50,14 +55,12 @@ public:
|
|||||||
|
|
||||||
SpriteSheet* GetSprite() { return &sprite; }
|
SpriteSheet* GetSprite() { return &sprite; }
|
||||||
private:
|
private:
|
||||||
void CheckSpeed();
|
|
||||||
|
|
||||||
Vector2 position;
|
Vector2 position;
|
||||||
Vector2 motion;
|
Vector2 motion;
|
||||||
SpriteSheet sprite;
|
SpriteSheet sprite;
|
||||||
|
|
||||||
//for moving diagonal
|
//for moving diagonally
|
||||||
bool limitSpeed = false;
|
bool diagonal = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ enum class SceneList {
|
|||||||
FIRST,
|
FIRST,
|
||||||
|
|
||||||
//custom indexes
|
//custom indexes
|
||||||
INCOMBAT,
|
|
||||||
INWORLD,
|
|
||||||
LOBBY,
|
|
||||||
MAINMENU,
|
|
||||||
OPTIONSCREEN,
|
|
||||||
SPLASHSCREEN,
|
SPLASHSCREEN,
|
||||||
|
MAINMENU,
|
||||||
|
OPTIONSMENU,
|
||||||
|
LOBBYMENU,
|
||||||
|
INWORLD,
|
||||||
|
INCOMBAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ SDL_Surface* BaseScene::screen = nullptr;
|
|||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
BaseScene::BaseScene() {
|
BaseScene::BaseScene() {
|
||||||
nextScene = SceneList::CONTINUE;
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseScene::~BaseScene() {
|
BaseScene::~BaseScene() {
|
||||||
@@ -28,18 +28,18 @@
|
|||||||
|
|
||||||
class BaseScene {
|
class BaseScene {
|
||||||
public:
|
public:
|
||||||
/* Public access members */
|
//Public access members
|
||||||
BaseScene();
|
BaseScene();
|
||||||
virtual ~BaseScene();
|
virtual ~BaseScene();
|
||||||
|
|
||||||
/* Program control */
|
//Program control
|
||||||
static SDL_Surface* SetScreen(int w, int h, int bpp = 0, Uint32 flags = SDL_HWSURFACE|SDL_DOUBLEBUF);
|
static SDL_Surface* SetScreen(int w, int h, int bpp = 0, Uint32 flags = SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||||
static SDL_Surface* GetScreen();
|
static SDL_Surface* GetScreen();
|
||||||
|
|
||||||
SceneList SetNextScene(SceneList sceneIndex);
|
SceneList SetNextScene(SceneList sceneIndex);
|
||||||
SceneList GetNextScene() const;
|
SceneList GetNextScene() const;
|
||||||
|
|
||||||
/* Frame loop */
|
//Frame loop
|
||||||
virtual void RunFrame(double delta);
|
virtual void RunFrame(double delta);
|
||||||
virtual void RenderFrame();
|
virtual void RenderFrame();
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ protected:
|
|||||||
virtual void FrameEnd() {}
|
virtual void FrameEnd() {}
|
||||||
virtual void Render(SDL_Surface* const screen) {}
|
virtual void Render(SDL_Surface* const screen) {}
|
||||||
|
|
||||||
/* Event handlers */
|
//Event handlers
|
||||||
virtual void QuitEvent() { SetNextScene(SceneList::QUIT); }
|
virtual void QuitEvent() { SetNextScene(SceneList::QUIT); }
|
||||||
virtual void MouseMotion(SDL_MouseMotionEvent const&) {}
|
virtual void MouseMotion(SDL_MouseMotionEvent const&) {}
|
||||||
virtual void MouseButtonDown(SDL_MouseButtonEvent const&) {}
|
virtual void MouseButtonDown(SDL_MouseButtonEvent const&) {}
|
||||||
@@ -68,7 +68,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static SDL_Surface* screen;
|
static SDL_Surface* screen;
|
||||||
SceneList nextScene;
|
SceneList nextScene = SceneList::CONTINUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -21,24 +21,16 @@
|
|||||||
*/
|
*/
|
||||||
#include "in_combat.hpp"
|
#include "in_combat.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Public access members
|
//Public access members
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
InCombat::InCombat() {
|
InCombat::InCombat() {
|
||||||
#ifdef DEBUG
|
//
|
||||||
cout << "entering InCombat" << endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InCombat::~InCombat() {
|
InCombat::~InCombat() {
|
||||||
#ifdef DEBUG
|
//
|
||||||
cout << "leaving InCombat" << endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -26,18 +26,18 @@
|
|||||||
|
|
||||||
class InCombat : public BaseScene {
|
class InCombat : public BaseScene {
|
||||||
public:
|
public:
|
||||||
/* Public access members */
|
//Public access members
|
||||||
InCombat();
|
InCombat();
|
||||||
~InCombat();
|
~InCombat();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Frame loop */
|
//Frame loop
|
||||||
void FrameStart();
|
void FrameStart();
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
void FrameEnd();
|
void FrameEnd();
|
||||||
void Render(SDL_Surface* const);
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
/* Event handlers */
|
//Event handlers
|
||||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
@@ -0,0 +1,499 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "in_world.hpp"
|
||||||
|
|
||||||
|
#include "channels.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Public access members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
InWorld::InWorld(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex):
|
||||||
|
config(*argConfig),
|
||||||
|
network(*argNetwork),
|
||||||
|
clientIndex(*argClientIndex)
|
||||||
|
{
|
||||||
|
//setup the utility objects
|
||||||
|
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||||
|
buttonImage.SetClipH(buttonImage.GetClipH()/3);
|
||||||
|
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||||
|
|
||||||
|
//pass the utility objects
|
||||||
|
disconnectButton.SetImage(&buttonImage);
|
||||||
|
disconnectButton.SetFont(&font);
|
||||||
|
shutDownButton.SetImage(&buttonImage);
|
||||||
|
shutDownButton.SetFont(&font);
|
||||||
|
|
||||||
|
//set the button positions
|
||||||
|
disconnectButton.SetX(50);
|
||||||
|
disconnectButton.SetY(50 + buttonImage.GetClipH() * 0);
|
||||||
|
shutDownButton.SetX(50);
|
||||||
|
shutDownButton.SetY(50 + buttonImage.GetClipH() * 1);
|
||||||
|
|
||||||
|
//set the button texts
|
||||||
|
disconnectButton.SetText("Disconnect");
|
||||||
|
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
|
||||||
|
NetworkPacket packet;
|
||||||
|
packet.meta.type = NetworkPacket::Type::PLAYER_NEW;
|
||||||
|
packet.playerInfo.clientIndex = clientIndex;
|
||||||
|
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 = {0,0};
|
||||||
|
packet.playerInfo.motion = {0,0};
|
||||||
|
|
||||||
|
//send it
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
|
//request a sync
|
||||||
|
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
// RequestRegion(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
InWorld::~InWorld() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Frame loop
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void InWorld::FrameStart() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::Update(double delta) {
|
||||||
|
NetworkPacket packet;
|
||||||
|
|
||||||
|
//suck in all waiting packets
|
||||||
|
while(network.Receive()) {
|
||||||
|
deserialize(&packet, network.GetInData());
|
||||||
|
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||||
|
HandlePacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
//update the characters
|
||||||
|
for (auto& it : playerCharacters) {
|
||||||
|
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::RenderFrame() {
|
||||||
|
// SDL_FillRect(GetScreen(), 0, 0);
|
||||||
|
Render(GetScreen());
|
||||||
|
SDL_Flip(GetScreen());
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::Render(SDL_Surface* const screen) {
|
||||||
|
//draw the map
|
||||||
|
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);
|
||||||
|
shutDownButton.DrawTo(screen);
|
||||||
|
|
||||||
|
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||||
|
|
||||||
|
fps.Calculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Event handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void InWorld::QuitEvent() {
|
||||||
|
//exit the game AND the server
|
||||||
|
RequestDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
|
disconnectButton.MouseMotion(motion);
|
||||||
|
shutDownButton.MouseMotion(motion);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
|
disconnectButton.MouseButtonDown(button);
|
||||||
|
shutDownButton.MouseButtonDown(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
|
if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
|
RequestDisconnect();
|
||||||
|
}
|
||||||
|
if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
|
RequestShutDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
|
||||||
|
switch(key.keysym.sym) {
|
||||||
|
case SDLK_ESCAPE: {
|
||||||
|
QuitEvent();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//player movement
|
||||||
|
case SDLK_LEFT:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::WEST);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::EAST);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_UP:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::NORTH);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_DOWN:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::SOUTH);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
||||||
|
switch(key.keysym.sym) {
|
||||||
|
//player movement
|
||||||
|
case SDLK_LEFT:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::EAST);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::WEST);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_UP:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::SOUTH);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_DOWN:
|
||||||
|
if (localCharacter) {
|
||||||
|
localCharacter->AdjustDirection(PlayerCharacter::Direction::NORTH);
|
||||||
|
SendState();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Network handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void InWorld::HandlePacket(NetworkPacket packet) {
|
||||||
|
switch(packet.meta.type) {
|
||||||
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
|
HandleDisconnect(packet);
|
||||||
|
break;
|
||||||
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
|
HandlePlayerNew(packet);
|
||||||
|
break;
|
||||||
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
|
HandlePlayerDelete(packet);
|
||||||
|
break;
|
||||||
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
|
HandlePlayerUpdate(packet);
|
||||||
|
break;
|
||||||
|
case NetworkPacket::Type::REGION_CONTENT:
|
||||||
|
HandleRegionContent(packet);
|
||||||
|
break;
|
||||||
|
//handle errors
|
||||||
|
default:
|
||||||
|
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::HandleDisconnect(NetworkPacket packet) {
|
||||||
|
network.Unbind(Channels::SERVER);
|
||||||
|
clientIndex = -1;
|
||||||
|
SetNextScene(SceneList::MAINMENU);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::HandlePlayerNew(NetworkPacket packet) {
|
||||||
|
if (playerCharacters.find(packet.playerInfo.playerIndex) != playerCharacters.end()) {
|
||||||
|
throw(std::runtime_error("Cannot create duplicate players"));
|
||||||
|
}
|
||||||
|
|
||||||
|
playerCharacters[packet.playerInfo.playerIndex].GetSprite()->LoadSurface(config["dir.sprites"] + packet.playerInfo.avatar, 4, 4);
|
||||||
|
playerCharacters[packet.playerInfo.playerIndex].SetPosition(packet.playerInfo.position);
|
||||||
|
playerCharacters[packet.playerInfo.playerIndex].SetMotion(packet.playerInfo.motion);
|
||||||
|
playerCharacters[packet.playerInfo.playerIndex].ResetDirection();
|
||||||
|
|
||||||
|
//catch this client's player object
|
||||||
|
if (packet.playerInfo.clientIndex == clientIndex && !localCharacter) {
|
||||||
|
playerIndex = packet.playerInfo.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::HandlePlayerDelete(NetworkPacket packet) {
|
||||||
|
if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) {
|
||||||
|
throw(std::runtime_error("Cannot delete non-existant players"));
|
||||||
|
}
|
||||||
|
|
||||||
|
playerCharacters.erase(packet.playerInfo.playerIndex);
|
||||||
|
|
||||||
|
//catch this client's player object
|
||||||
|
if (packet.playerInfo.clientIndex == clientIndex) {
|
||||||
|
playerIndex = -1;
|
||||||
|
localCharacter = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::HandlePlayerUpdate(NetworkPacket packet) {
|
||||||
|
if (playerCharacters.find(packet.playerInfo.playerIndex) == playerCharacters.end()) {
|
||||||
|
HandlePlayerNew(packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//update only if the message didn't originate from here
|
||||||
|
if (packet.playerInfo.clientIndex != clientIndex) {
|
||||||
|
playerCharacters[packet.playerInfo.playerIndex].SetPosition(packet.playerInfo.position);
|
||||||
|
playerCharacters[packet.playerInfo.playerIndex].SetMotion(packet.playerInfo.motion);
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//pack the packet
|
||||||
|
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||||
|
packet.playerInfo.clientIndex = clientIndex;
|
||||||
|
packet.playerInfo.playerIndex = playerIndex;
|
||||||
|
packet.playerInfo.position = localCharacter->GetPosition();
|
||||||
|
packet.playerInfo.motion = localCharacter->GetMotion();
|
||||||
|
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::RequestDisconnect() {
|
||||||
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//send a disconnect request
|
||||||
|
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
||||||
|
packet.clientInfo.index = clientIndex;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(Channels::SERVER, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InWorld::RequestShutDown() {
|
||||||
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//send a shutdown request
|
||||||
|
packet.meta.type = NetworkPacket::Type::SHUTDOWN;
|
||||||
|
packet.clientInfo.index = clientIndex;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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 INWORLD_HPP_
|
||||||
|
#define INWORLD_HPP_
|
||||||
|
|
||||||
|
//maps
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
#include "map_file_format.hpp"
|
||||||
|
#include "region_pager.hpp"
|
||||||
|
|
||||||
|
//networking
|
||||||
|
#include "udp_network_utility.hpp"
|
||||||
|
#include "network_packet.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
|
//graphics
|
||||||
|
#include "image.hpp"
|
||||||
|
#include "raster_font.hpp"
|
||||||
|
#include "button.hpp"
|
||||||
|
#include "tile_sheet.hpp"
|
||||||
|
|
||||||
|
//common
|
||||||
|
#include "config_utility.hpp"
|
||||||
|
#include "frame_rate.hpp"
|
||||||
|
|
||||||
|
//client
|
||||||
|
#include "base_scene.hpp"
|
||||||
|
#include "player_character.hpp"
|
||||||
|
|
||||||
|
//STL
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
class InWorld : public BaseScene {
|
||||||
|
public:
|
||||||
|
//Public access members
|
||||||
|
InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const);
|
||||||
|
~InWorld();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//Frame loop
|
||||||
|
void FrameStart();
|
||||||
|
void Update(double delta);
|
||||||
|
void FrameEnd();
|
||||||
|
void RenderFrame();
|
||||||
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
|
//Event handlers
|
||||||
|
void QuitEvent();
|
||||||
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
|
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
|
//Network handlers
|
||||||
|
void HandlePacket(NetworkPacket);
|
||||||
|
void HandleDisconnect(NetworkPacket);
|
||||||
|
void HandlePlayerNew(NetworkPacket);
|
||||||
|
void HandlePlayerDelete(NetworkPacket);
|
||||||
|
void HandlePlayerUpdate(NetworkPacket);
|
||||||
|
void HandleRegionContent(NetworkPacket);
|
||||||
|
|
||||||
|
//Server control
|
||||||
|
void SendState();
|
||||||
|
void RequestDisconnect();
|
||||||
|
void RequestShutDown();
|
||||||
|
void RequestRegion(int x, int y);
|
||||||
|
|
||||||
|
//utilities
|
||||||
|
int CheckBufferDistance(Region* const);
|
||||||
|
void UpdateMap();
|
||||||
|
|
||||||
|
//globals
|
||||||
|
ConfigUtility& config;
|
||||||
|
FrameRate fps;
|
||||||
|
UDPNetworkUtility& network;
|
||||||
|
int& clientIndex;
|
||||||
|
|
||||||
|
//graphics
|
||||||
|
Image buttonImage;
|
||||||
|
RasterFont font;
|
||||||
|
TileSheet tileSheet;
|
||||||
|
|
||||||
|
//map
|
||||||
|
RegionPager<BlankGenerator, DummyFormat> mapPager;
|
||||||
|
|
||||||
|
//UI
|
||||||
|
Button disconnectButton;
|
||||||
|
Button shutDownButton;
|
||||||
|
struct {
|
||||||
|
int x = 0, y = 0;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
int marginX = 0, marginY = 0;
|
||||||
|
} camera;
|
||||||
|
|
||||||
|
//game
|
||||||
|
std::map<int, PlayerCharacter> playerCharacters;
|
||||||
|
PlayerCharacter* localCharacter = nullptr;
|
||||||
|
int playerIndex = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "lobby_menu.hpp"
|
||||||
|
|
||||||
|
#include "channels.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Public access members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
LobbyMenu::LobbyMenu(ConfigUtility* const argConfig, UDPNetworkUtility* const argNetwork, int* const argClientIndex):
|
||||||
|
config(*argConfig),
|
||||||
|
network(*argNetwork),
|
||||||
|
clientIndex(*argClientIndex)
|
||||||
|
{
|
||||||
|
//setup the utility objects
|
||||||
|
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||||
|
image.SetClipH(image.GetClipH()/3);
|
||||||
|
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||||
|
|
||||||
|
//pass the utility objects
|
||||||
|
search.SetImage(&image);
|
||||||
|
search.SetFont(&font);
|
||||||
|
join.SetImage(&image);
|
||||||
|
join.SetFont(&font);
|
||||||
|
back.SetImage(&image);
|
||||||
|
back.SetFont(&font);
|
||||||
|
|
||||||
|
//set the button positions
|
||||||
|
search.SetX(50);
|
||||||
|
search.SetY(50 + image.GetClipH() * 0);
|
||||||
|
join.SetX(50);
|
||||||
|
join.SetY(50 + image.GetClipH() * 1);
|
||||||
|
back.SetX(50);
|
||||||
|
back.SetY(50 + image.GetClipH() * 2);
|
||||||
|
|
||||||
|
//set the button texts
|
||||||
|
search.SetText("Search");
|
||||||
|
join.SetText("Join");
|
||||||
|
back.SetText("Back");
|
||||||
|
|
||||||
|
//set the server list's position
|
||||||
|
listBox = {300, 50, 200, font.GetCharH()};
|
||||||
|
}
|
||||||
|
|
||||||
|
LobbyMenu::~LobbyMenu() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Frame loop
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void LobbyMenu::FrameStart() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::Update(double delta) {
|
||||||
|
//suck in all waiting packets
|
||||||
|
NetworkPacket packet;
|
||||||
|
while(network.Receive()) {
|
||||||
|
deserialize(&packet, network.GetInData());
|
||||||
|
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||||
|
HandlePacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::FrameEnd() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::Render(SDL_Surface* const screen) {
|
||||||
|
search.DrawTo(screen);
|
||||||
|
join.DrawTo(screen);
|
||||||
|
back.DrawTo(screen);
|
||||||
|
for (int i = 0; i < serverInfo.size(); i++) {
|
||||||
|
//draw the selected server's highlight
|
||||||
|
if (selection == &serverInfo[i]) {
|
||||||
|
SDL_Rect r = listBox;
|
||||||
|
r.y += i * listBox.h;
|
||||||
|
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39));
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw the server name
|
||||||
|
font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Event handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void LobbyMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
|
search.MouseMotion(motion);
|
||||||
|
join.MouseMotion(motion);
|
||||||
|
back.MouseMotion(motion);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
|
search.MouseButtonDown(button);
|
||||||
|
join.MouseButtonDown(button);
|
||||||
|
back.MouseButtonDown(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
|
if (search.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
|
//the vars
|
||||||
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//broadcast to the network, or a specific server
|
||||||
|
packet.meta.type = NetworkPacket::Type::BROADCAST_REQUEST;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(config["server.host"].c_str(), config.Int("server.port"), buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
|
//reset the server list
|
||||||
|
serverInfo.clear();
|
||||||
|
selection = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) {
|
||||||
|
//the vars
|
||||||
|
NetworkPacket packet;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//join the selected server
|
||||||
|
packet.meta.type = NetworkPacket::Type::JOIN_REQUEST;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&selection->address, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
selection = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (back.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
|
SetNextScene(SceneList::MAINMENU);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (
|
||||||
|
//has the user selected a server on the list?
|
||||||
|
button.x > listBox.x &&
|
||||||
|
button.x < listBox.x + listBox.w &&
|
||||||
|
button.y > listBox.y &&
|
||||||
|
button.y < listBox.y + listBox.h * serverInfo.size()
|
||||||
|
) {
|
||||||
|
selection = &serverInfo[(button.y - listBox.y)/listBox.h];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
selection = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
||||||
|
switch(key.keysym.sym) {
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
SetNextScene(SceneList::MAINMENU);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void LobbyMenu::HandlePacket(NetworkPacket packet) {
|
||||||
|
switch(packet.meta.type) {
|
||||||
|
case NetworkPacket::Type::BROADCAST_RESPONSE: {
|
||||||
|
ServerInformation server;
|
||||||
|
server.name = packet.serverInfo.name;
|
||||||
|
server.address = packet.meta.srcAddress;
|
||||||
|
serverInfo.push_back(server);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||||
|
clientIndex = packet.clientInfo.index;
|
||||||
|
network.Bind(&packet.meta.srcAddress, Channels::SERVER);
|
||||||
|
SetNextScene(SceneList::INWORLD);
|
||||||
|
break;
|
||||||
|
|
||||||
|
//handle errors
|
||||||
|
default:
|
||||||
|
throw(std::runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,32 +19,27 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef INWORLD_HPP_
|
#ifndef LOBBYMENU_HPP_
|
||||||
#define INWORLD_HPP_
|
#define LOBBYMENU_HPP_
|
||||||
|
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
|
|
||||||
#include "defines.hpp"
|
#include "image.hpp"
|
||||||
#include "singleton.hpp"
|
#include "raster_font.hpp"
|
||||||
#include "packet.hpp"
|
#include "button.hpp"
|
||||||
#include "network_queue.hpp"
|
|
||||||
#include "information_manager.hpp"
|
|
||||||
#include "player_character.hpp"
|
|
||||||
|
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "surface_manager.hpp"
|
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
#include "button.hpp"
|
#include "network_packet.hpp"
|
||||||
#include "raster_font.hpp"
|
#include "serial.hpp"
|
||||||
#include "frame_rate.hpp"
|
|
||||||
|
|
||||||
#include <map>
|
#include <vector>
|
||||||
|
|
||||||
class InWorld : public BaseScene {
|
class LobbyMenu : public BaseScene {
|
||||||
public:
|
public:
|
||||||
//Public access members
|
//Public access members
|
||||||
InWorld();
|
LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const);
|
||||||
~InWorld();
|
~LobbyMenu();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//Frame loop
|
//Frame loop
|
||||||
@@ -54,35 +49,38 @@ protected:
|
|||||||
void Render(SDL_Surface* const);
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
//Event handlers
|
//Event handlers
|
||||||
void QuitEvent();
|
|
||||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
void KeyDown(SDL_KeyboardEvent const&);
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
void KeyUp(SDL_KeyboardEvent const&);
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
//Utilities
|
void HandlePacket(NetworkPacket);
|
||||||
int HandlePacket(Packet);
|
|
||||||
void Disconnect();
|
|
||||||
void ExitGame();
|
|
||||||
|
|
||||||
void HandleDisconnection(Packet&);
|
//global
|
||||||
|
ConfigUtility& config;
|
||||||
void AddPlayer(Packet&);
|
UDPNetworkUtility& network;
|
||||||
void RemovePlayer(Packet&);
|
int& clientIndex;
|
||||||
void UpdatePlayer(Packet&);
|
|
||||||
|
|
||||||
void SendState();
|
|
||||||
|
|
||||||
//services
|
|
||||||
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
|
|
||||||
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
|
|
||||||
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
|
|
||||||
InformationManager* infoMgr = Singleton<InformationManager>::Get();
|
|
||||||
|
|
||||||
//members
|
//members
|
||||||
|
Image image;
|
||||||
RasterFont font;
|
RasterFont font;
|
||||||
std::map<int, PlayerCharacter> playerCharacters;
|
Button search;
|
||||||
|
Button join;
|
||||||
|
Button back;
|
||||||
|
|
||||||
|
//server list
|
||||||
|
struct ServerInformation {
|
||||||
|
std::string name;
|
||||||
|
IPaddress address;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ServerInformation> serverInfo;
|
||||||
|
|
||||||
|
//a terrible hack, forgive me
|
||||||
|
//I'd love a proper gui system for this
|
||||||
|
SDL_Rect listBox;
|
||||||
|
ServerInformation* selection = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -21,27 +21,42 @@
|
|||||||
*/
|
*/
|
||||||
#include "main_menu.hpp"
|
#include "main_menu.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Public access members
|
//Public access members
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
MainMenu::MainMenu() {
|
MainMenu::MainMenu(ConfigUtility* const argConfig):
|
||||||
#ifdef DEBUG
|
config(*argConfig)
|
||||||
cout << "entering MainMenu" << endl;
|
{
|
||||||
#endif
|
//setup the utility objects
|
||||||
startButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Start");
|
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||||
optionsButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Options");
|
image.SetClipH(image.GetClipH()/3);
|
||||||
quitButton.Setup(50, 50 + surfaceMgr->Get("button")->h/3 * 2, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Quit");
|
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||||
|
|
||||||
|
//pass the utility objects
|
||||||
|
startButton.SetImage(&image);
|
||||||
|
startButton.SetFont(&font);
|
||||||
|
optionsButton.SetImage(&image);
|
||||||
|
optionsButton.SetFont(&font);
|
||||||
|
quitButton.SetImage(&image);
|
||||||
|
quitButton.SetFont(&font);
|
||||||
|
|
||||||
|
//set the button positions
|
||||||
|
startButton.SetX(50);
|
||||||
|
startButton.SetY(50 + image.GetClipH() * 0);
|
||||||
|
optionsButton.SetX(50);
|
||||||
|
optionsButton.SetY(50 + image.GetClipH() * 1);
|
||||||
|
quitButton.SetX(50);
|
||||||
|
quitButton.SetY(50 + image.GetClipH() * 2);
|
||||||
|
|
||||||
|
//set the button texts
|
||||||
|
startButton.SetText("Start");
|
||||||
|
optionsButton.SetText("Options");
|
||||||
|
quitButton.SetText("Quit");
|
||||||
}
|
}
|
||||||
|
|
||||||
MainMenu::~MainMenu() {
|
MainMenu::~MainMenu() {
|
||||||
#ifdef DEBUG
|
//
|
||||||
cout << "leaving MainMenu" << endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
@@ -84,10 +99,10 @@ void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
|||||||
|
|
||||||
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
if (startButton.MouseButtonUp(button) == Button::State::HOVER) {
|
if (startButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
SetNextScene(SceneList::LOBBY);
|
SetNextScene(SceneList::LOBBYMENU);
|
||||||
}
|
}
|
||||||
if (optionsButton.MouseButtonUp(button) == Button::State::HOVER) {
|
if (optionsButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
SetNextScene(SceneList::OPTIONSCREEN);
|
SetNextScene(SceneList::OPTIONSMENU);
|
||||||
}
|
}
|
||||||
if (quitButton.MouseButtonUp(button) == Button::State::HOVER) {
|
if (quitButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
QuitEvent();
|
QuitEvent();
|
||||||
@@ -101,3 +116,7 @@ void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||||
|
//
|
||||||
|
}
|
||||||
@@ -23,32 +23,38 @@
|
|||||||
#define MAINMENU_HPP_
|
#define MAINMENU_HPP_
|
||||||
|
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
#include "singleton.hpp"
|
|
||||||
|
|
||||||
#include "surface_manager.hpp"
|
#include "config_utility.hpp"
|
||||||
|
#include "image.hpp"
|
||||||
|
#include "raster_font.hpp"
|
||||||
#include "button.hpp"
|
#include "button.hpp"
|
||||||
|
|
||||||
class MainMenu : public BaseScene {
|
class MainMenu : public BaseScene {
|
||||||
public:
|
public:
|
||||||
/* Public access members */
|
//Public access members
|
||||||
MainMenu();
|
MainMenu(ConfigUtility* const);
|
||||||
~MainMenu();
|
~MainMenu();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Frame loop */
|
//Frame loop
|
||||||
void FrameStart();
|
void FrameStart();
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
void FrameEnd();
|
void FrameEnd();
|
||||||
void Render(SDL_Surface* const);
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
/* Event handlers */
|
//Event handlers
|
||||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
void KeyDown(SDL_KeyboardEvent const&);
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
|
//globals
|
||||||
|
ConfigUtility& config;
|
||||||
|
|
||||||
|
//members
|
||||||
|
Image image;
|
||||||
|
RasterFont font;
|
||||||
Button startButton;
|
Button startButton;
|
||||||
Button optionsButton;
|
Button optionsButton;
|
||||||
Button quitButton;
|
Button quitButton;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#config
|
||||||
|
INCLUDES+=. .. ../../common ../../common/graphics ../../common/map ../../common/network ../../common/ui
|
||||||
|
LIBS+=
|
||||||
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
#source
|
||||||
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
|
#objects
|
||||||
|
OBJDIR=obj
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
|
#output
|
||||||
|
OUTDIR=..
|
||||||
|
OUT=$(addprefix $(OUTDIR)/,libclient.a)
|
||||||
|
|
||||||
|
#targets
|
||||||
|
all: $(OBJ) $(OUT)
|
||||||
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
|
||||||
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUT): | $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUTDIR):
|
||||||
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "options_menu.hpp"
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Public access members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
OptionsMenu::OptionsMenu(ConfigUtility* const argConfig):
|
||||||
|
config(*argConfig)
|
||||||
|
{
|
||||||
|
//setup the utility objects
|
||||||
|
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||||
|
image.SetClipH(image.GetClipH()/3);
|
||||||
|
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||||
|
|
||||||
|
//pass the utility objects
|
||||||
|
backButton.SetImage(&image);
|
||||||
|
backButton.SetFont(&font);
|
||||||
|
|
||||||
|
//set the button positions
|
||||||
|
backButton.SetX(50);
|
||||||
|
backButton.SetY(50 + image.GetClipH() * 0);
|
||||||
|
|
||||||
|
//set the button texts
|
||||||
|
backButton.SetText("Back");
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionsMenu::~OptionsMenu() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Frame loop
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void OptionsMenu::FrameStart() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsMenu::Update(double delta) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsMenu::FrameEnd() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsMenu::Render(SDL_Surface* const screen) {
|
||||||
|
backButton.DrawTo(screen);
|
||||||
|
|
||||||
|
font.DrawStringTo("Oh, were you looking for the options screen?", screen, 50, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Event handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void OptionsMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
|
backButton.MouseMotion(motion);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
|
backButton.MouseButtonDown(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
|
if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||||
|
SetNextScene(SceneList::MAINMENU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
||||||
|
switch(key.keysym.sym) {
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
SetNextScene(SceneList::MAINMENU);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OptionsMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||||
|
//
|
||||||
|
}
|
||||||
@@ -19,38 +19,21 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef LOBBY_HPP_
|
#ifndef OPTIONSMENU_HPP_
|
||||||
#define LOBBY_HPP_
|
#define OPTIONSMENU_HPP_
|
||||||
|
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
|
|
||||||
#include "defines.hpp"
|
|
||||||
#include "singleton.hpp"
|
|
||||||
|
|
||||||
#include "packet.hpp"
|
|
||||||
#include "network_queue.hpp"
|
|
||||||
#include "information_manager.hpp"
|
|
||||||
|
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "surface_manager.hpp"
|
#include "image.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
|
||||||
#include "button.hpp"
|
|
||||||
#include "raster_font.hpp"
|
#include "raster_font.hpp"
|
||||||
|
#include "button.hpp"
|
||||||
|
|
||||||
#include <vector>
|
class OptionsMenu : public BaseScene {
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct ServerEntry {
|
|
||||||
std::string name;
|
|
||||||
IPaddress address;
|
|
||||||
//TODO: player count
|
|
||||||
};
|
|
||||||
|
|
||||||
class Lobby : public BaseScene {
|
|
||||||
public:
|
public:
|
||||||
//Public access members
|
//Public access members
|
||||||
Lobby();
|
OptionsMenu(ConfigUtility* const);
|
||||||
~Lobby();
|
~OptionsMenu();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//Frame loop
|
//Frame loop
|
||||||
@@ -66,28 +49,13 @@ protected:
|
|||||||
void KeyDown(SDL_KeyboardEvent const&);
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
void KeyUp(SDL_KeyboardEvent const&);
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
//utilities
|
//globals
|
||||||
int HandlePacket(Packet);
|
ConfigUtility& config;
|
||||||
void BroadcastNetwork();
|
|
||||||
void PushServer(Packet&);
|
|
||||||
void ConnectToServer(ServerEntry*);
|
|
||||||
void BeginGame(Packet&);
|
|
||||||
|
|
||||||
//services
|
|
||||||
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
|
|
||||||
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
|
|
||||||
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
|
|
||||||
InformationManager* infoMgr = Singleton<InformationManager>::Get();
|
|
||||||
|
|
||||||
//members
|
//members
|
||||||
Button refreshButton;
|
Image image;
|
||||||
Button joinButton;
|
|
||||||
Button backButton;
|
|
||||||
|
|
||||||
RasterFont font;
|
RasterFont font;
|
||||||
SDL_Rect listBox;
|
Button backButton;
|
||||||
std::vector<ServerEntry> serverList;
|
|
||||||
ServerEntry* selectedServer = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -19,23 +19,33 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#include "sprite_sheet.hpp"
|
#include "splash_screen.hpp"
|
||||||
|
|
||||||
void SpriteSheet::Update(double delta) {
|
//-------------------------
|
||||||
if (delay && (ticks += delta) >= delay) {
|
//Public access members
|
||||||
if (++currentFrame >= maxFrames) {
|
//-------------------------
|
||||||
currentFrame = 0;
|
|
||||||
}
|
SplashScreen::SplashScreen(ConfigUtility* const argConfig):
|
||||||
ticks = 0;
|
config(*argConfig)
|
||||||
}
|
{
|
||||||
image.SetClipX(currentFrame * image.GetClipW());
|
logo.LoadSurface(config["dir.logos"] + "krstudios.bmp");
|
||||||
image.SetClipY(currentStrip * image.GetClipH());
|
startTick = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface* SpriteSheet::SetSurface(SDL_Surface* const s, Uint16 w, Uint16 h) {
|
SplashScreen::~SplashScreen() {
|
||||||
image.SetSurface(s);
|
//
|
||||||
image.SetClip({0, 0, w, h});
|
}
|
||||||
currentFrame = 0; maxFrames = image.GetSurface()->w / image.GetClipW();
|
|
||||||
currentStrip = 0; maxStrips = image.GetSurface()->h / image.GetClipH();
|
//-------------------------
|
||||||
delay = ticks = 0;
|
//Frame loop
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void SplashScreen::Update(double delta) {
|
||||||
|
if (std::chrono::steady_clock::now() - startTick > std::chrono::duration<int>(1)) {
|
||||||
|
SetNextScene(SceneList::MAINMENU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplashScreen::Render(SDL_Surface* const screen) {
|
||||||
|
logo.DrawTo(screen, (screen->w - logo.GetClipW()) / 2, (screen->h - logo.GetClipH()) / 2);
|
||||||
}
|
}
|
||||||
@@ -23,31 +23,29 @@
|
|||||||
#define SPLASHSCREEN_HPP_
|
#define SPLASHSCREEN_HPP_
|
||||||
|
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
#include "singleton.hpp"
|
|
||||||
|
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "surface_manager.hpp"
|
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
class SplashScreen : public BaseScene {
|
class SplashScreen : public BaseScene {
|
||||||
public:
|
public:
|
||||||
/* Public access members */
|
//Public access members
|
||||||
SplashScreen();
|
SplashScreen(ConfigUtility* const);
|
||||||
~SplashScreen();
|
~SplashScreen();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Frame loop */
|
//Frame loop
|
||||||
void RunFrame(double delta);
|
void Update(double delta);
|
||||||
void RenderFrame();
|
void Render(SDL_Surface* const);
|
||||||
void LoadResources();
|
|
||||||
|
|
||||||
bool loaded = false;
|
//globals
|
||||||
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
|
ConfigUtility& config;
|
||||||
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
|
|
||||||
|
//members
|
||||||
|
std::chrono::steady_clock::time_point startTick;
|
||||||
Image logo;
|
Image logo;
|
||||||
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#include "splash_screen.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Public access members
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
SplashScreen::SplashScreen() {
|
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "entering SplashScreen" << endl;
|
|
||||||
#endif
|
|
||||||
logo.SetSurface(surfaceMgr->Load("splash-logo", configUtil->String("logos") + "/krstudios.bmp"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SplashScreen::~SplashScreen() {
|
|
||||||
surfaceMgr->Free("splash-logo");
|
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "leaving SplashScreen" << endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Frame loop
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
void SplashScreen::RunFrame(double delta) {
|
|
||||||
HandleEvents();
|
|
||||||
if (!loaded) {
|
|
||||||
//never repeat this
|
|
||||||
loaded = true;
|
|
||||||
|
|
||||||
//quick draw
|
|
||||||
RenderFrame();
|
|
||||||
|
|
||||||
LoadResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::chrono::steady_clock::now() - start > std::chrono::duration<int>(1)) {
|
|
||||||
SetNextScene(SceneList::MAINMENU);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplashScreen::RenderFrame() {
|
|
||||||
SDL_FillRect(GetScreen(), 0, 0);
|
|
||||||
int x = (GetScreen()->w - logo.GetClipW()) / 2;
|
|
||||||
int y = (GetScreen()->h - logo.GetClipH()) / 2;
|
|
||||||
logo.DrawTo(GetScreen(), x, y);
|
|
||||||
SDL_Flip(GetScreen());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplashScreen::LoadResources() {
|
|
||||||
//standard
|
|
||||||
surfaceMgr->Load("font", configUtil->String("fonts") + "/pk_white_8.bmp");
|
|
||||||
surfaceMgr->Load("button", configUtil->String("interface") + "/button_menu.bmp");
|
|
||||||
|
|
||||||
//debugging
|
|
||||||
surfaceMgr->Load("elliot", configUtil->String("sprites") + "/elliot2.bmp");
|
|
||||||
surfaceMgr->Load("coa", configUtil->String("sprites") + "/coa2.bmp");
|
|
||||||
surfaceMgr->Load("flower", configUtil->String("sprites") + "/aniflower.bmp");
|
|
||||||
surfaceMgr->Load("terrain", configUtil->String("tilesets") + "/terrain.bmp");
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
@@ -21,8 +21,9 @@
|
|||||||
*/
|
*/
|
||||||
#include "config_utility.hpp"
|
#include "config_utility.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -74,3 +75,31 @@ void ConfigUtility::Load(string fname) {
|
|||||||
|
|
||||||
is.close();
|
is.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string& ConfigUtility::String(std::string s) {
|
||||||
|
return table[s];
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConfigUtility::Integer(std::string s) {
|
||||||
|
std::map<std::string, std::string>::iterator it = table.find(s);
|
||||||
|
if (it == table.end()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return atoi(it->second.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
double ConfigUtility::Double(std::string s) {
|
||||||
|
std::map<std::string, std::string>::iterator it = table.find(s);
|
||||||
|
if (it == table.end()) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return atof(it->second.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigUtility::Boolean(std::string s) {
|
||||||
|
std::map<std::string, std::string>::iterator it = table.find(s);
|
||||||
|
if (it == table.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return it->second == "true";
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,40 +24,32 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
class ConfigUtility {
|
class ConfigUtility {
|
||||||
public:
|
public:
|
||||||
ConfigUtility() {}
|
ConfigUtility() = default;
|
||||||
ConfigUtility(std::string s) { Load(s); }
|
ConfigUtility(std::string s) { Load(s); }
|
||||||
|
|
||||||
void Load(std::string fname);
|
void Load(std::string fname);
|
||||||
|
|
||||||
std::string String(std::string s) {
|
//convert to a type
|
||||||
return table[s];
|
std::string& String(std::string);
|
||||||
}
|
int Integer(std::string);
|
||||||
const char* CString(std::string s) {
|
double Double(std::string);
|
||||||
return table[s].c_str();
|
bool Boolean(std::string);
|
||||||
}
|
|
||||||
int Integer(std::string s) {
|
|
||||||
return atoi(table[s].c_str());
|
|
||||||
}
|
|
||||||
double Double(std::string s) {
|
|
||||||
return atof(table[s].c_str());
|
|
||||||
}
|
|
||||||
bool Boolean(std::string s) {
|
|
||||||
return table[s] == "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//shorthand
|
||||||
std::string& operator[](std::string s) {
|
std::string& operator[](std::string s) {
|
||||||
return table[s];
|
return String(s);
|
||||||
}
|
}
|
||||||
int Int(std::string s) {
|
int Int(std::string s) {
|
||||||
return Integer(s);
|
return Integer(s);
|
||||||
}
|
}
|
||||||
int Bool(std::string s) {
|
bool Bool(std::string s) {
|
||||||
return Boolean(s);
|
return Boolean(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//OO breaker
|
||||||
std::map<std::string, std::string>* GetMap() {
|
std::map<std::string, std::string>* GetMap() {
|
||||||
return &table;
|
return &table;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -22,7 +22,27 @@
|
|||||||
#ifndef FRAMERATE_HPP_
|
#ifndef FRAMERATE_HPP_
|
||||||
#define FRAMERATE_HPP_
|
#define FRAMERATE_HPP_
|
||||||
|
|
||||||
int clockFrameRate();
|
#include <chrono>
|
||||||
int getFrameRate();
|
|
||||||
|
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
|
#endif
|
||||||
|
|||||||
@@ -22,16 +22,88 @@
|
|||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
Image& Image::operator=(Image const& rhs) {
|
||||||
|
//don't screw yourself
|
||||||
|
if (this == &rhs) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeSurface();
|
||||||
|
|
||||||
|
//Copy the other Image's stuff
|
||||||
|
surface = rhs.surface;
|
||||||
|
clip = rhs.clip;
|
||||||
|
local = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image& Image::operator=(Image&& rhs) {
|
||||||
|
//don't screw yourself
|
||||||
|
if (this == &rhs) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeSurface();
|
||||||
|
|
||||||
|
//Steal the other Image's stuff
|
||||||
|
surface = rhs.surface;
|
||||||
|
clip = rhs.clip;
|
||||||
|
local = rhs.local;
|
||||||
|
|
||||||
|
rhs.surface = nullptr;
|
||||||
|
rhs.clip = {0, 0, 0, 0};
|
||||||
|
rhs.local = false;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Surface* Image::LoadSurface(std::string fname) {
|
SDL_Surface* Image::LoadSurface(std::string fname) {
|
||||||
|
FreeSurface();
|
||||||
SDL_Surface* p = SDL_LoadBMP(fname.c_str());
|
SDL_Surface* p = SDL_LoadBMP(fname.c_str());
|
||||||
if (!p) {
|
if (!p) {
|
||||||
throw(std::runtime_error(std::string() + "Failed to load file: " + fname));
|
std::ostringstream os;
|
||||||
|
os << "Failed to load file: " << fname;
|
||||||
|
throw(std::runtime_error(os.str()));
|
||||||
}
|
}
|
||||||
surface = p;
|
surface = p;
|
||||||
SetTransparentColor(255, 0, 255); //default
|
|
||||||
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
|
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
|
||||||
local = true;
|
local = true;
|
||||||
|
SetTransparentColor(255, 0, 255); //default
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* Image::CreateSurface(Uint16 w, Uint16 h) {
|
||||||
|
FreeSurface();
|
||||||
|
Uint32 rmask, gmask, bmask, amask;
|
||||||
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||||
|
rmask = 0xff000000;
|
||||||
|
gmask = 0x00ff0000;
|
||||||
|
bmask = 0x0000ff00;
|
||||||
|
amask = 0x000000ff;
|
||||||
|
#else
|
||||||
|
rmask = 0x000000ff;
|
||||||
|
gmask = 0x0000ff00;
|
||||||
|
bmask = 0x00ff0000;
|
||||||
|
amask = 0xff000000;
|
||||||
|
#endif
|
||||||
|
SDL_Surface* p = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, rmask, gmask, bmask, amask);
|
||||||
|
if (!p) {
|
||||||
|
throw(std::runtime_error("Failed to create Image surface"));
|
||||||
|
}
|
||||||
|
surface = p;
|
||||||
|
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
|
||||||
|
local = true;
|
||||||
|
SetTransparentColor(255, 0, 255); //default
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* Image::SetSurface(SDL_Surface* p) {
|
||||||
|
FreeSurface();
|
||||||
|
if (!p) {
|
||||||
|
throw(std::invalid_argument("No surface pointer provided"));
|
||||||
|
}
|
||||||
|
surface = p;
|
||||||
|
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
|
||||||
|
local = false;
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,16 +116,6 @@ void Image::FreeSurface() {
|
|||||||
clip = {0, 0, 0, 0};
|
clip = {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface* Image::SetSurface(SDL_Surface* p) {
|
|
||||||
if (!p) {
|
|
||||||
throw(std::invalid_argument("No surface pointer provided"));
|
|
||||||
}
|
|
||||||
surface = p;
|
|
||||||
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
|
|
||||||
local = false;
|
|
||||||
return surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::DrawTo(SDL_Surface* dest, Sint16 x, Sint16 y) {
|
void Image::DrawTo(SDL_Surface* dest, Sint16 x, Sint16 y) {
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
throw(std::logic_error("No image surface to draw"));
|
throw(std::logic_error("No image surface to draw"));
|
||||||
@@ -66,6 +128,9 @@ void Image::SetTransparentColor(Uint8 r, Uint8 g, Uint8 b) {
|
|||||||
if (!surface) {
|
if (!surface) {
|
||||||
throw(std::logic_error("Failed to set the transparent color"));
|
throw(std::logic_error("Failed to set the transparent color"));
|
||||||
}
|
}
|
||||||
|
if (!local) {
|
||||||
|
throw(std::logic_error("Cannot set the transparent color of a non-local surface"));
|
||||||
|
}
|
||||||
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, SDL_MapRGB(surface->format, r, g, b));
|
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, SDL_MapRGB(surface->format, r, g, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,5 +138,8 @@ void Image::ClearTransparentColor() {
|
|||||||
if (!surface) {
|
if (!surface) {
|
||||||
throw(std::logic_error("Failed to clear the transparent color"));
|
throw(std::logic_error("Failed to clear the transparent color"));
|
||||||
}
|
}
|
||||||
|
if (!local) {
|
||||||
|
throw(std::logic_error("Cannot clear the transparent color of a non-local surface"));
|
||||||
|
}
|
||||||
SDL_SetColorKey(surface, 0, 0);
|
SDL_SetColorKey(surface, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -28,14 +28,21 @@
|
|||||||
class Image {
|
class Image {
|
||||||
public:
|
public:
|
||||||
Image() = default;
|
Image() = default;
|
||||||
|
Image(Image const& rhs) { *this = rhs; }
|
||||||
|
Image(Image&& rhs) { *this = std::move(rhs); }
|
||||||
|
Image(std::string fname) { LoadSurface(fname); }
|
||||||
|
Image(Uint16 w, Uint16 h) { CreateSurface(w, h); }
|
||||||
Image(SDL_Surface* p) { SetSurface(p); }
|
Image(SDL_Surface* p) { SetSurface(p); }
|
||||||
~Image() { FreeSurface(); }
|
~Image() { FreeSurface(); }
|
||||||
|
|
||||||
SDL_Surface* LoadSurface(std::string fname);
|
Image& operator=(Image const&);
|
||||||
void FreeSurface();
|
Image& operator=(Image&&);
|
||||||
|
|
||||||
|
SDL_Surface* LoadSurface(std::string fname);
|
||||||
|
SDL_Surface* CreateSurface(Uint16 w, Uint16 h);
|
||||||
SDL_Surface* SetSurface(SDL_Surface*);
|
SDL_Surface* SetSurface(SDL_Surface*);
|
||||||
SDL_Surface* GetSurface() const { return surface; }
|
SDL_Surface* GetSurface() const { return surface; }
|
||||||
|
void FreeSurface();
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const, Sint16 x, Sint16 y);
|
void DrawTo(SDL_Surface* const, Sint16 x, Sint16 y);
|
||||||
|
|
||||||
@@ -53,7 +60,7 @@ public:
|
|||||||
Uint16 GetClipW() const { return clip.w; }
|
Uint16 GetClipW() const { return clip.w; }
|
||||||
Uint16 GetClipH() const { return clip.h; }
|
Uint16 GetClipH() const { return clip.h; }
|
||||||
|
|
||||||
bool GetLocal() { return local; }
|
bool GetLocal() const { return local; }
|
||||||
|
|
||||||
void SetTransparentColor(Uint8 r, Uint8 g, Uint8 b);
|
void SetTransparentColor(Uint8 r, Uint8 g, Uint8 b);
|
||||||
void ClearTransparentColor();
|
void ClearTransparentColor();
|
||||||
@@ -1,23 +1,25 @@
|
|||||||
#config
|
#config
|
||||||
LOCALLIBS=../lib/libCommon.a
|
INCLUDES+=. .. ../map
|
||||||
LIB=
|
LIBS+=
|
||||||
INCLUDES=../common
|
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
#source
|
#source
|
||||||
SRC=$(wildcard *.cpp)
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
#objects
|
#objects
|
||||||
OBJDIR=obj
|
OBJDIR=obj
|
||||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
#output
|
#output
|
||||||
OUTDIR=../out
|
OUTDIR=../..
|
||||||
OUT=$(addprefix $(OUTDIR)/,test)
|
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||||
|
|
||||||
#targets
|
#targets
|
||||||
all: $(OBJ) $(OUT)
|
all: $(OBJ) $(OUT)
|
||||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
|
||||||
$(OBJ): | $(OBJDIR)
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
@@ -32,6 +34,9 @@ $(OUTDIR):
|
|||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) *.o *.a *.exe
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "sprite_sheet.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
void SpriteSheet::Update(double delta) {
|
||||||
|
if (delay && (tick += delta) >= delay) {
|
||||||
|
if (++xIndex >= xCount) {
|
||||||
|
xIndex = 0;
|
||||||
|
}
|
||||||
|
tick = 0;
|
||||||
|
}
|
||||||
|
image.SetClipX(xIndex * image.GetClipW());
|
||||||
|
image.SetClipY(yIndex * image.GetClipH());
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* SpriteSheet::LoadSurface(std::string fname, Uint16 xCellCount, Uint16 yCellCount) {
|
||||||
|
image.LoadSurface(fname);
|
||||||
|
|
||||||
|
xCount = xCellCount;
|
||||||
|
yCount = yCellCount;
|
||||||
|
|
||||||
|
image.SetClipW(image.GetSurface()->w / xCount);
|
||||||
|
image.SetClipH(image.GetSurface()->h / yCount);
|
||||||
|
|
||||||
|
xIndex = yIndex = 0;
|
||||||
|
delay = tick = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* SpriteSheet::SetSurface(SDL_Surface* surface, Uint16 xCellCount, Uint16 yCellCount) {
|
||||||
|
image.SetSurface(surface);
|
||||||
|
|
||||||
|
xCount = xCellCount;
|
||||||
|
yCount = yCellCount;
|
||||||
|
|
||||||
|
image.SetClipW(image.GetSurface()->w / xCount);
|
||||||
|
image.SetClipH(image.GetSurface()->h / yCount);
|
||||||
|
|
||||||
|
xIndex = yIndex = 0;
|
||||||
|
delay = tick = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpriteSheet::FreeSurface() {
|
||||||
|
image.FreeSurface();
|
||||||
|
xCount = yCount = 0;
|
||||||
|
xIndex = yIndex = 0;
|
||||||
|
delay = tick = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint16 SpriteSheet::SetXCount(Uint16 i) {
|
||||||
|
xIndex = 0;
|
||||||
|
return xCount = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint16 SpriteSheet::SetYCount(Uint16 i) {
|
||||||
|
yIndex = 0;
|
||||||
|
return yCount = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint16 SpriteSheet::SetXIndex(Uint16 i) {
|
||||||
|
if (i > xCount) {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Cannot set x index to " << i;
|
||||||
|
throw(std::invalid_argument(os.str()));
|
||||||
|
}
|
||||||
|
return xIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint16 SpriteSheet::SetYIndex(Uint16 i) {
|
||||||
|
if (i > yCount) {
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Cannot set y index to " << i;
|
||||||
|
throw(std::invalid_argument(os.str()));
|
||||||
|
}
|
||||||
|
return yIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
double SpriteSheet::SetDelay(double d) {
|
||||||
|
tick = 0;
|
||||||
|
return delay = d;
|
||||||
|
}
|
||||||
@@ -24,39 +24,43 @@
|
|||||||
|
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
#include "SDL/SDL.h"
|
|
||||||
|
|
||||||
class SpriteSheet {
|
class SpriteSheet {
|
||||||
public:
|
public:
|
||||||
SpriteSheet() = default;
|
SpriteSheet() = default;
|
||||||
SpriteSheet(SDL_Surface* s, Uint16 w, Uint16 h) { SetSurface(s, w, h); }
|
SpriteSheet(std::string fname, Uint16 xCellCount, Uint16 yCellCount) { LoadSurface(fname, xCellCount, yCellCount); }
|
||||||
~SpriteSheet() = default;
|
SpriteSheet(SDL_Surface* surface, Uint16 xCellCount, Uint16 yCellCount) { SetSurface(surface, xCellCount, yCellCount); }
|
||||||
|
~SpriteSheet() { FreeSurface(); };
|
||||||
|
|
||||||
void Update(double delta);
|
void Update(double delta);
|
||||||
|
|
||||||
SDL_Surface* SetSurface(SDL_Surface* const, Uint16 w, Uint16 h);
|
SDL_Surface* LoadSurface(std::string fname, Uint16 xCellCount, Uint16 yCellCount);
|
||||||
SDL_Surface* GetSurface() const { return image.GetSurface(); }
|
SDL_Surface* SetSurface(SDL_Surface* surface, Uint16 xCellCount, Uint16 yCellCount);
|
||||||
|
SDL_Surface* GetSurface() { return image.GetSurface(); }
|
||||||
|
void FreeSurface();
|
||||||
|
|
||||||
void DrawTo(SDL_Surface* const dest, Sint16 x, Sint16 y) { image.DrawTo(dest, x, y); }
|
void DrawTo(SDL_Surface* const dest, Sint16 x, Sint16 y) { image.DrawTo(dest, x, y); }
|
||||||
|
|
||||||
//Accessors and Mutators
|
//accessors and mutators
|
||||||
double SetDelay(double i) { return delay = i; }
|
Image* GetImage() { return ℑ } //OO breaker
|
||||||
|
|
||||||
|
Uint16 SetXCount(Uint16);
|
||||||
|
Uint16 SetYCount(Uint16);
|
||||||
|
Uint16 SetXIndex(Uint16);
|
||||||
|
Uint16 SetYIndex(Uint16);
|
||||||
|
|
||||||
|
Uint16 GetXCount() const { return xCount; }
|
||||||
|
Uint16 GetYCount() const { return yCount; }
|
||||||
|
Uint16 GetXIndex() const { return xIndex; }
|
||||||
|
Uint16 GetYIndex() const { return yIndex; }
|
||||||
|
|
||||||
|
double SetDelay(double d);
|
||||||
double GetDelay() const { return delay; }
|
double GetDelay() const { return delay; }
|
||||||
|
|
||||||
int SetCurrentFrame(int i) { return currentFrame = i; }
|
|
||||||
int SetCurrentStrip(int i) { return currentStrip = i; }
|
|
||||||
|
|
||||||
Uint16 GetFrameWidth() const { return image.GetClipW(); }
|
|
||||||
Uint16 GetFrameHeight() const { return image.GetClipH(); }
|
|
||||||
int GetCurrentFrame() const { return currentFrame; };
|
|
||||||
int GetCurrentStrip() const { return currentStrip; };
|
|
||||||
int GetMaxFrames() const { return maxFrames; }
|
|
||||||
int GetMaxStrips() const { return maxStrips; }
|
|
||||||
private:
|
private:
|
||||||
Image image;
|
Image image;
|
||||||
int currentFrame = 0, maxFrames = 0;
|
Uint16 xCount = 0, yCount = 0; //number of cells
|
||||||
int currentStrip = 0, maxStrips = 0;
|
Uint16 xIndex = 0, yIndex = 0; //current cell being drawn
|
||||||
double delay = 0, ticks = 0;
|
double delay = 0.0, tick = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#include "tile_sheet.hpp"
|
||||||
|
|
||||||
|
void TileSheet::Load(std::string fname, int xc, int yc) {
|
||||||
|
XCount = xc;
|
||||||
|
YCount = yc;
|
||||||
|
image.LoadSurface(fname);
|
||||||
|
image.SetClipW(image.GetClipW()/XCount);
|
||||||
|
image.SetClipH(image.GetClipH()/YCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheet::Unload() {
|
||||||
|
image.FreeSurface();
|
||||||
|
XCount = YCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, Region::type_t tile) {
|
||||||
|
//0 is invisible
|
||||||
|
if (tile == 0) return;
|
||||||
|
image.SetClipX((tile-1) % XCount * image.GetClipW());
|
||||||
|
image.SetClipY((tile-1) / XCount * image.GetClipH());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/* 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 TILESHEET_HPP_
|
||||||
|
#define TILESHEET_HPP_
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
#include "image.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class TileSheet {
|
||||||
|
public:
|
||||||
|
TileSheet() = default;
|
||||||
|
TileSheet(std::string f, int x, int y) { Load(f, x, y); }
|
||||||
|
~TileSheet() = default;
|
||||||
|
|
||||||
|
void Load(std::string fname, int XCount, int YCount);
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
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
|
||||||
|
Image* GetImage() { return ℑ }
|
||||||
|
int GetXCount() { return XCount; }
|
||||||
|
int GetYCount() { return YCount; }
|
||||||
|
int GetTileW() { return image.GetClipW(); }
|
||||||
|
int GetTileH() { return image.GetClipH(); }
|
||||||
|
private:
|
||||||
|
Image image;
|
||||||
|
int XCount = 0, YCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,23 +1,30 @@
|
|||||||
#config
|
#config
|
||||||
LOCALLIBS=
|
INCLUDES+=.
|
||||||
LIB=
|
LIBS+=
|
||||||
INCLUDES=
|
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
#source
|
#source
|
||||||
SRC=$(wildcard *.cpp)
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
#objects
|
#objects
|
||||||
OBJDIR=obj
|
OBJDIR=obj
|
||||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
#output
|
#output
|
||||||
OUTDIR=../lib
|
OUTDIR=..
|
||||||
OUT=$(addprefix $(OUTDIR)/,libCommon.a)
|
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||||
|
|
||||||
#targets
|
#targets
|
||||||
all: $(OBJ) $(OUT)
|
all: $(OBJ) $(OUT)
|
||||||
ar -crs $(OUT) $(OBJ)
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
$(MAKE) -C graphics
|
||||||
|
$(MAKE) -C map
|
||||||
|
$(MAKE) -C script
|
||||||
|
$(MAKE) -C network
|
||||||
|
$(MAKE) -C ui
|
||||||
|
|
||||||
$(OBJ): | $(OBJDIR)
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
@@ -32,6 +39,9 @@ $(OUTDIR):
|
|||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) *.o *.a *.exe
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#config
|
||||||
|
INCLUDES+=. .. ../graphics
|
||||||
|
LIBS+=
|
||||||
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
#source
|
||||||
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
|
#objects
|
||||||
|
OBJDIR=obj
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
|
#output
|
||||||
|
OUTDIR=../..
|
||||||
|
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||||
|
|
||||||
|
#targets
|
||||||
|
all: $(OBJ) $(OUT)
|
||||||
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
|
||||||
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUT): | $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUTDIR):
|
||||||
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#include "map_file_format.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
void DummyFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
void DummyFormat::Save(Region* const ptr) {
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void VerboseFormat::Load(Region** const ptr, int x, int y) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerboseFormat::Save(Region* const ptr) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompactFormat::Load(Region** const ptr, int x, int y) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompactFormat::Save(Region* const ptr) {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void LuaFormat::Load(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
//something to load into
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Load");
|
||||||
|
lua_pushlightuserdata(state, *ptr);
|
||||||
|
lua_pushstring(state, saveDir.c_str());
|
||||||
|
if (lua_pcall(state, 2, 1, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
if (lua_toboolean(state, -1) == false) {
|
||||||
|
delete (*ptr);
|
||||||
|
(*ptr) = nullptr;
|
||||||
|
}
|
||||||
|
lua_pop(state, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaFormat::Save(Region* const ptr) {
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Save");
|
||||||
|
lua_pushlightuserdata(state, ptr);
|
||||||
|
lua_pushstring(state, saveDir.c_str());
|
||||||
|
if (lua_pcall(state, 2, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
lua_pop(state, 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/* 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 MAPFILEFORMAT_HPP_
|
||||||
|
#define MAPFILEFORMAT_HPP_
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
#include "lua/lua.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class DummyFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
class VerboseFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompactFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
class LuaFormat {
|
||||||
|
public:
|
||||||
|
void Load(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Save(Region* const);
|
||||||
|
|
||||||
|
std::string SetSaveDir(std::string s) { return saveDir = s; }
|
||||||
|
std::string GetSaveDir() { return saveDir; }
|
||||||
|
|
||||||
|
lua_State* SetLuaState(lua_State* L) { return state = L; }
|
||||||
|
lua_State* GetLuaState() { return state; }
|
||||||
|
private:
|
||||||
|
std::string saveDir;
|
||||||
|
lua_State* state = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
void BlankGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlankGenerator::Unload(Region* const ptr) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void PerlinGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerlinGenerator::Unload(Region* const ptr) {
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void LuaGenerator::Create(Region** const ptr, int width, int height, int depth, int x, int y) {
|
||||||
|
//something to work on
|
||||||
|
(*ptr) = new Region(width, height, depth, x, y);
|
||||||
|
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Create");
|
||||||
|
lua_pushlightuserdata(state, *ptr);
|
||||||
|
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
lua_pop(state, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaGenerator::Unload(Region* const ptr) {
|
||||||
|
//API hook
|
||||||
|
lua_getglobal(state, "Region");
|
||||||
|
lua_getfield(state, -1, "Unload");
|
||||||
|
lua_pushlightuserdata(state, ptr);
|
||||||
|
if (lua_pcall(state, 1, 0, 0) != LUA_OK) {
|
||||||
|
throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(state, -1) ));
|
||||||
|
}
|
||||||
|
lua_pop(state, 1);
|
||||||
|
|
||||||
|
//clean up the memory
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/* 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 MAPGENERATOR_HPP_
|
||||||
|
#define MAPGENERATOR_HPP_
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
#include "lua/lua.hpp"
|
||||||
|
|
||||||
|
class BlankGenerator {
|
||||||
|
public:
|
||||||
|
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Unload(Region* const);
|
||||||
|
private:
|
||||||
|
//
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
class PerlinGenerator {
|
||||||
|
public:
|
||||||
|
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Unload(Region* const);
|
||||||
|
private:
|
||||||
|
//
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
class LuaGenerator {
|
||||||
|
public:
|
||||||
|
void Create(Region** const, int width, int height, int depth, int x, int y);
|
||||||
|
void Unload(Region* const);
|
||||||
|
|
||||||
|
lua_State* SetLuaState(lua_State* L) { return state = L; }
|
||||||
|
lua_State* GetLuaState() { return state; }
|
||||||
|
private:
|
||||||
|
lua_State* state = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
Region::Region(int argWidth, int argHeight, int argDepth, int argX, int argY):
|
||||||
|
width(argWidth),
|
||||||
|
height(argHeight),
|
||||||
|
depth(argDepth),
|
||||||
|
x(argX),
|
||||||
|
y(argY)
|
||||||
|
{
|
||||||
|
tiles = new type_t**[width];
|
||||||
|
for (register int i = 0; i < width; ++i) {
|
||||||
|
tiles[i] = new type_t*[height];
|
||||||
|
for (register int j = 0; j < height; ++j) {
|
||||||
|
tiles[i][j] = new type_t[depth];
|
||||||
|
for (register int k = 0; k < depth; ++k) {
|
||||||
|
tiles[i][j][k] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Region::~Region() {
|
||||||
|
for (register int i = 0; i < width; ++i) {
|
||||||
|
for (register int j = 0; j < height; j++) {
|
||||||
|
delete tiles[i][j];
|
||||||
|
}
|
||||||
|
delete tiles[i];
|
||||||
|
}
|
||||||
|
delete tiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
|
||||||
|
return tiles[x][y][z] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region::type_t Region::GetTile(int x, int y, int z) {
|
||||||
|
return tiles[x][y][z];
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -19,31 +19,39 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef SURFACEMANAGER_HPP_
|
#ifndef REGION_HPP_
|
||||||
#define SURFACEMANAGER_HPP_
|
#define REGION_HPP_
|
||||||
|
|
||||||
#include "SDL/SDL.h"
|
//temporary?
|
||||||
|
#define REGION_WIDTH 20
|
||||||
|
#define REGION_HEIGHT 20
|
||||||
|
#define REGION_DEPTH 3
|
||||||
|
|
||||||
#include <map>
|
class Region {
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class SurfaceManager {
|
|
||||||
public:
|
public:
|
||||||
SurfaceManager() = default;
|
typedef unsigned short type_t;
|
||||||
~SurfaceManager() noexcept { FreeAll(); }
|
|
||||||
|
|
||||||
SDL_Surface* Load(std::string key, std::string fname);
|
Region() = delete;
|
||||||
SDL_Surface* Reload(std::string key, std::string fname);
|
Region(int width, int height, int depth, int x, int y);
|
||||||
SDL_Surface* Get(std::string key);
|
~Region();
|
||||||
SDL_Surface* Set(std::string key, SDL_Surface* ptr);
|
|
||||||
void Free(std::string key);
|
|
||||||
void FreeAll();
|
|
||||||
|
|
||||||
SDL_Surface* operator[](std::string key) { return Get(key); };
|
type_t SetTile(int x, int y, int z, type_t v);
|
||||||
|
type_t GetTile(int x, int y, int z);
|
||||||
|
|
||||||
|
//accessors
|
||||||
|
int GetWidth() const { return width; }
|
||||||
|
int GetHeight() const { return height; }
|
||||||
|
int GetDepth() const { return depth; }
|
||||||
|
int GetX() const { return x; }
|
||||||
|
int GetY() const { return y; }
|
||||||
private:
|
private:
|
||||||
SDL_Surface* LoadSurface(std::string key, std::string fname);
|
const int width;
|
||||||
typedef std::map<std::string, SDL_Surface*> MapType;
|
const int height;
|
||||||
MapType surfaceMap;
|
const int depth;
|
||||||
|
const int x;
|
||||||
|
const int y;
|
||||||
|
|
||||||
|
type_t*** tiles = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#include "region_pager.hpp"
|
||||||
|
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
RegionPagerBase::RegionPagerBase(int argWidth, int argHeight, int argDepth):
|
||||||
|
regionWidth(argWidth),
|
||||||
|
regionHeight(argHeight),
|
||||||
|
regionDepth(argDepth)
|
||||||
|
{
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionPagerBase::~RegionPagerBase() {
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) {
|
||||||
|
Region* ptr = GetRegion(x, y);
|
||||||
|
return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Region::type_t RegionPagerBase::GetTile(int x, int y, int z) {
|
||||||
|
Region* ptr = GetRegion(x, y);
|
||||||
|
return ptr->GetTile(x - ptr->GetX(), y - ptr->GetY(), z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* RegionPagerBase::GetRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
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
|
||||||
|
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||||
|
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* RegionPagerBase::PushRegion(Region* ptr) {
|
||||||
|
regionList.push_front(ptr);
|
||||||
|
return regionList.front();
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
/* 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 REGIONPAGER_HPP_
|
||||||
|
#define REGIONPAGER_HPP_
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
class RegionPagerBase {
|
||||||
|
public:
|
||||||
|
RegionPagerBase() = default;
|
||||||
|
RegionPagerBase(int regionWidth, int regionHeight, int regionDepth);
|
||||||
|
virtual ~RegionPagerBase();
|
||||||
|
|
||||||
|
//tile manipulation
|
||||||
|
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 manipulation
|
||||||
|
Region* GetRegion(int x, int y);
|
||||||
|
Region* FindRegion(int x, int y);
|
||||||
|
Region* PushRegion(Region*);
|
||||||
|
|
||||||
|
//interface
|
||||||
|
virtual Region* LoadRegion(int x, int y) = 0;
|
||||||
|
virtual Region* SaveRegion(int x, int y) = 0;
|
||||||
|
virtual Region* CreateRegion(int x, int y) = 0;
|
||||||
|
virtual void UnloadRegion(int x, int y) = 0;
|
||||||
|
//TODO: delete?
|
||||||
|
|
||||||
|
//accessors & mutators
|
||||||
|
//NOTE: don't change the sizes mid-program, it will cause issues
|
||||||
|
int SetRegionWidth(int i) { return regionWidth = i; }
|
||||||
|
int SetRegionHeight(int i) { return regionHeight = i; }
|
||||||
|
int SetRegionDepth(int i) { return regionDepth = i; }
|
||||||
|
|
||||||
|
int GetRegionWidth() const { return regionWidth; }
|
||||||
|
int GetRegionHeight() const { return regionHeight; }
|
||||||
|
int GetRegionDepth() const { return regionDepth; }
|
||||||
|
|
||||||
|
std::list<Region*>* GetContainer() { return ®ionList; }
|
||||||
|
protected:
|
||||||
|
int regionWidth;
|
||||||
|
int regionHeight;
|
||||||
|
int regionDepth;
|
||||||
|
std::list<Region*> regionList;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename MapGenerator, typename MapFileFormat>
|
||||||
|
class RegionPager : public RegionPagerBase {
|
||||||
|
public:
|
||||||
|
RegionPager() = default;
|
||||||
|
RegionPager(int w, int h, int d):
|
||||||
|
RegionPagerBase(w, h, d)
|
||||||
|
{
|
||||||
|
//EMPTY
|
||||||
|
}
|
||||||
|
~RegionPager() {
|
||||||
|
UnloadAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* LoadRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
//load the region if possible
|
||||||
|
Region* ptr = nullptr;
|
||||||
|
format.Load(&ptr, regionWidth, regionHeight, regionDepth, x, y);
|
||||||
|
if (ptr) {
|
||||||
|
regionList.push_back(ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* SaveRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
//find & save the region
|
||||||
|
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); it++) {
|
||||||
|
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||||
|
format.Save(*it);
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region* CreateRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
//create and push the object
|
||||||
|
Region* ptr = nullptr;
|
||||||
|
generator.Create(&ptr, regionWidth, regionHeight, regionDepth, x, y);
|
||||||
|
regionList.push_back(ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadRegion(int x, int y) {
|
||||||
|
//snap the coords
|
||||||
|
x = snapToBase(regionWidth, x);
|
||||||
|
y = snapToBase(regionHeight, y);
|
||||||
|
|
||||||
|
for (std::list<Region*>::iterator it = regionList.begin(); it != regionList.end(); /* EMPTY */) {
|
||||||
|
if ((*it)->GetX() == x && (*it)->GetY() == y) {
|
||||||
|
generator.Unload(*it);
|
||||||
|
regionList.erase(it);
|
||||||
|
|
||||||
|
//reset the loop, because of reasons
|
||||||
|
it = regionList.begin();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void UnloadAll() {
|
||||||
|
for (auto& it : regionList) {
|
||||||
|
generator.Unload(it);
|
||||||
|
}
|
||||||
|
regionList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//accessors
|
||||||
|
MapGenerator* GetGenerator() { return &generator; }
|
||||||
|
MapFileFormat* GetFormat() { return &format; }
|
||||||
|
protected:
|
||||||
|
MapGenerator generator;
|
||||||
|
MapFileFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#config
|
||||||
|
INCLUDES+=. .. ../map
|
||||||
|
LIBS+=
|
||||||
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
#source
|
||||||
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
|
#objects
|
||||||
|
OBJDIR=obj
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
|
#output
|
||||||
|
OUTDIR=../..
|
||||||
|
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||||
|
|
||||||
|
#targets
|
||||||
|
all: $(OBJ) $(OUT)
|
||||||
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
|
||||||
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUT): | $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUTDIR):
|
||||||
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
@@ -19,10 +19,11 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef PACKETTYPE_HPP_
|
#ifndef NETWORKPACKET_HPP_
|
||||||
#define PACKETTYPE_HPP_
|
#define NETWORKPACKET_HPP_
|
||||||
|
|
||||||
#include "vector2.hpp"
|
#include "vector2.hpp"
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
#include "SDL/SDL_net.h"
|
#include "SDL/SDL_net.h"
|
||||||
|
|
||||||
@@ -30,31 +31,47 @@
|
|||||||
|
|
||||||
#pragma pack(push, 0)
|
#pragma pack(push, 0)
|
||||||
|
|
||||||
union Packet {
|
union NetworkPacket {
|
||||||
//the type of packet being sent
|
//types of packets
|
||||||
enum class Type {
|
enum class Type {
|
||||||
|
//default: there is something wrong
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
|
|
||||||
|
//not used
|
||||||
PING = 1,
|
PING = 1,
|
||||||
PONG = 2,
|
PONG = 2,
|
||||||
|
|
||||||
|
//Searching for a server to join
|
||||||
BROADCAST_REQUEST = 3,
|
BROADCAST_REQUEST = 3,
|
||||||
BROADCAST_RESPONSE = 4,
|
BROADCAST_RESPONSE = 4,
|
||||||
|
|
||||||
|
//try to join the server
|
||||||
JOIN_REQUEST = 5,
|
JOIN_REQUEST = 5,
|
||||||
JOIN_RESPONSE = 6,
|
JOIN_RESPONSE = 6,
|
||||||
|
|
||||||
|
//disconnect from the server
|
||||||
DISCONNECT = 7,
|
DISCONNECT = 7,
|
||||||
|
|
||||||
|
//mass update
|
||||||
SYNCHRONIZE = 8,
|
SYNCHRONIZE = 8,
|
||||||
|
|
||||||
PLAYER_NEW = 9,
|
//shut down the server
|
||||||
PLAYER_DELETE = 10,
|
SHUTDOWN = 9,
|
||||||
PLAYER_UPDATE = 11,
|
|
||||||
|
//Player movement, etc.
|
||||||
|
PLAYER_NEW = 10,
|
||||||
|
PLAYER_DELETE = 11,
|
||||||
|
PLAYER_UPDATE = 12,
|
||||||
|
|
||||||
|
//map data
|
||||||
|
REGION_REQUEST = 13,
|
||||||
|
REGION_CONTENT = 14,
|
||||||
};
|
};
|
||||||
|
|
||||||
//metadata on the packet itself
|
//metadata on the packet itself
|
||||||
struct Metadata {
|
struct Metadata {
|
||||||
Type type;
|
Type type;
|
||||||
IPaddress address;
|
IPaddress srcAddress;
|
||||||
int clientIndex;
|
|
||||||
}meta;
|
}meta;
|
||||||
|
|
||||||
//information about the server
|
//information about the server
|
||||||
@@ -63,26 +80,38 @@ union Packet {
|
|||||||
//TODO: version info
|
//TODO: version info
|
||||||
char name[PACKET_STRING_SIZE];
|
char name[PACKET_STRING_SIZE];
|
||||||
//TODO: player count
|
//TODO: player count
|
||||||
|
//TODO: map format
|
||||||
}serverInfo;
|
}serverInfo;
|
||||||
|
|
||||||
//information about a specific player
|
//information about the client
|
||||||
struct PlayerInformation {
|
struct ClientInformation {
|
||||||
Metadata meta;
|
Metadata meta;
|
||||||
int index;
|
int index;
|
||||||
|
}clientInfo;
|
||||||
|
|
||||||
|
//information about a player
|
||||||
|
struct PlayerInformation {
|
||||||
|
Metadata meta;
|
||||||
|
int clientIndex;
|
||||||
|
int playerIndex;
|
||||||
char handle[PACKET_STRING_SIZE];
|
char handle[PACKET_STRING_SIZE];
|
||||||
char avatar[PACKET_STRING_SIZE];
|
char avatar[PACKET_STRING_SIZE];
|
||||||
Vector2 position;
|
Vector2 position;
|
||||||
Vector2 motion;
|
Vector2 motion;
|
||||||
//TODO Playerdata
|
|
||||||
}playerInfo;
|
}playerInfo;
|
||||||
|
|
||||||
//zero the packet
|
//map data
|
||||||
Packet() {
|
struct RegionInformation {
|
||||||
|
Metadata meta;
|
||||||
|
int width, height, depth, x, y;
|
||||||
|
Region* region;
|
||||||
|
}regionInfo;
|
||||||
|
|
||||||
|
//defaults
|
||||||
|
NetworkPacket() {
|
||||||
meta.type = Type::NONE;
|
meta.type = Type::NONE;
|
||||||
meta.address.host = 0;
|
meta.srcAddress = {0,0};
|
||||||
meta.address.port = 0;
|
}
|
||||||
meta.clientIndex = -1;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//internal serialization functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void serializeType(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeServer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(buffer, packet->serverInfo.name, PACKET_STRING_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeClient(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(buffer, &packet->clientInfo.index, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializePlayer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//indexes
|
||||||
|
memcpy(buffer, &packet->playerInfo.clientIndex, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->playerInfo.playerIndex, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//text
|
||||||
|
memcpy(buffer, packet->playerInfo.handle, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
memcpy(buffer, packet->playerInfo.avatar, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
|
||||||
|
//vectors
|
||||||
|
memcpy(buffer, &packet->playerInfo.position.x, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(buffer, &packet->playerInfo.position.y, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(buffer, &packet->playerInfo.motion.x, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(buffer, &packet->playerInfo.motion.y, sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeRegionFormat(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//size
|
||||||
|
memcpy(buffer, &packet->regionInfo.width, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->regionInfo.height, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->regionInfo.depth, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//x & y
|
||||||
|
memcpy(buffer, &packet->regionInfo.x, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(buffer, &packet->regionInfo.y, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void serializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||||
|
//format
|
||||||
|
memcpy(buffer, &packet->meta.type, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//size
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetWidth();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetHeight();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetDepth();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//x & y
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetX();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
*reinterpret_cast<int*>(buffer) = packet->regionInfo.region->GetY();
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//content
|
||||||
|
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) {
|
||||||
|
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) {
|
||||||
|
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) {
|
||||||
|
*reinterpret_cast<Region::type_t*>(buffer) = packet->regionInfo.region->GetTile(i, j, k);
|
||||||
|
buffer += sizeof(Region::type_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//internal deserialization functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void deserializeType(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeServer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(packet->serverInfo.name, buffer, PACKET_STRING_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeClient(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
memcpy(&packet->clientInfo.index, buffer, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializePlayer(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//indexes
|
||||||
|
memcpy(&packet->playerInfo.clientIndex, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->playerInfo.playerIndex, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//text
|
||||||
|
memcpy(packet->playerInfo.handle, buffer, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
memcpy(packet->playerInfo.avatar, buffer, PACKET_STRING_SIZE);
|
||||||
|
buffer += PACKET_STRING_SIZE;
|
||||||
|
|
||||||
|
//vectors
|
||||||
|
memcpy(&packet->playerInfo.position.x, buffer, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(&packet->playerInfo.position.y, buffer, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(&packet->playerInfo.motion.x, buffer, sizeof(double));
|
||||||
|
buffer += sizeof(double);
|
||||||
|
memcpy(&packet->playerInfo.motion.y, buffer, sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeRegionFormat(NetworkPacket* packet, char* buffer) {
|
||||||
|
memcpy(&packet->meta.type, buffer, sizeof(NetworkPacket::Type));
|
||||||
|
buffer += sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//size
|
||||||
|
memcpy(&packet->regionInfo.width, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->regionInfo.height, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->regionInfo.depth, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
|
||||||
|
//x & y
|
||||||
|
memcpy(&packet->regionInfo.x, buffer, sizeof(int));
|
||||||
|
buffer += sizeof(int);
|
||||||
|
memcpy(&packet->regionInfo.y, buffer, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeRegionContent(NetworkPacket* packet, char* buffer) {
|
||||||
|
//format
|
||||||
|
deserializeRegionFormat(packet, buffer);
|
||||||
|
buffer += sizeof(int) * 5 + sizeof(NetworkPacket::Type);
|
||||||
|
|
||||||
|
//content
|
||||||
|
BlankGenerator().Create(
|
||||||
|
&packet->regionInfo.region,
|
||||||
|
packet->regionInfo.width,
|
||||||
|
packet->regionInfo.height,
|
||||||
|
packet->regionInfo.depth,
|
||||||
|
packet->regionInfo.x,
|
||||||
|
packet->regionInfo.y
|
||||||
|
);
|
||||||
|
|
||||||
|
for (register int i = 0; i < packet->regionInfo.region->GetWidth(); i++) {
|
||||||
|
for (register int j = 0; j < packet->regionInfo.region->GetHeight(); j++) {
|
||||||
|
for (register int k = 0; k < packet->regionInfo.region->GetDepth(); k++) {
|
||||||
|
packet->regionInfo.region->SetTile(i, j, k, *reinterpret_cast<Region::type_t*>(buffer));
|
||||||
|
buffer += sizeof(Region::type_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//the interface functions
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void serialize(NetworkPacket* packet, void* buffer) {
|
||||||
|
switch(packet->meta.type) {
|
||||||
|
//No extra data
|
||||||
|
case NetworkPacket::Type::NONE:
|
||||||
|
case NetworkPacket::Type::PING:
|
||||||
|
case NetworkPacket::Type::PONG:
|
||||||
|
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||||
|
case NetworkPacket::Type::JOIN_REQUEST:
|
||||||
|
case NetworkPacket::Type::SYNCHRONIZE:
|
||||||
|
serializeType(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Server info
|
||||||
|
case NetworkPacket::Type::BROADCAST_RESPONSE:
|
||||||
|
serializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Client info
|
||||||
|
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||||
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
|
case NetworkPacket::Type::SHUTDOWN:
|
||||||
|
serializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Player info
|
||||||
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
|
serializePlayer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//region info
|
||||||
|
case NetworkPacket::Type::REGION_REQUEST:
|
||||||
|
serializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkPacket::Type::REGION_CONTENT:
|
||||||
|
serializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(NetworkPacket* packet, void* buffer) {
|
||||||
|
//find the type, so that you can actually deserialize the packet!
|
||||||
|
deserializeType(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
switch(packet->meta.type) {
|
||||||
|
//No extra data
|
||||||
|
case NetworkPacket::Type::NONE:
|
||||||
|
case NetworkPacket::Type::PING:
|
||||||
|
case NetworkPacket::Type::PONG:
|
||||||
|
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||||
|
case NetworkPacket::Type::JOIN_REQUEST:
|
||||||
|
case NetworkPacket::Type::SYNCHRONIZE:
|
||||||
|
//NOTHING
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Server info
|
||||||
|
case NetworkPacket::Type::BROADCAST_RESPONSE:
|
||||||
|
deserializeServer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Client info
|
||||||
|
case NetworkPacket::Type::JOIN_RESPONSE:
|
||||||
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
|
case NetworkPacket::Type::SHUTDOWN:
|
||||||
|
deserializeClient(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Player info
|
||||||
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
|
deserializePlayer(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
//region info
|
||||||
|
case NetworkPacket::Type::REGION_REQUEST:
|
||||||
|
deserializeRegionFormat(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NetworkPacket::Type::REGION_CONTENT:
|
||||||
|
deserializeRegionContent(packet, reinterpret_cast<char*>(buffer));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* 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 SERIAL_HPP_
|
||||||
|
#define SERIAL_HPP_
|
||||||
|
|
||||||
|
#include "network_packet.hpp"
|
||||||
|
|
||||||
|
/* Sending regions are the largest type of packet
|
||||||
|
* content: width * height * depth * sizoeof(type)
|
||||||
|
* map format: sizeof(int) * 5
|
||||||
|
* metadata: sizeof(metadata)
|
||||||
|
*/
|
||||||
|
#define PACKET_BUFFER_SIZE REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + sizeof(int) * 5 + sizeof(NetworkPacket::Metadata)
|
||||||
|
|
||||||
|
void serialize(NetworkPacket* const, void*);
|
||||||
|
void deserialize(NetworkPacket* const, void*);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -32,17 +32,9 @@ public:
|
|||||||
void Open(int port, int packSize);
|
void Open(int port, int packSize);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
//bind to an available channel
|
//bind to a channel
|
||||||
int Bind(const char* ip, int port) {
|
int Bind(const char* ip, int port, int channel = -1);
|
||||||
Bind(ip, port, -1);
|
int Bind(IPaddress* add, int channel = -1);
|
||||||
}
|
|
||||||
int Bind(IPaddress* add) {
|
|
||||||
Bind(add, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//bind to certain channel
|
|
||||||
int Bind(const char* ip, int port, int channel);
|
|
||||||
int Bind(IPaddress* add, int channel);
|
|
||||||
void Unbind(int channel);
|
void Unbind(int channel);
|
||||||
|
|
||||||
IPaddress* GetIPAddress(int channel) {
|
IPaddress* GetIPAddress(int channel) {
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#include "network_queue.hpp"
|
|
||||||
#include "singleton.hpp"
|
|
||||||
|
|
||||||
#include "udp_network_utility.hpp"
|
|
||||||
|
|
||||||
#include "SDL/SDL_thread.h"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <deque>
|
|
||||||
|
|
||||||
static SDL_sem* lock = SDL_CreateSemaphore(1);
|
|
||||||
static SDL_Thread* queueThread = nullptr;
|
|
||||||
|
|
||||||
static std::deque<Packet> queue;
|
|
||||||
|
|
||||||
static bool running = false;
|
|
||||||
|
|
||||||
static int networkQueue(void*) {
|
|
||||||
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
|
|
||||||
while(running) {
|
|
||||||
SDL_SemWait(lock);
|
|
||||||
while(netUtil->Receive()) {
|
|
||||||
Packet p;
|
|
||||||
memcpy(&p, netUtil->GetInData(), sizeof(Packet));
|
|
||||||
p.meta.address = netUtil->GetInPacket()->address;
|
|
||||||
queue.push_back(p);
|
|
||||||
}
|
|
||||||
SDL_SemPost(lock);
|
|
||||||
SDL_Delay(10);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void beginQueueThread() {
|
|
||||||
if (running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
running = true;
|
|
||||||
if (!(queueThread = SDL_CreateThread(networkQueue, nullptr))) {
|
|
||||||
throw(std::runtime_error("Failed to create the network thread"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void endQueueThread() {
|
|
||||||
if (!running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
running = false;
|
|
||||||
SDL_WaitThread(queueThread, nullptr);
|
|
||||||
queueThread = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void killQueueThread() {
|
|
||||||
if (!running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
running = false;
|
|
||||||
SDL_KillThread(queueThread);
|
|
||||||
queueThread = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet peekNetworkPacket() {
|
|
||||||
SDL_SemWait(lock);
|
|
||||||
Packet p;
|
|
||||||
if (queue.size() > 0) {
|
|
||||||
Packet p = queue[0];
|
|
||||||
}
|
|
||||||
SDL_SemPost(lock);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet popNetworkPacket() {
|
|
||||||
SDL_SemWait(lock);
|
|
||||||
Packet p;
|
|
||||||
if (queue.size() > 0) {
|
|
||||||
p = queue[0];
|
|
||||||
queue.pop_front();
|
|
||||||
}
|
|
||||||
SDL_SemPost(lock);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flushNetworkQueue() {
|
|
||||||
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
|
|
||||||
SDL_SemWait(lock);
|
|
||||||
while(netUtil->Receive());
|
|
||||||
queue.clear();
|
|
||||||
SDL_SemPost(lock);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $
|
||||||
|
** Initialization of libraries for lua.c and other clients
|
||||||
|
** See Copyright Notice in lua.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Modified for use in Tortuga, renamed to linit.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If you embed Lua in your program and need to open the standard
|
||||||
|
** libraries, call luaL_openlibs in your program. If you need a
|
||||||
|
** different set of libraries, copy this file to your project and edit
|
||||||
|
** it to suit your needs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define linit_c
|
||||||
|
#define LUA_LIB
|
||||||
|
|
||||||
|
#include "lua/lua.hpp"
|
||||||
|
#include "region_api.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** these libs are loaded by lua.c and are readily available to any Lua
|
||||||
|
** program
|
||||||
|
*/
|
||||||
|
static const luaL_Reg loadedlibs[] = {
|
||||||
|
/* Standard libs */
|
||||||
|
{"_G", luaopen_base},
|
||||||
|
{LUA_LOADLIBNAME, luaopen_package},
|
||||||
|
{LUA_COLIBNAME, luaopen_coroutine},
|
||||||
|
{LUA_TABLIBNAME, luaopen_table},
|
||||||
|
{LUA_IOLIBNAME, luaopen_io},
|
||||||
|
{LUA_OSLIBNAME, luaopen_os},
|
||||||
|
{LUA_STRLIBNAME, luaopen_string},
|
||||||
|
{LUA_BITLIBNAME, luaopen_bit32},
|
||||||
|
{LUA_MATHLIBNAME, luaopen_math},
|
||||||
|
{LUA_DBLIBNAME, luaopen_debug},
|
||||||
|
|
||||||
|
/* custom libs */
|
||||||
|
{LUA_REGIONLIBNAME, luaopen_regionapi},
|
||||||
|
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** these libs are preloaded and must be required before used
|
||||||
|
*/
|
||||||
|
static const luaL_Reg preloadedlibs[] = {
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
LUALIB_API void luaL_openlibs (lua_State *L) {
|
||||||
|
const luaL_Reg *lib;
|
||||||
|
/* call open functions from 'loadedlibs' and set results to global table */
|
||||||
|
for (lib = loadedlibs; lib->func; lib++) {
|
||||||
|
luaL_requiref(L, lib->name, lib->func, 1);
|
||||||
|
lua_pop(L, 1); /* remove lib */
|
||||||
|
}
|
||||||
|
/* add open functions from 'preloadedlibs' into 'package.preload' table */
|
||||||
|
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||||
|
for (lib = preloadedlibs; lib->func; lib++) {
|
||||||
|
lua_pushcfunction(L, lib->func);
|
||||||
|
lua_setfield(L, -2, lib->name);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1); /* remove _PRELOAD table */
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#config
|
||||||
|
INCLUDES+=. .. ../map
|
||||||
|
LIBS+=
|
||||||
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
#source
|
||||||
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
|
#objects
|
||||||
|
OBJDIR=obj
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
|
#output
|
||||||
|
OUTDIR=../..
|
||||||
|
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||||
|
|
||||||
|
#targets
|
||||||
|
all: $(OBJ) $(OUT)
|
||||||
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
|
||||||
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUT): | $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUTDIR):
|
||||||
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
#include "region_api.hpp"
|
||||||
|
|
||||||
|
#include "region.hpp"
|
||||||
|
|
||||||
|
static int setTile(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
ptr->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getTile(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
int ret = ptr->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
|
||||||
|
lua_pushnumber(L, ret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getWidth(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetWidth());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getHeight(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetHeight());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getDepth(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetDepth());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getX(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetX());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getY(lua_State* L) {
|
||||||
|
Region* ptr = (Region*)lua_touserdata(L, 1);
|
||||||
|
lua_pushinteger(L, ptr->GetY());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dummy(lua_State* L) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const luaL_Reg regionlib[] = {
|
||||||
|
{"SetTile",setTile},
|
||||||
|
{"GetTile",getTile},
|
||||||
|
{"GetWidth",getWidth},
|
||||||
|
{"GetHeight",getHeight},
|
||||||
|
{"GetDepth",getDepth},
|
||||||
|
{"GetX",getX},
|
||||||
|
{"GetY",getY},
|
||||||
|
{"Create", dummy},
|
||||||
|
{"Unload", dummy},
|
||||||
|
{"Load", dummy},
|
||||||
|
{"Save", dummy},
|
||||||
|
{nullptr, nullptr}
|
||||||
|
};
|
||||||
|
|
||||||
|
LUAMOD_API int luaopen_regionapi(lua_State* L) {
|
||||||
|
luaL_newlib(L, regionlib);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
/* Copyright: (c) Kayne Ruse 2014
|
||||||
*
|
*
|
||||||
* This software is provided 'as-is', without any express or implied
|
* This software is provided 'as-is', without any express or implied
|
||||||
* warranty. In no event will the authors be held liable for any damages
|
* warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -19,20 +19,12 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef SINGLETON_HPP_
|
#ifndef REGIONAPI_HPP_
|
||||||
#define SINGLETON_HPP_
|
#define REGIONAPI_HPP_
|
||||||
|
|
||||||
template<typename T>
|
#include "lua/lua.hpp"
|
||||||
class Singleton {
|
|
||||||
public:
|
|
||||||
static T* Get() {
|
|
||||||
return &instance;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
static T instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
#define LUA_REGIONLIBNAME "Region"
|
||||||
T Singleton<T>::instance;
|
LUAMOD_API int luaopen_regionapi(lua_State* L);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/* Copyright: (c) Kayne Ruse 2013
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#include "surface_manager.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
SDL_Surface* SurfaceManager::Load(std::string key, std::string fname) {
|
|
||||||
MapType::iterator it = surfaceMap.find(key);
|
|
||||||
if (it != surfaceMap.end()) {
|
|
||||||
throw(std::runtime_error(std::string("Surface already loaded: ") + key + std::string(", ") + fname));
|
|
||||||
}
|
|
||||||
return LoadSurface(key, fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Surface* SurfaceManager::Reload(std::string key, std::string fname) {
|
|
||||||
MapType::iterator it = surfaceMap.find(key);
|
|
||||||
if (it != surfaceMap.end()) {
|
|
||||||
SDL_FreeSurface(it->second);
|
|
||||||
surfaceMap.erase(it);
|
|
||||||
}
|
|
||||||
return LoadSurface(key, fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Surface* SurfaceManager::Get(std::string key) {
|
|
||||||
MapType::iterator it = surfaceMap.find(key);
|
|
||||||
if (it == surfaceMap.end()) {
|
|
||||||
throw(std::runtime_error(std::string("Could not find key: ") + key));
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Surface* SurfaceManager::Set(std::string key, SDL_Surface* ptr) {
|
|
||||||
MapType::iterator it = surfaceMap.find(key);
|
|
||||||
if (it != surfaceMap.end()) {
|
|
||||||
throw(std::runtime_error(std::string("Key already exists: ") + key));
|
|
||||||
}
|
|
||||||
return surfaceMap[key] = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SurfaceManager::Free(std::string key) {
|
|
||||||
MapType::iterator it = surfaceMap.find(key);
|
|
||||||
if (it != surfaceMap.end()) {
|
|
||||||
SDL_FreeSurface(it->second);
|
|
||||||
surfaceMap.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SurfaceManager::FreeAll() {
|
|
||||||
for (auto it : surfaceMap) {
|
|
||||||
SDL_FreeSurface(it.second);
|
|
||||||
}
|
|
||||||
surfaceMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Surface* SurfaceManager::LoadSurface(std::string key, std::string fname) {
|
|
||||||
SDL_Surface* ptr = SDL_LoadBMP(fname.c_str());
|
|
||||||
if (!ptr) {
|
|
||||||
throw(std::runtime_error(std::string("Failed to load file: ") + fname));
|
|
||||||
}
|
|
||||||
SDL_SetColorKey(ptr, SDL_SRCCOLORKEY, SDL_MapRGB(ptr->format, 255, 0, 255)); //default
|
|
||||||
return surfaceMap[key] = ptr;
|
|
||||||
}
|
|
||||||
@@ -23,13 +23,6 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
void Button::Setup(Sint16 i, Sint16 j, SDL_Surface* bg, SDL_Surface* fg, std::string t) {
|
|
||||||
x = i;
|
|
||||||
y = j;
|
|
||||||
SetSurfaces(bg, fg);
|
|
||||||
SetText(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
Button::State Button::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
Button::State Button::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
return CalcState(motion.x, motion.y, motion.state & SDL_BUTTON_LMASK);
|
return CalcState(motion.x, motion.y, motion.state & SDL_BUTTON_LMASK);
|
||||||
}
|
}
|
||||||
@@ -49,41 +42,40 @@ Button::State Button::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Button::DrawTo(SDL_Surface* const dest) {
|
void Button::DrawTo(SDL_Surface* const dest) {
|
||||||
image.DrawTo(dest, x, y);
|
if (!image || !font) {
|
||||||
font.DrawStringTo(text, dest, textX + x, textY + y);
|
throw(std::runtime_error("Surface not set for Button"));
|
||||||
}
|
}
|
||||||
|
image->SetClipY(state * image->GetClipH());
|
||||||
void Button::SetSurfaces(SDL_Surface* bg, SDL_Surface* fg) {
|
image->DrawTo(dest, x, y);
|
||||||
//graphical stuff
|
font->DrawStringTo(text, dest, textX + x, textY + y);
|
||||||
image.SetSurface(bg);
|
|
||||||
image.SetClipH(image.GetClipH() / 3); //3 phases, vertical storage
|
|
||||||
font.SetSurface(fg);
|
|
||||||
|
|
||||||
//reset textX & textY
|
|
||||||
SetText(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Button::SetText(std::string t) {
|
std::string Button::SetText(std::string t) {
|
||||||
|
if (!image || !font) {
|
||||||
|
throw(std::runtime_error("Surface not set for Button"));
|
||||||
|
}
|
||||||
//one line, cache the position
|
//one line, cache the position
|
||||||
text = t;
|
text = t;
|
||||||
textX = (image.GetClipW() / 2) - (font.GetCharW() * text.size() / 2);
|
textX = (image->GetClipW() / 2) - (font->GetCharW() * text.size() / 2);
|
||||||
textY = (image.GetClipH() / 2) - (font.GetCharH() / 2);
|
textY = (image->GetClipH() / 2) - (font->GetCharH() / 2);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
Button::State Button::CalcState(Sint16 i, Sint16 j, bool leftPressed) {
|
Button::State Button::CalcState(Sint16 i, Sint16 j, bool leftPressed) {
|
||||||
if (i < x || i > (x + image.GetClipW()) ||
|
if (!image || !font) {
|
||||||
j < y || j > (y + image.GetClipH())
|
throw(std::runtime_error("Surface not set for Button"));
|
||||||
|
}
|
||||||
|
//if out of bounds
|
||||||
|
if (i < x || i >= (x + image->GetClipW()) ||
|
||||||
|
j < y || j >= (y + image->GetClipH())
|
||||||
) {
|
) {
|
||||||
image.SetClipY(0);
|
|
||||||
return state = State::NORMAL;
|
return state = State::NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leftPressed) {
|
if (leftPressed) {
|
||||||
image.SetClipY(image.GetClipH()*2);
|
|
||||||
return state = State::PRESSED;
|
return state = State::PRESSED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
image.SetClipY(image.GetClipH());
|
|
||||||
return state = State::HOVER;
|
return state = State::HOVER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,52 +27,66 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
//3-phases, no toggle, centred text
|
/* 3-phases, no toggle, centred text
|
||||||
|
* This class uses the size of the provided image as its bounds. Also,
|
||||||
|
* The provided image should be formatted correctly.
|
||||||
|
*
|
||||||
|
* The button's image should be divided into 3 sections virtucally,
|
||||||
|
* which act as the different button images. The clip width & height of the
|
||||||
|
* Image should be set manually, and the height should be 1/3 of the total
|
||||||
|
* graphical data.
|
||||||
|
*/
|
||||||
class Button {
|
class Button {
|
||||||
public:
|
public:
|
||||||
enum class State {
|
enum State {
|
||||||
NORMAL, HOVER, PRESSED
|
NORMAL = 0, HOVER = 1, PRESSED = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
Button() = default;
|
Button() = default;
|
||||||
Button(Sint16 x, Sint16 y, SDL_Surface* bg, SDL_Surface* fg, std::string t = "") { Setup(x, y, bg, fg, t); }
|
~Button() = default;
|
||||||
|
|
||||||
void Setup(Sint16 x, Sint16 y, SDL_Surface* bg, SDL_Surface* fg, std::string text = "");
|
//handle input
|
||||||
|
|
||||||
//return the current state
|
|
||||||
State MouseMotion(SDL_MouseMotionEvent const&);
|
State MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
State MouseButtonDown(SDL_MouseButtonEvent const&);
|
State MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
State MouseButtonUp(SDL_MouseButtonEvent const&);
|
State MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
State GetState() const { return state; }
|
|
||||||
|
|
||||||
//yet another draw function
|
//yet another draw function
|
||||||
void DrawTo(SDL_Surface* const);
|
void DrawTo(SDL_Surface* const);
|
||||||
|
|
||||||
//simple accessors and mutators
|
//accessors and mutators
|
||||||
|
Image* SetImage(Image* const ptr) { return image = ptr; }
|
||||||
|
Image* GetImage() { return image; }
|
||||||
|
RasterFont* SetFont(RasterFont* const ptr) { return font = ptr; }
|
||||||
|
RasterFont* GetFont() { return font; }
|
||||||
|
|
||||||
Sint16 SetX(Sint16 i) { return x = i; }
|
Sint16 SetX(Sint16 i) { return x = i; }
|
||||||
Sint16 SetY(Sint16 i) { return y = i; }
|
Sint16 SetY(Sint16 i) { return y = i; }
|
||||||
Sint16 GetX() const { return x; }
|
Sint16 GetX() const { return x; }
|
||||||
Sint16 GetY() const { return y; }
|
Sint16 GetY() const { return y; }
|
||||||
|
|
||||||
void SetSurfaces(SDL_Surface* bg, SDL_Surface* fg);
|
Sint16 SetTextX(Sint16 i) { return textX = i; }
|
||||||
|
Sint16 SetTextY(Sint16 i) { return textY = i; }
|
||||||
std::string SetText(std::string t);
|
|
||||||
std::string GetText() const { return text; }
|
|
||||||
|
|
||||||
//raw access, be careful
|
|
||||||
Image* GetImage() { return ℑ }
|
|
||||||
RasterFont* GetFont() { return &font; }
|
|
||||||
|
|
||||||
//debug
|
|
||||||
Sint16 GetTextX() const { return textX; }
|
Sint16 GetTextX() const { return textX; }
|
||||||
Sint16 GetTextY() const { return textY; }
|
Sint16 GetTextY() const { return textY; }
|
||||||
|
|
||||||
|
State SetState(State s) { return state = s; }
|
||||||
|
State GetState() const { return state; }
|
||||||
|
|
||||||
|
std::string SetText(std::string);
|
||||||
|
std::string GetText() const { return text; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
State CalcState(Sint16 x, Sint16 y, bool leftPressed);
|
State CalcState(Sint16 x, Sint16 y, bool leftPressed);
|
||||||
|
|
||||||
|
//point to the provided external objects
|
||||||
|
Image* image = nullptr;
|
||||||
|
RasterFont* font = nullptr;
|
||||||
|
|
||||||
|
//positions
|
||||||
Sint16 x = 0, y = 0;
|
Sint16 x = 0, y = 0;
|
||||||
Sint16 textX = 0, textY = 0; //prevent recalc every loop
|
Sint16 textX = 0, textY = 0;
|
||||||
Image image;
|
|
||||||
RasterFont font;
|
//
|
||||||
State state = State::NORMAL;
|
State state = State::NORMAL;
|
||||||
std::string text;
|
std::string text;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#config
|
||||||
|
INCLUDES+=. .. ../graphics
|
||||||
|
LIBS+=
|
||||||
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
#source
|
||||||
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
|
#objects
|
||||||
|
OBJDIR=obj
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
|
#output
|
||||||
|
OUTDIR=../..
|
||||||
|
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||||
|
|
||||||
|
#targets
|
||||||
|
all: $(OBJ) $(OUT)
|
||||||
|
ar -crs $(OUT) $(OBJ)
|
||||||
|
|
||||||
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUT): | $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUTDIR):
|
||||||
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "menu_bar.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
void MenuBar::DrawTo(SDL_Surface* const dest) {
|
||||||
|
for (auto& i : entries) {
|
||||||
|
i.DrawTo(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
|
for (auto& i : entries) {
|
||||||
|
i.MouseMotion(motion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
|
for (auto& i : entries) {
|
||||||
|
i.MouseButtonDown(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::MouseButtonUp(SDL_MouseButtonEvent const& button, int* entry, int* butt) {
|
||||||
|
*entry = *butt = -1;
|
||||||
|
int ret = -1;
|
||||||
|
for (auto& i : entries) {
|
||||||
|
ret = i.MouseButtonUp(button);
|
||||||
|
|
||||||
|
if (ret != -1) {
|
||||||
|
*entry = (&i - entries.data());
|
||||||
|
*butt = ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::SetEntries(std::vector<std::vector<std::string>> info) {
|
||||||
|
if (!image || !font) {
|
||||||
|
throw(std::runtime_error("Surfaces not loaded into the menu bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.clear();
|
||||||
|
for (int i = 0; i < info.size(); i++) {
|
||||||
|
//create the entry & the main button
|
||||||
|
entries.push_back(MenuBarEntry());
|
||||||
|
entries[i].mainButton.SetImage(image);
|
||||||
|
entries[i].mainButton.SetFont(font);
|
||||||
|
entries[i].mainButton.SetText(info[i][0]);
|
||||||
|
entries[i].mainButton.SetX(i * image->GetClipW());
|
||||||
|
entries[i].mainButton.SetY(0);
|
||||||
|
for (int j = 0; j < info[i].size()-1; j++) {
|
||||||
|
//create each drop button in this entry
|
||||||
|
entries[i].dropButtons.push_back(Button());
|
||||||
|
entries[i].dropButtons[j].SetImage(image);
|
||||||
|
entries[i].dropButtons[j].SetFont(font);
|
||||||
|
entries[i].dropButtons[j].SetText(info[i][j+1]);
|
||||||
|
entries[i].dropButtons[j].SetX(i * image->GetClipW());
|
||||||
|
entries[i].dropButtons[j].SetY((j+1) * image->GetClipH());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::MenuBarEntry::DrawTo(SDL_Surface* const dest) {
|
||||||
|
//only draw the dropButtons in the user has this menu open
|
||||||
|
mainButton.DrawTo(dest);
|
||||||
|
|
||||||
|
if (!open) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& i : dropButtons) {
|
||||||
|
i.DrawTo(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::MenuBarEntry::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
|
//open the menu
|
||||||
|
bool o = mainButton.MouseMotion(motion) == Button::State::PRESSED;
|
||||||
|
|
||||||
|
if (!(open |= o)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& i : dropButtons) {
|
||||||
|
//dragging down the menu
|
||||||
|
o |= i.MouseMotion(motion) == Button::State::PRESSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
open = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::MenuBarEntry::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
|
//open the menu
|
||||||
|
if (!(open = mainButton.MouseButtonDown(button) == Button::State::PRESSED)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//update the others anyway
|
||||||
|
for (auto& i : dropButtons) {
|
||||||
|
i.MouseButtonDown(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MenuBar::MenuBarEntry::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
|
int ret = -1;
|
||||||
|
mainButton.MouseButtonUp(button);
|
||||||
|
|
||||||
|
for (auto& i : dropButtons) {
|
||||||
|
//the user just released this button
|
||||||
|
if (i.GetState() != i.MouseButtonUp(button) && i.GetState() == Button::State::HOVER && open) {
|
||||||
|
//get this button's index
|
||||||
|
ret = (&i - dropButtons.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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 MENUBAR_HPP_
|
||||||
|
#define MENUBAR_HPP_
|
||||||
|
|
||||||
|
#include "image.hpp"
|
||||||
|
#include "raster_font.hpp"
|
||||||
|
#include "button.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/* I've redesigned this so that the contents of the menu bar can't change during run time.
|
||||||
|
* This is more restrictive but I'm focusing on getting this working first.
|
||||||
|
* The Image and Font pointers must be set before the text data is entered.
|
||||||
|
*
|
||||||
|
* This class needs a rewrite.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MenuBar {
|
||||||
|
public:
|
||||||
|
MenuBar() = default;
|
||||||
|
~MenuBar() = default;
|
||||||
|
|
||||||
|
//yet another draw function
|
||||||
|
void DrawTo(SDL_Surface* const dest);
|
||||||
|
|
||||||
|
//user inputs
|
||||||
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
|
void MouseButtonUp(SDL_MouseButtonEvent const&, int* entry, int* button);
|
||||||
|
|
||||||
|
//manage the entries & buttons
|
||||||
|
void SetEntries(std::vector<std::vector<std::string>> info);
|
||||||
|
void ClearEntries() { entries.clear(); }
|
||||||
|
|
||||||
|
//Accessors and mutators
|
||||||
|
Image* SetImage(Image* const ptr) { return image = ptr; }
|
||||||
|
Image* GetImage() { return image; }
|
||||||
|
RasterFont* SetFont(RasterFont* const ptr) { return font = ptr; }
|
||||||
|
RasterFont* GetFont() { return font; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
class MenuBarEntry;
|
||||||
|
|
||||||
|
std::vector<MenuBarEntry> entries;
|
||||||
|
|
||||||
|
Image* image = nullptr;
|
||||||
|
RasterFont* font = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MenuBar::MenuBarEntry {
|
||||||
|
public:
|
||||||
|
MenuBarEntry() = default;
|
||||||
|
~MenuBarEntry() = default;
|
||||||
|
|
||||||
|
void DrawTo(SDL_Surface* const dest);
|
||||||
|
|
||||||
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
|
int MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Button mainButton;
|
||||||
|
|
||||||
|
std::vector<Button> dropButtons;
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
friend class MenuBar;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -23,9 +23,8 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
/* Note: This class can only take a raster font with 16*16 characters, and the
|
/* It might be more efficient to render to a different surface (like an Image)
|
||||||
* indevidual characters must have the same dimensions. Overall this class is too
|
* rather than calling this function with all of it's '%' and '/'.
|
||||||
* restrictive; I suggest using a 3rd party library.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x, Sint16 y) {
|
void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x, Sint16 y) {
|
||||||
@@ -41,10 +40,21 @@ void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface* RasterFont::SetSurface(SDL_Surface* p) {
|
/* Note: This class can only take a raster font with 16*16 characters, and the
|
||||||
if (image.SetSurface(p)) {
|
* indevidual characters must have the same dimensions. Overall this class is too
|
||||||
|
* restrictive; I suggest using a 3rd party library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
SDL_Surface* RasterFont::LoadSurface(std::string fname) {
|
||||||
|
image.LoadSurface(fname);
|
||||||
|
image.SetClipW(image.GetSurface()->w/16);
|
||||||
|
image.SetClipH(image.GetSurface()->h/16);
|
||||||
|
return image.GetSurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* RasterFont::SetSurface(SDL_Surface* p) {
|
||||||
|
image.SetSurface(p);
|
||||||
image.SetClipW(image.GetSurface()->w/16);
|
image.SetClipW(image.GetSurface()->w/16);
|
||||||
image.SetClipH(image.GetSurface()->h/16);
|
image.SetClipH(image.GetSurface()->h/16);
|
||||||
}
|
|
||||||
return image.GetSurface();
|
return image.GetSurface();
|
||||||
}
|
}
|
||||||
@@ -24,21 +24,29 @@
|
|||||||
|
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class RasterFont {
|
class RasterFont {
|
||||||
public:
|
public:
|
||||||
RasterFont() = default;
|
RasterFont() = default;
|
||||||
|
RasterFont(RasterFont const& rhs) { *this = rhs; }
|
||||||
|
RasterFont(RasterFont&& rhs) { *this = std::move(rhs); }
|
||||||
|
RasterFont(std::string fname) { LoadSurface(fname); }
|
||||||
RasterFont(SDL_Surface* p) { SetSurface(p); }
|
RasterFont(SDL_Surface* p) { SetSurface(p); }
|
||||||
~RasterFont() = default;
|
~RasterFont() = default;
|
||||||
|
|
||||||
|
RasterFont& operator=(RasterFont const& rhs) { image = rhs.image; }
|
||||||
|
RasterFont& operator=(RasterFont&& rhs) { image = std::move(rhs.image); }
|
||||||
|
|
||||||
void DrawStringTo(std::string, SDL_Surface* const, Sint16 x, Sint16 y);
|
void DrawStringTo(std::string, SDL_Surface* const, Sint16 x, Sint16 y);
|
||||||
|
|
||||||
//Accessors and Mutators
|
//Accessors and Mutators
|
||||||
|
SDL_Surface* LoadSurface(std::string);
|
||||||
SDL_Surface* SetSurface(SDL_Surface*);
|
SDL_Surface* SetSurface(SDL_Surface*);
|
||||||
SDL_Surface* GetSurface() const { return image.GetSurface(); }
|
SDL_Surface* GetSurface() const { return image.GetSurface(); }
|
||||||
Uint16 GetCharW() { return image.GetClipW(); }
|
void FreeSurface() { image.FreeSurface(); }
|
||||||
Uint16 GetCharH() { return image.GetClipH(); }
|
|
||||||
|
Uint16 GetCharW() const { return image.GetClipW(); }
|
||||||
|
Uint16 GetCharH() const { return image.GetClipH(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Image image;
|
Image image;
|
||||||
};
|
};
|
||||||
@@ -19,26 +19,41 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#include "frame_rate.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
#include <algorithm>
|
||||||
|
|
||||||
typedef std::chrono::high_resolution_clock Clock;
|
int snapToBase(int base, int x) {
|
||||||
|
//snap to a grid
|
||||||
static int frameCount = 0;
|
if (x < 0) {
|
||||||
static int lastFrameRate = 0;
|
x++;
|
||||||
static Clock::time_point tick = Clock::now();
|
return x / base * base - base;
|
||||||
|
|
||||||
int clockFrameRate() {
|
|
||||||
frameCount++;
|
|
||||||
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
|
|
||||||
lastFrameRate = frameCount;
|
|
||||||
frameCount = 0;
|
|
||||||
tick = Clock::now();
|
|
||||||
}
|
}
|
||||||
return lastFrameRate;
|
return x / base * base;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getFrameRate() {
|
std::string truncatePath(std::string pathname) {
|
||||||
return lastFrameRate;
|
return std::string(
|
||||||
|
std::find_if(
|
||||||
|
pathname.rbegin(),
|
||||||
|
pathname.rend(),
|
||||||
|
[](char ch) -> bool {
|
||||||
|
//windows only
|
||||||
|
return ch == '/' || ch == '\\';
|
||||||
|
// //unix only
|
||||||
|
// return ch == '/';
|
||||||
|
}).base(),
|
||||||
|
pathname.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_string_custom(int i) {
|
||||||
|
char buffer[20];
|
||||||
|
snprintf(buffer, 20, "%d", i);
|
||||||
|
return std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int to_integer_custom(std::string s) {
|
||||||
|
int ret = 0;
|
||||||
|
sscanf(s.c_str(), "%d", &ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -19,22 +19,30 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef INFORMATIONMANAGER_HPP_
|
#ifndef UTILITY_HPP_
|
||||||
#define INFORMATIONMANAGER_HPP_
|
#define UTILITY_HPP_
|
||||||
|
|
||||||
class InformationManager {
|
#include <string>
|
||||||
public:
|
|
||||||
int SetClientIndex(int i) { return clientIndex = i; }
|
|
||||||
int GetClientIndex() { return clientIndex; }
|
|
||||||
void ResetClientIndex() { clientIndex = -1; }
|
|
||||||
|
|
||||||
//one player at a time
|
int snapToBase(int base, int x);
|
||||||
int SetPlayerIndex(int i) { return playerIndex = i; }
|
std::string truncatePath(std::string pathname);
|
||||||
int GetPlayerIndex() { return playerIndex; }
|
|
||||||
void ResetPlayerIndex() { playerIndex = -1; }
|
//fixing known bugs in g++
|
||||||
private:
|
std::string to_string_custom(int i);
|
||||||
int clientIndex = -1;
|
|
||||||
int playerIndex = -1;
|
int to_integer_custom(std::string);
|
||||||
|
|
||||||
|
//wow
|
||||||
|
template<typename ContainerT, typename PredicateT>
|
||||||
|
void erase_if(ContainerT& items, const PredicateT& predicate) {
|
||||||
|
for(auto it = items.begin(); it != items.end(); /* empty */) {
|
||||||
|
if(predicate(*it)) {
|
||||||
|
it = items.erase(it);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -27,8 +27,13 @@
|
|||||||
|
|
||||||
class Vector2 {
|
class Vector2 {
|
||||||
public:
|
public:
|
||||||
double x = 0, y = 0;
|
double x, y;
|
||||||
|
|
||||||
|
//This is explicitly a POD
|
||||||
Vector2() = default;
|
Vector2() = default;
|
||||||
|
Vector2(double i, double j): x(i), y(j) {};
|
||||||
|
~Vector2() = default;
|
||||||
|
Vector2& operator=(Vector2 const&) = default;
|
||||||
|
|
||||||
double Length() const {
|
double Length() const {
|
||||||
return sqrt(x*x+y*y);
|
return sqrt(x*x+y*y);
|
||||||
@@ -89,7 +94,7 @@ public:
|
|||||||
bool operator==(Vector2 v) { return (x == v.x && y == v.y); }
|
bool operator==(Vector2 v) { return (x == v.x && y == v.y); }
|
||||||
bool operator!=(Vector2 v) { return (x != v.x || y != v.y); }
|
bool operator!=(Vector2 v) { return (x != v.x || y != v.y); }
|
||||||
|
|
||||||
//member templates
|
//member templates (curry the above operators)
|
||||||
template<typename T> Vector2 operator+=(T t) { return *this = *this + t; }
|
template<typename T> Vector2 operator+=(T t) { return *this = *this + t; }
|
||||||
template<typename T> Vector2 operator-=(T t) { return *this = *this - t; }
|
template<typename T> Vector2 operator-=(T t) { return *this = *this - t; }
|
||||||
template<typename T> Vector2 operator*=(T t) { return *this = *this * t; }
|
template<typename T> Vector2 operator*=(T t) { return *this = *this * t; }
|
||||||
@@ -98,7 +103,7 @@ public:
|
|||||||
template<typename T> bool operator!=(T t) { return (x != t || y != t); }
|
template<typename T> bool operator!=(T t) { return (x != t || y != t); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//non-member templates
|
//non-member templates (flip the order)
|
||||||
template<typename T> Vector2 operator+(T t, Vector2 v) { return v + t; }
|
template<typename T> Vector2 operator+(T t, Vector2 v) { return v + t; }
|
||||||
template<typename T> Vector2 operator-(T t, Vector2 v) { return v - t; }
|
template<typename T> Vector2 operator-(T t, Vector2 v) { return v - t; }
|
||||||
template<typename T> Vector2 operator*(T t, Vector2 v) { return v * t; }
|
template<typename T> Vector2 operator*(T t, Vector2 v) { return v * t; }
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "base_scene.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Static declarations
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
SDL_Surface* BaseScene::screen = nullptr;
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Public access members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
BaseScene::BaseScene() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseScene::~BaseScene() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Program control
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
SDL_Surface* BaseScene::SetScreen(int w, int h, int bpp, Uint32 flags) {
|
||||||
|
if (!bpp) {
|
||||||
|
bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
screen = SDL_SetVideoMode(w, h, bpp, flags);
|
||||||
|
|
||||||
|
if (!screen) {
|
||||||
|
throw(std::runtime_error("Failed to create the screen surface"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* BaseScene::GetScreen() {
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneList BaseScene::SetNextScene(SceneList sceneIndex) {
|
||||||
|
return nextScene = sceneIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneList BaseScene::GetNextScene() const {
|
||||||
|
return nextScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Frame loop
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void BaseScene::RunFrame(double delta) {
|
||||||
|
FrameStart();
|
||||||
|
HandleEvents();
|
||||||
|
Update(delta);
|
||||||
|
FrameEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseScene::RenderFrame() {
|
||||||
|
SDL_FillRect(screen, 0, 0);
|
||||||
|
Render(screen);
|
||||||
|
SDL_Flip(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Event handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void BaseScene::HandleEvents() {
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
while(SDL_PollEvent(&event)) {
|
||||||
|
switch(event.type) {
|
||||||
|
case SDL_QUIT:
|
||||||
|
QuitEvent();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_VIDEORESIZE:
|
||||||
|
SetScreen(event.resize.w, event.resize.h, 0, screen->flags);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
MouseMotion(event.motion);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
MouseButtonDown(event.button);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
MouseButtonUp(event.button);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
KeyDown(event.key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_KEYUP:
|
||||||
|
KeyUp(event.key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef USE_EVENT_JOYSTICK
|
||||||
|
//TODO: joystick/gamepad support
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_EVENT_UNKNOWN
|
||||||
|
default:
|
||||||
|
UnknownEvent(event);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}//switch
|
||||||
|
}//while
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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 BASESCENE_HPP_
|
||||||
|
#define BASESCENE_HPP_
|
||||||
|
|
||||||
|
#include "scene_list.hpp"
|
||||||
|
|
||||||
|
#include "SDL/SDL.h"
|
||||||
|
|
||||||
|
class BaseScene {
|
||||||
|
public:
|
||||||
|
//Public access members
|
||||||
|
BaseScene();
|
||||||
|
virtual ~BaseScene();
|
||||||
|
|
||||||
|
//Program control
|
||||||
|
static SDL_Surface* SetScreen(int w, int h, int bpp = 0, Uint32 flags = SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||||
|
static SDL_Surface* GetScreen();
|
||||||
|
|
||||||
|
SceneList SetNextScene(SceneList sceneIndex);
|
||||||
|
SceneList GetNextScene() const;
|
||||||
|
|
||||||
|
//Frame loop
|
||||||
|
virtual void RunFrame(double delta);
|
||||||
|
virtual void RenderFrame();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void FrameStart() {}
|
||||||
|
virtual void HandleEvents();
|
||||||
|
virtual void Update(double delta) {}
|
||||||
|
virtual void FrameEnd() {}
|
||||||
|
virtual void Render(SDL_Surface* const screen) {}
|
||||||
|
|
||||||
|
//Event handlers
|
||||||
|
virtual void QuitEvent() { SetNextScene(SceneList::QUIT); }
|
||||||
|
virtual void MouseMotion(SDL_MouseMotionEvent const&) {}
|
||||||
|
virtual void MouseButtonDown(SDL_MouseButtonEvent const&) {}
|
||||||
|
virtual void MouseButtonUp(SDL_MouseButtonEvent const&) {}
|
||||||
|
virtual void KeyDown(SDL_KeyboardEvent const&) {}
|
||||||
|
virtual void KeyUp(SDL_KeyboardEvent const&) {}
|
||||||
|
|
||||||
|
#ifdef USE_EVENT_JOYSTICK
|
||||||
|
//TODO: joystick/gamepad support
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_EVENT_UNKNOWN
|
||||||
|
virtual void UnknownEvent(SDL_Event const&) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
static SDL_Surface* screen;
|
||||||
|
SceneList nextScene = SceneList::CONTINUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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 EditorApplications, 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.
|
||||||
|
*/
|
||||||
|
#include "editor_application.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Static declarations
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
EditorApplication EditorApplication::instance;
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Scene headers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
//Add the custom scene headers here
|
||||||
|
#include "editor_scene.hpp"
|
||||||
|
#include "testificate_scene.hpp"
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Public access members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
EditorApplication::EditorApplication() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorApplication::~EditorApplication() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorApplication::Init() {
|
||||||
|
config.Load("rsc\\config.cfg");
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO))
|
||||||
|
throw(std::runtime_error("Failed to initialize SDL"));
|
||||||
|
|
||||||
|
BaseScene::SetScreen(config.Int("screen.w"), config.Int("screen.h"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorApplication::Proc() {
|
||||||
|
LoadScene(SceneList::FIRST);
|
||||||
|
|
||||||
|
//prepare the time system
|
||||||
|
typedef std::chrono::steady_clock Clock;
|
||||||
|
|
||||||
|
Clock::duration delta(16 * Clock::duration::period::den / std::milli::den);
|
||||||
|
Clock::time_point simTime = Clock::now();
|
||||||
|
Clock::time_point realTime;
|
||||||
|
|
||||||
|
//The main loop
|
||||||
|
while(activeScene->GetNextScene() != SceneList::QUIT) {
|
||||||
|
//switch scenes when necessary
|
||||||
|
if (activeScene->GetNextScene() != SceneList::CONTINUE) {
|
||||||
|
LoadScene(activeScene->GetNextScene());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//update the current time
|
||||||
|
realTime = Clock::now();
|
||||||
|
|
||||||
|
//simulate game time
|
||||||
|
while (simTime < realTime) {
|
||||||
|
//call each user defined function
|
||||||
|
activeScene->RunFrame(double(delta.count()) / Clock::duration::period::den);
|
||||||
|
simTime += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw the game to the screen
|
||||||
|
activeScene->RenderFrame();
|
||||||
|
|
||||||
|
//give the computer a break
|
||||||
|
SDL_Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnloadScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorApplication::Quit() {
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Private access members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void EditorApplication::LoadScene(SceneList sceneIndex) {
|
||||||
|
UnloadScene();
|
||||||
|
|
||||||
|
switch(sceneIndex) {
|
||||||
|
//add scene creation calls here
|
||||||
|
case SceneList::FIRST:
|
||||||
|
case SceneList::EDITORSCENE:
|
||||||
|
activeScene = new EditorScene(&config);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SceneList::TESTIFICATESCENE:
|
||||||
|
activeScene = new TestificateScene(&config);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw(std::logic_error("Failed to recognize the scene index"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorApplication::UnloadScene() {
|
||||||
|
delete activeScene;
|
||||||
|
activeScene = nullptr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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 EDITORAPPLICATION_HPP_
|
||||||
|
#define EDITORAPPLICATION_HPP_
|
||||||
|
|
||||||
|
#include "scene_list.hpp"
|
||||||
|
#include "base_scene.hpp"
|
||||||
|
#include "config_utility.hpp"
|
||||||
|
|
||||||
|
class EditorApplication {
|
||||||
|
private:
|
||||||
|
EditorApplication();
|
||||||
|
~EditorApplication();
|
||||||
|
static EditorApplication instance;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static EditorApplication* GetInstance() { return &instance; }
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Proc();
|
||||||
|
void Quit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
//Private access members
|
||||||
|
void LoadScene(SceneList sceneIndex);
|
||||||
|
void UnloadScene();
|
||||||
|
|
||||||
|
//globals
|
||||||
|
ConfigUtility config;
|
||||||
|
|
||||||
|
BaseScene* activeScene = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "editor_scene.hpp"
|
||||||
|
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Public access members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
EditorScene::EditorScene(ConfigUtility* const arg1):
|
||||||
|
config(*arg1)
|
||||||
|
{
|
||||||
|
//create the debugging "window"
|
||||||
|
debugInfo.CreateSurface(256, 256);
|
||||||
|
|
||||||
|
//setup the utility objects
|
||||||
|
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
|
||||||
|
|
||||||
|
buttonImage.LoadSurface(config["dir.interface"] + "button_menu.bmp");
|
||||||
|
buttonImage.SetClipH(buttonImage.GetClipH()/3);
|
||||||
|
|
||||||
|
//setup the menu bar
|
||||||
|
menuBar.SetFont(&font);
|
||||||
|
menuBar.SetImage(&buttonImage);
|
||||||
|
|
||||||
|
menuBar.SetEntries({
|
||||||
|
{"File", "New", "Open", "Save", "Close"},
|
||||||
|
{"Edit", "Set Tile", "Set Brush", "Script"},
|
||||||
|
{"Debug", "Debug On", "Debug Off", "Toggle", "Testificate"}
|
||||||
|
});
|
||||||
|
|
||||||
|
//setup the map
|
||||||
|
pager.SetRegionWidth(REGION_WIDTH);
|
||||||
|
pager.SetRegionHeight(REGION_HEIGHT);
|
||||||
|
pager.SetRegionDepth(REGION_DEPTH);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
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() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Frame loop
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void EditorScene::FrameStart() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::Update(double delta) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::FrameEnd() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::Render(SDL_Surface* const screen) {
|
||||||
|
tsheet.DrawRegionTo(screen, pager.GetRegion(0, 0), camera.x, camera.y);
|
||||||
|
/* //debug
|
||||||
|
for (int i = 0; i < pager.GetRegionWidth()*2; i++) {
|
||||||
|
for (int j = 0; j < pager.GetRegionHeight()*2; j++) {
|
||||||
|
for (int k = 0; k < pager.GetRegionDepth(); k++) {
|
||||||
|
//TODO: skip the out-of-bounds regions
|
||||||
|
tsheet.DrawTo(
|
||||||
|
screen,
|
||||||
|
i*tsheet.GetTileW()-camera.x,
|
||||||
|
j*tsheet.GetTileH()-camera.y,
|
||||||
|
pager.GetTile(i,j,k)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//draw a big bar across the top (hackish)
|
||||||
|
buttonImage.SetClipY(0);
|
||||||
|
for (int i = 0; i < screen->w; i += buttonImage.GetClipW()) {
|
||||||
|
buttonImage.DrawTo(screen, i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw the menu bar
|
||||||
|
menuBar.DrawTo(screen);
|
||||||
|
|
||||||
|
//draw some debugging info
|
||||||
|
if (debugOpen) {
|
||||||
|
SDL_FillRect(debugInfo.GetSurface(), 0, 0);
|
||||||
|
DrawToDebugInfo(string("camera.x: ") + to_string_custom(camera.x), 0);
|
||||||
|
DrawToDebugInfo(string("camera.y: ") + to_string_custom(camera.y), 1);
|
||||||
|
debugInfo.DrawTo(screen, screen->w - debugInfo.GetClipW(), buttonImage.GetClipH());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::DrawToDebugInfo(std::string str, int line) {
|
||||||
|
//draw the debug info on the right, with a grey background
|
||||||
|
SDL_Rect clip = {
|
||||||
|
Sint16(debugInfo.GetClipW() - str.size() * font.GetCharW()),
|
||||||
|
Sint16(font.GetCharH() * line),
|
||||||
|
Uint16(str.size() * font.GetCharW()),
|
||||||
|
Uint16(font.GetCharH())
|
||||||
|
};
|
||||||
|
SDL_FillRect(debugInfo.GetSurface(), &clip, SDL_MapRGB(debugInfo.GetSurface()->format, 64, 64, 64));
|
||||||
|
font.DrawStringTo(str, debugInfo.GetSurface(), clip.x, clip.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Event handlers
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void EditorScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
|
menuBar.MouseMotion(motion);
|
||||||
|
|
||||||
|
if (motion.state & SDL_BUTTON_RMASK) {
|
||||||
|
camera.x -= motion.xrel;
|
||||||
|
camera.y -= motion.yrel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
|
menuBar.MouseButtonDown(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
|
int entry, drop;
|
||||||
|
menuBar.MouseButtonUp(button, &entry, &drop);
|
||||||
|
HandleMenuOption(entry, drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::KeyDown(SDL_KeyboardEvent const& key) {
|
||||||
|
switch(key.keysym.sym) {
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
QuitEvent();
|
||||||
|
break;
|
||||||
|
case SDLK_SPACE:
|
||||||
|
camera.x = 0;
|
||||||
|
camera.y = 0;
|
||||||
|
break;
|
||||||
|
case SDLK_TAB:
|
||||||
|
debugOpen = !debugOpen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorScene::KeyUp(SDL_KeyboardEvent const& key) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
//Members
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
void EditorScene::HandleMenuOption(int entry, int drop) {
|
||||||
|
//manage input from the menu bar
|
||||||
|
switch(entry) {
|
||||||
|
case 0: //File
|
||||||
|
switch(drop) {
|
||||||
|
case 0:
|
||||||
|
//TODO: NEW
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//TODO: OPEN
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//TODO: SAVE
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
//TODO: CLOSE
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: //Edit
|
||||||
|
switch(drop) {
|
||||||
|
case 0:
|
||||||
|
//TODO: SET TILE
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
//TODO: SET BRUSH
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
//TODO: SCRIPT
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: //Debug
|
||||||
|
switch(drop) {
|
||||||
|
case 0:
|
||||||
|
debugOpen = true;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
debugOpen = false;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
debugOpen = !debugOpen;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
SetNextScene(SceneList::TESTIFICATESCENE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/* Copyright: (c) Kayne Ruse 2013
|
||||||
|
*
|
||||||
|
* 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 EDITORSCENE_HPP_
|
||||||
|
#define EDITORSCENE_HPP_
|
||||||
|
|
||||||
|
#include "base_scene.hpp"
|
||||||
|
|
||||||
|
#include "config_utility.hpp"
|
||||||
|
#include "image.hpp"
|
||||||
|
#include "raster_font.hpp"
|
||||||
|
#include "menu_bar.hpp"
|
||||||
|
|
||||||
|
#include "region_pager.hpp"
|
||||||
|
#include "map_generator.hpp"
|
||||||
|
#include "map_file_format.hpp"
|
||||||
|
#include "tile_sheet.hpp"
|
||||||
|
|
||||||
|
class EditorScene : public BaseScene {
|
||||||
|
public:
|
||||||
|
//Public access members
|
||||||
|
EditorScene(ConfigUtility* const);
|
||||||
|
~EditorScene();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//Frame loop
|
||||||
|
void FrameStart();
|
||||||
|
void Update(double delta);
|
||||||
|
void FrameEnd();
|
||||||
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
|
//Event handlers
|
||||||
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
|
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
|
//members
|
||||||
|
void HandleMenuOption(int entry, int drop);
|
||||||
|
|
||||||
|
//globals
|
||||||
|
ConfigUtility& config;
|
||||||
|
|
||||||
|
//debugging tools
|
||||||
|
void DrawToDebugInfo(std::string, int line);
|
||||||
|
Image debugInfo;
|
||||||
|
bool debugOpen = true;
|
||||||
|
|
||||||
|
RasterFont font;
|
||||||
|
Image buttonImage;
|
||||||
|
MenuBar menuBar;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int x = 0, y = 0;
|
||||||
|
} camera;
|
||||||
|
|
||||||
|
RegionPager<BlankGenerator, DummyFormat> pager;
|
||||||
|
TileSheet tsheet;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -19,16 +19,24 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef NETWORKQUEUE_HPP_
|
#include "editor_application.hpp"
|
||||||
#define NETWORKQUEUE_HPP_
|
|
||||||
|
|
||||||
#include "packet.hpp"
|
#include <stdexcept>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
void beginQueueThread();
|
using namespace std;
|
||||||
void endQueueThread();
|
|
||||||
void killQueueThread();
|
|
||||||
Packet peekNetworkPacket();
|
|
||||||
Packet popNetworkPacket();
|
|
||||||
void flushNetworkQueue();
|
|
||||||
|
|
||||||
#endif
|
int main(int, char**) {
|
||||||
|
cout << "Beginning editor" << endl;
|
||||||
|
try {
|
||||||
|
EditorApplication::GetInstance()->Init();
|
||||||
|
EditorApplication::GetInstance()->Proc();
|
||||||
|
EditorApplication::GetInstance()->Quit();
|
||||||
|
}
|
||||||
|
catch(exception& e) {
|
||||||
|
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cout << "Clean exit" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#config
|
||||||
|
INCLUDES+=../common ../common/graphics ../common/map ../common/ui
|
||||||
|
LIBS+=../libcommon.a -lmingw32 -lSDLmain -lSDL -llua
|
||||||
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
|
#source
|
||||||
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
|
#objects
|
||||||
|
OBJDIR=obj
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
|
#output
|
||||||
|
OUTDIR=../out
|
||||||
|
OUT=$(addprefix $(OUTDIR)/,editor)
|
||||||
|
|
||||||
|
#targets
|
||||||
|
all: $(OBJ) $(OUT)
|
||||||
|
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||||
|
|
||||||
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUT): | $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(OUTDIR):
|
||||||
|
mkdir $(OUTDIR)
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
rebuild: clean all
|
||||||
@@ -19,16 +19,18 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef DEFINES_HPP_
|
#ifndef SCENELIST_HPP_
|
||||||
#define DEFINES_HPP_
|
#define SCENELIST_HPP_
|
||||||
|
|
||||||
#define GAME_CHANNEL 0
|
enum class SceneList {
|
||||||
#define CHAT_CHANNEL 1
|
//these are reserved
|
||||||
|
QUIT,
|
||||||
|
CONTINUE,
|
||||||
|
FIRST,
|
||||||
|
|
||||||
#define WALKING_SPEED 140
|
//custom indexes
|
||||||
|
TESTIFICATESCENE,
|
||||||
enum class CardinalDirection {
|
EDITORSCENE,
|
||||||
NORTH, SOUTH, EAST, WEST
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -19,59 +19,73 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#include "option_screen.hpp"
|
#include "testificate_scene.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Public access members
|
//Public access members
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
OptionScreen::OptionScreen() {
|
TestificateScene::TestificateScene(ConfigUtility* const arg1):
|
||||||
#ifdef DEBUG
|
config(*arg1)
|
||||||
cout << "entering OptionScreen" << endl;
|
{
|
||||||
#endif
|
//
|
||||||
backButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Back");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionScreen::~OptionScreen() {
|
TestificateScene::~TestificateScene() {
|
||||||
#ifdef DEBUG
|
//
|
||||||
cout << "leaving OptionScreen" << endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Frame loop
|
//Frame loop
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
void OptionScreen::Render(SDL_Surface* const screen) {
|
void TestificateScene::FrameStart() {
|
||||||
backButton.DrawTo(screen);
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestificateScene::Update(double delta) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestificateScene::FrameEnd() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestificateScene::Render(SDL_Surface* const screen) {
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Event handlers
|
//Event handlers
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
void OptionScreen::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
void TestificateScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||||
backButton.MouseMotion(motion);
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionScreen::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
|
||||||
backButton.MouseButtonDown(button);
|
void TestificateScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionScreen::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
void TestificateScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||||
if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
|
//
|
||||||
SetNextScene(SceneList::MAINMENU);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OptionScreen::KeyDown(SDL_KeyboardEvent const& key) {
|
void TestificateScene::KeyDown(SDL_KeyboardEvent const& key) {
|
||||||
switch(key.keysym.sym) {
|
switch(key.keysym.sym) {
|
||||||
case SDLK_ESCAPE:
|
case SDLK_ESCAPE:
|
||||||
SetNextScene(SceneList::MAINMENU);
|
// QuitEvent();
|
||||||
|
SetNextScene(SceneList::EDITORSCENE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestificateScene::KeyUp(SDL_KeyboardEvent const& key) {
|
||||||
|
//
|
||||||
|
}
|
||||||
@@ -19,33 +19,35 @@
|
|||||||
* 3. This notice may not be removed or altered from any source
|
* 3. This notice may not be removed or altered from any source
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
#ifndef OPTIONSCREEN_HPP_
|
#ifndef TESTIFICATESCENE_HPP_
|
||||||
#define OPTIONSCREEN_HPP_
|
#define TESTIFICATESCENE_HPP_
|
||||||
|
|
||||||
#include "base_scene.hpp"
|
#include "base_scene.hpp"
|
||||||
#include "singleton.hpp"
|
|
||||||
|
|
||||||
#include "surface_manager.hpp"
|
#include "config_utility.hpp"
|
||||||
#include "button.hpp"
|
|
||||||
|
|
||||||
class OptionScreen : public BaseScene {
|
class TestificateScene : public BaseScene {
|
||||||
public:
|
public:
|
||||||
/* Public access members */
|
//Public access members
|
||||||
OptionScreen();
|
TestificateScene(ConfigUtility* const);
|
||||||
~OptionScreen();
|
~TestificateScene();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Frame loop */
|
//Frame loop
|
||||||
|
void FrameStart();
|
||||||
|
void Update(double delta);
|
||||||
|
void FrameEnd();
|
||||||
void Render(SDL_Surface* const);
|
void Render(SDL_Surface* const);
|
||||||
|
|
||||||
/* Event handlers */
|
//Event handlers
|
||||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||||
void KeyDown(SDL_KeyboardEvent const&);
|
void KeyDown(SDL_KeyboardEvent const&);
|
||||||
|
void KeyUp(SDL_KeyboardEvent const&);
|
||||||
|
|
||||||
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get();
|
//globals
|
||||||
Button backButton;
|
ConfigUtility& config;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
LIBDIR=lib
|
#for use on Windows:
|
||||||
|
|
||||||
|
#MKDIR=mkdir
|
||||||
|
#RM=del /y
|
||||||
|
|
||||||
|
CXXFLAGS+=-static-libgcc -static-libstdc++
|
||||||
|
CFLAGS+=-static-libgcc
|
||||||
|
|
||||||
|
export
|
||||||
|
|
||||||
OUTDIR=out
|
OUTDIR=out
|
||||||
|
|
||||||
all: $(LIBDIR) $(OUTDIR)
|
all: $(OUTDIR)
|
||||||
$(MAKE) -C common
|
$(MAKE) -C common
|
||||||
$(MAKE) -C server
|
$(MAKE) -C server
|
||||||
$(MAKE) -C client
|
$(MAKE) -C client
|
||||||
$(MAKE) -C test
|
$(MAKE) -C editor
|
||||||
|
|
||||||
$(LIBDIR):
|
|
||||||
mkdir $(LIBDIR)
|
|
||||||
|
|
||||||
$(OUTDIR):
|
$(OUTDIR):
|
||||||
mkdir $(OUTDIR)
|
mkdir $(OUTDIR)
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
#configuration of the programs
|
#configuration of the programs
|
||||||
server.host = 127.0.0.1
|
server.host = 255.255.255.255
|
||||||
server.port = 1991
|
server.port = 21795
|
||||||
server.name = foobar
|
server.name = local
|
||||||
|
|
||||||
|
server.dbname = database.db
|
||||||
|
|
||||||
screen.w = 800
|
screen.w = 800
|
||||||
screen.h = 600
|
screen.h = 600
|
||||||
screen.f = false
|
screen.f = false
|
||||||
|
|
||||||
#directories
|
#directories
|
||||||
fonts = rsc/graphics/fonts
|
dir.fonts = rsc/graphics/fonts/
|
||||||
logos = rsc/graphics/logos
|
dir.logos = rsc/graphics/logos/
|
||||||
sprites = rsc/graphics/sprites
|
dir.sprites = rsc/graphics/sprites/
|
||||||
tilesets = rsc/graphics/tilesets
|
dir.tilesets = rsc/graphics/tilesets/
|
||||||
interface = rsc/graphics/interface
|
dir.interface = rsc/graphics/interface/
|
||||||
|
dir.scripts = rsc/scripts/
|
||||||
|
|
||||||
|
#map system
|
||||||
|
map.pager.width = 20
|
||||||
|
map.pager.height = 20
|
||||||
|
map.pager.depth = 3
|
||||||
|
|
||||||
|
#player options
|
||||||
|
player.handle = username
|
||||||
|
player.avatar = elliot2.bmp
|
||||||
|
|
||||||
#debugging
|
#debugging
|
||||||
debug = true
|
|
||||||
avatar = elliot
|
|
||||||
handle = UserName
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 108 KiB |
@@ -0,0 +1,29 @@
|
|||||||
|
print("Lua script check OK (./rsc)")
|
||||||
|
|
||||||
|
function Region.Create(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
|
||||||
|
|
||||||
|
function Region.Unload(r)
|
||||||
|
print("Region:Unload(r", Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
end
|
||||||
|
|
||||||
|
--return true if file loaded, otherwise return false
|
||||||
|
function Region.Load(r, saveDir)
|
||||||
|
print("Region:Load(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function Region.Save(r, saveDir)
|
||||||
|
print("Region:Save(r,", saveDir, Region.GetX(r), Region.GetY(r), ")")
|
||||||
|
end
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
-------------------------
|
||||||
|
--Server
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS UserAccounts (
|
||||||
|
userAccountID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
username varchar(30) UNIQUE,
|
||||||
|
password varchar(30),
|
||||||
|
blacklisted BIT DEFAULT 0,
|
||||||
|
whitelisted BIT DEFAULT 1
|
||||||
|
);
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
--Items
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS GlobalItemList (
|
||||||
|
globalItemListID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
itemName varchar(30) UNIQUE,
|
||||||
|
itemImage varchar(30),
|
||||||
|
type varchar(15), --{'mundane', 'consumable', 'equipment'}
|
||||||
|
maxStackSize INTEGER, --{1-max; 0 for non-stackable}
|
||||||
|
maxUniqueCopies INTEGER --{1-max; 0 for unlimited}
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS MundaneItems (
|
||||||
|
mundaneItemID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||||
|
--holds whatever
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS Consumables (
|
||||||
|
consumableID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||||
|
--holds all consumable items info (food, potions, etc.)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS Equipment (
|
||||||
|
equipmentID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||||
|
--hold all equipment info
|
||||||
|
);
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
--Players
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS PlayerCharacters (
|
||||||
|
playerCharacterID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name varchar(30) UNIQUE,
|
||||||
|
|
||||||
|
--stats
|
||||||
|
currentLevel INTEGER DEFAULT 0,
|
||||||
|
currentExperience INTEGER DEFAULT 0,
|
||||||
|
maxHealth INTEGER DEFAULT 0,
|
||||||
|
maxMana INTEGER DEFAULT 0,
|
||||||
|
currentHealth INTEGER DEFAULT 0,
|
||||||
|
currentMana INTEGER DEFAULT 0,
|
||||||
|
attack INTEGER DEFAULT 0,
|
||||||
|
defence INTEGER DEFAULT 0,
|
||||||
|
--etc.
|
||||||
|
|
||||||
|
--equipment
|
||||||
|
weapon INTEGER REFERENCES Equipment(equipmentID),
|
||||||
|
helmet INTEGER REFERENCES Equipment(equipmentID),
|
||||||
|
armour INTEGER REFERENCES Equipment(equipmentID)
|
||||||
|
--etc.
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS PlayerInventoryItems (
|
||||||
|
characterID INTEGER REFERENCES PlayerCharacters(characterID),
|
||||||
|
globalItemListID INTEGER REFERENCES GlobalItemList(globalItemListID)
|
||||||
|
);
|
||||||
@@ -21,27 +21,25 @@
|
|||||||
*/
|
*/
|
||||||
#include "server_application.hpp"
|
#include "server_application.hpp"
|
||||||
|
|
||||||
|
#include "SDL/SDL.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int main(int, char**) {
|
int main(int argc, char** argv) {
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "Beginning server" << endl;
|
cout << "Beginning server" << endl;
|
||||||
#endif
|
|
||||||
try {
|
try {
|
||||||
ServerApplication app;
|
ServerApplication app;
|
||||||
app.Init();
|
app.Init(argc, argv);
|
||||||
app.Proc();
|
app.Loop();
|
||||||
app.Quit();
|
app.Quit();
|
||||||
}
|
}
|
||||||
catch(exception& e) {
|
catch(exception& e) {
|
||||||
cerr << "Fatal error: " << e.what() << endl;
|
cerr << "Fatal error: " << e.what() << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
cout << "Clean exit" << endl;
|
cout << "Clean exit" << endl;
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
#config
|
#config
|
||||||
LOCALLIBS=../lib/libCommon.a
|
INCLUDES+=. ../common ../common/map ../common/script ../common/network
|
||||||
LIB=$(LOCALLIBS) -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL
|
LIBS+=../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
|
||||||
INCLUDES=../common
|
|
||||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
|
||||||
|
|
||||||
#source
|
#source
|
||||||
SRC=$(wildcard *.cpp)
|
CXXSRC=$(wildcard *.cpp)
|
||||||
|
CSRC=$(wildcard *.c)
|
||||||
|
|
||||||
#objects
|
#objects
|
||||||
OBJDIR=obj
|
OBJDIR=obj
|
||||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
|
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||||
|
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
|
||||||
|
|
||||||
#output
|
#output
|
||||||
OUTDIR=../out
|
OUTDIR=../out
|
||||||
@@ -17,7 +19,7 @@ OUT=$(addprefix $(OUTDIR)/,server)
|
|||||||
|
|
||||||
#targets
|
#targets
|
||||||
all: $(OBJ) $(OUT)
|
all: $(OBJ) $(OUT)
|
||||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
|
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||||
|
|
||||||
$(OBJ): | $(OBJDIR)
|
$(OBJ): | $(OBJDIR)
|
||||||
|
|
||||||
@@ -32,6 +34,9 @@ $(OUTDIR):
|
|||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) *.o *.a *.exe
|
$(RM) *.o *.a *.exe
|
||||||
|
|
||||||
|
|||||||
@@ -21,298 +21,341 @@
|
|||||||
*/
|
*/
|
||||||
#include "server_application.hpp"
|
#include "server_application.hpp"
|
||||||
|
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <chrono>
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
//-------------------------
|
int runSQLScript(sqlite3* db, std::string fname) {
|
||||||
//Quick and dirty
|
ifstream is(fname);
|
||||||
//-------------------------
|
if (!is.is_open()) {
|
||||||
|
return -1;
|
||||||
static std::string itos(int i) {
|
}
|
||||||
char buffer[20];
|
string script;
|
||||||
snprintf(buffer, 20, "%d", i);
|
getline(is, script, '\0');
|
||||||
return std::string(buffer);
|
is.close();
|
||||||
|
//TODO: flesh out this error if needed
|
||||||
|
if (sqlite3_exec(db, script.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Public access members
|
//Define the public members
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
ServerApplication::ServerApplication() {
|
void ServerApplication::Init(int argc, char** argv) {
|
||||||
//
|
cout << "Beginning startup" << endl;
|
||||||
}
|
int ret = 0;
|
||||||
|
|
||||||
ServerApplication::~ServerApplication() {
|
//load config
|
||||||
//
|
config.Load("rsc\\config.cfg");
|
||||||
}
|
|
||||||
|
|
||||||
/* ServerApplication::Init()
|
//Init SDL
|
||||||
* This function initializes the entire program. There are a number of things
|
if (SDL_Init(0)) {
|
||||||
* that could go wrong here, which is why there is such an unusual order of
|
throw(runtime_error("Failed to initialize SDL"));
|
||||||
* operations.
|
|
||||||
* Important things to note:
|
|
||||||
* The APIs are initiated here.
|
|
||||||
* The global objects are initialized here.
|
|
||||||
* The ConfigUtility's call to Load() also ensures that the "rsc\" folder is in the directory. It's easy to forget it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ServerApplication::Init() {
|
|
||||||
//load the config file
|
|
||||||
try {
|
|
||||||
configUtil->Load("rsc/config.cfg");
|
|
||||||
}
|
|
||||||
catch(std::runtime_error& e) {
|
|
||||||
std::string s = e.what();
|
|
||||||
s += "; Ensure that the \"rsc\" directory is present";
|
|
||||||
throw(std::runtime_error(s));
|
|
||||||
}
|
}
|
||||||
|
cout << "Initialized SDL" << endl;
|
||||||
|
|
||||||
//check the port is valid
|
//Init SDL_net
|
||||||
if (configUtil->Int("server.port") <= 0) {
|
|
||||||
throw(runtime_error("Cannot open the server on an invalid port or port 0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//initialize the APIs
|
|
||||||
if (SDLNet_Init()) {
|
if (SDLNet_Init()) {
|
||||||
throw(runtime_error("Failed to initialize SDL_net"));
|
throw(runtime_error("Failed to initialize SDL_net"));
|
||||||
}
|
}
|
||||||
|
network.Open(config.Int("server.port"), PACKET_BUFFER_SIZE);
|
||||||
|
cout << "Initialized SDL_net" << endl;
|
||||||
|
|
||||||
//initiate the remaining singletons
|
//Init SQL
|
||||||
netUtil->Open(configUtil->Int("server.port"), sizeof(Packet));
|
ret = sqlite3_open_v2(config["server.dbname"].c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, nullptr);
|
||||||
|
if (ret != SQLITE_OK || !database) {
|
||||||
|
throw(runtime_error(string() + "Failed to initialize SQL: " + sqlite3_errmsg(database) ));
|
||||||
|
}
|
||||||
|
cout << "Initialized SQL" << endl;
|
||||||
|
|
||||||
//create the threads
|
//setup the database
|
||||||
beginQueueThread();
|
if (runSQLScript(database, config["dir.scripts"] + "setup_server.sql")) {
|
||||||
|
throw(runtime_error("Failed to initialize SQL's setup script"));
|
||||||
|
}
|
||||||
|
cout << "Initialized SQL's setup script" << endl;
|
||||||
|
|
||||||
//output the server information
|
//lua
|
||||||
cout << configUtil->String("server.name") << endl;
|
luaState = luaL_newstate();
|
||||||
cout << "Open on port " << configUtil->String("server.port") << endl;
|
if (!luaState) {
|
||||||
|
throw(runtime_error("Failed to initialize lua"));
|
||||||
|
}
|
||||||
|
luaL_openlibs(luaState);
|
||||||
|
cout << "Initialized lua" << endl;
|
||||||
|
|
||||||
//disable this for debugging
|
//run the startup script
|
||||||
running = true;
|
if (luaL_dofile(luaState, (config["dir.scripts"] + "setup_server.lua").c_str())) {
|
||||||
|
throw(runtime_error(string() + "Failed to initialize lua's setup script: " + lua_tostring(luaState, -1) ));
|
||||||
|
}
|
||||||
|
cout << "Initialized lua's setup script" << endl;
|
||||||
|
|
||||||
|
//setup the map object
|
||||||
|
mapPager.SetRegionWidth(REGION_WIDTH);
|
||||||
|
mapPager.SetRegionHeight(REGION_HEIGHT);
|
||||||
|
mapPager.SetRegionDepth(REGION_DEPTH);
|
||||||
|
mapPager.GetGenerator()->SetLuaState(luaState);
|
||||||
|
mapPager.GetFormat()->SetLuaState(luaState);
|
||||||
|
mapPager.GetFormat()->SetSaveDir("save/mapname/");
|
||||||
|
//TODO: pass args to the generator & format as needed
|
||||||
|
//NOTE: I might need to rearrange the init process so that lua & SQL can interact
|
||||||
|
// with the map system as needed.
|
||||||
|
cout << "Initialized the map system" << endl;
|
||||||
|
cout << "\tsizeof(NetworkPacket): " << sizeof(NetworkPacket) << endl;
|
||||||
|
cout << "\tPACKET_BUFFER_SIZE: " << PACKET_BUFFER_SIZE << endl;
|
||||||
|
|
||||||
|
//finalize the startup
|
||||||
|
cout << "Startup completed successfully" << endl;
|
||||||
|
|
||||||
|
//debugging
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::Proc() {
|
void ServerApplication::Loop() {
|
||||||
typedef chrono::high_resolution_clock Clock;
|
NetworkPacket packet;
|
||||||
|
|
||||||
Clock::time_point lastTick = Clock::now();
|
|
||||||
Clock::duration delta;
|
|
||||||
|
|
||||||
while(running) {
|
while(running) {
|
||||||
try {
|
//suck in the waiting packets & process them
|
||||||
//process all packets on the network queue
|
while(network.Receive()) {
|
||||||
while(HandlePacket(popNetworkPacket()));
|
//get the packet
|
||||||
|
deserialize(&packet, network.GetInData());
|
||||||
|
//cache the source address
|
||||||
|
packet.meta.srcAddress = network.GetInPacket()->address;
|
||||||
|
//we need to go deeper
|
||||||
|
HandlePacket(packet);
|
||||||
}
|
}
|
||||||
catch(exception& e) {
|
//give the computer a break
|
||||||
//handle any errors
|
|
||||||
cerr << "Network Error: " << e.what() << endl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get the time since last update
|
|
||||||
delta = Clock::now() - lastTick;
|
|
||||||
lastTick = Clock::now();
|
|
||||||
|
|
||||||
//update the world
|
|
||||||
UpdateWorld(double(delta.count()) / Clock::duration::period::den);
|
|
||||||
|
|
||||||
//give the machine a break
|
|
||||||
SDL_Delay(10);
|
SDL_Delay(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::Quit() {
|
void ServerApplication::Quit() {
|
||||||
//close the threads
|
cout << "Shutting down" << endl;
|
||||||
endQueueThread();
|
//empty the members
|
||||||
|
mapPager.UnloadAll();
|
||||||
|
//TODO: player manager
|
||||||
|
//TODO: client manager
|
||||||
|
|
||||||
//clean up the singletons
|
//APIs
|
||||||
netUtil->Close();
|
lua_close(luaState);
|
||||||
|
sqlite3_close_v2(database);
|
||||||
//deinitialize the APIs
|
network.Close();
|
||||||
SDLNet_Quit();
|
SDLNet_Quit();
|
||||||
|
SDL_Quit();
|
||||||
|
cout << "Shutdown finished" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------
|
//-------------------------
|
||||||
//Game loop
|
//Define the uber switch
|
||||||
//-------------------------
|
//-------------------------
|
||||||
|
|
||||||
void ServerApplication::UpdateWorld(double delta) {
|
void ServerApplication::HandlePacket(NetworkPacket packet) {
|
||||||
//the recalc here each loop is a stopgap, see issue #9 for details
|
switch(packet.meta.type) {
|
||||||
for (auto& it : players) {
|
case NetworkPacket::Type::BROADCAST_REQUEST:
|
||||||
if (it.second.motion.x != 0 && it.second.motion.y != 0) {
|
HandleBroadcastRequest(packet);
|
||||||
constexpr double d = 1.0/sqrt(2);
|
|
||||||
it.second.position += it.second.motion * delta * d;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
it.second.position += it.second.motion * delta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
//Network loop
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
int ServerApplication::HandlePacket(Packet p) {
|
|
||||||
switch(p.meta.type) {
|
|
||||||
case Packet::Type::NONE:
|
|
||||||
//DO NOTHING
|
|
||||||
return 0;
|
|
||||||
break;
|
break;
|
||||||
case Packet::Type::PING:
|
case NetworkPacket::Type::JOIN_REQUEST:
|
||||||
//quick pong
|
HandleJoinRequest(packet);
|
||||||
p.meta.type = Packet::Type::PONG;
|
|
||||||
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
|
|
||||||
break;
|
break;
|
||||||
case Packet::Type::PONG:
|
case NetworkPacket::Type::DISCONNECT:
|
||||||
//
|
HandleDisconnect(packet);
|
||||||
break;
|
break;
|
||||||
case Packet::Type::BROADCAST_REQUEST:
|
case NetworkPacket::Type::SYNCHRONIZE:
|
||||||
HandleBroadcast(p);
|
HandleSynchronize(packet);
|
||||||
break;
|
break;
|
||||||
// case PacketType::BROADCAST_RESPONSE:
|
case NetworkPacket::Type::SHUTDOWN:
|
||||||
// //
|
HandleShutdown(packet);
|
||||||
// break;
|
|
||||||
case Packet::Type::JOIN_REQUEST:
|
|
||||||
HandleConnection(p);
|
|
||||||
break;
|
break;
|
||||||
// case PacketType::JOIN_RESPONSE:
|
case NetworkPacket::Type::PLAYER_NEW:
|
||||||
// //
|
HandlePlayerNew(packet);
|
||||||
// break;
|
|
||||||
case Packet::Type::DISCONNECT:
|
|
||||||
HandleDisconnection(p);
|
|
||||||
break;
|
break;
|
||||||
case Packet::Type::SYNCHRONIZE:
|
case NetworkPacket::Type::PLAYER_DELETE:
|
||||||
SynchronizeEverything(p);
|
HandlePlayerDelete(packet);
|
||||||
break;
|
break;
|
||||||
case Packet::Type::PLAYER_NEW:
|
case NetworkPacket::Type::PLAYER_UPDATE:
|
||||||
AddPlayer(p);
|
HandlePlayerUpdate(packet);
|
||||||
RelayPacket(p);
|
|
||||||
break;
|
break;
|
||||||
case Packet::Type::PLAYER_DELETE:
|
case NetworkPacket::Type::REGION_REQUEST:
|
||||||
RemovePlayer(p);
|
HandleRegionRequest(packet);
|
||||||
RelayPacket(p);
|
|
||||||
break;
|
|
||||||
case Packet::Type::PLAYER_UPDATE:
|
|
||||||
UpdatePlayer(p);
|
|
||||||
RelayPacket(p);
|
|
||||||
break;
|
break;
|
||||||
|
//handle errors
|
||||||
default:
|
default:
|
||||||
throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type))));
|
throw(runtime_error("Unknown NetworkPacket::Type encountered"));
|
||||||
}
|
break;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerApplication::RelayPacket(Packet& p) {
|
|
||||||
//pump this packet to all clients
|
|
||||||
for (auto& it : clients) {
|
|
||||||
netUtil->Send(&it.second.address, &p, sizeof(Packet));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::SynchronizeEverything(Packet& sync) {
|
//-------------------------
|
||||||
//send all known data to this client
|
//Handle various network input
|
||||||
//TODO multithreading?
|
//-------------------------
|
||||||
|
|
||||||
//all players
|
void ServerApplication::HandleBroadcastRequest(NetworkPacket packet) {
|
||||||
Packet p;
|
//send back the server's metadata
|
||||||
p.meta.type = Packet::Type::PLAYER_UPDATE;
|
packet.meta.type = NetworkPacket::Type::BROADCAST_RESPONSE;
|
||||||
for (auto& it : players) {
|
//TODO: version info
|
||||||
p.meta.clientIndex = it.second.clientIndex;
|
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
|
||||||
|
//TODO: player count
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
p.playerInfo.index = it.second.index;
|
void ServerApplication::HandleJoinRequest(NetworkPacket packet) {
|
||||||
snprintf(p.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
|
//register the new client
|
||||||
snprintf(p.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
ClientEntry c;
|
||||||
p.playerInfo.position = it.second.position;
|
c.address = packet.meta.srcAddress;
|
||||||
p.playerInfo.motion = it.second.motion;
|
clientMap[clientCounter] = c;
|
||||||
|
|
||||||
netUtil->Send(&clients[sync.meta.clientIndex].address, &p, sizeof(Packet));
|
//send the client their info
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE;
|
||||||
|
packet.clientInfo.index = clientCounter;
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
|
||||||
|
network.Send(&clientMap[clientCounter].address, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
|
||||||
|
//finished this routine
|
||||||
|
clientCounter++;
|
||||||
|
cout << "Connect, total: " << clientMap.size() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerApplication::HandleDisconnect(NetworkPacket packet) {
|
||||||
|
//disconnect the specified client
|
||||||
|
//TODO: authenticate who is disconnecting/kicking
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
||||||
|
clientMap.erase(packet.clientInfo.index);
|
||||||
|
|
||||||
|
//delete players from all clients
|
||||||
|
NetworkPacket delPacket;
|
||||||
|
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
||||||
|
|
||||||
|
erase_if(playerMap, [&](std::pair<int, PlayerEntry> it) -> bool {
|
||||||
|
//find the internal players to delete
|
||||||
|
if (it.second.clientIndex == packet.clientInfo.index) {
|
||||||
|
delPacket.playerInfo.playerIndex = it.first;
|
||||||
|
//send the delete player command to all clients
|
||||||
|
PumpPacket(delPacket);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
//finished this routine
|
||||||
|
cout << "Disconnect, total: " << clientMap.size() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerApplication::HandleSynchronize(NetworkPacket packet) {
|
||||||
|
//send all the server's data to this client
|
||||||
|
//TODO: compensate for large distances
|
||||||
|
NetworkPacket newPacket;
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
//players
|
||||||
|
newPacket.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
|
||||||
|
for (auto& it : playerMap) {
|
||||||
|
newPacket.playerInfo.playerIndex = it.first;
|
||||||
|
snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
|
||||||
|
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
|
||||||
|
newPacket.playerInfo.position = it.second.position;
|
||||||
|
newPacket.playerInfo.motion = it.second.motion;
|
||||||
|
serialize(&newPacket, buffer);
|
||||||
|
network.Send(&clientMap[packet.clientInfo.index].address, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleBroadcast(Packet& bcast) {
|
void ServerApplication::HandleShutdown(NetworkPacket packet) {
|
||||||
//respond to a broadcast request with the server's data
|
//end the server
|
||||||
Packet p;
|
running = false;
|
||||||
p.meta.type = Packet::Type::BROADCAST_RESPONSE;
|
|
||||||
snprintf(p.serverInfo.name, PACKET_STRING_SIZE, "%s", configUtil->CString("server.name"));
|
//disconnect all clients
|
||||||
//TODO version information
|
packet.meta.type = NetworkPacket::Type::DISCONNECT;
|
||||||
netUtil->Send(&bcast.meta.address, &p, sizeof(Packet));
|
PumpPacket(packet);
|
||||||
|
|
||||||
|
//finished this routine
|
||||||
|
cout << "Shutdown signal accepted" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleConnection(Packet& request) {
|
void ServerApplication::HandlePlayerNew(NetworkPacket packet) {
|
||||||
//create the entries
|
//create the new player object
|
||||||
ClientEntry newClient = {
|
PlayerEntry newPlayer;
|
||||||
uniqueIndex++,
|
newPlayer.clientIndex = packet.playerInfo.clientIndex;
|
||||||
request.meta.address
|
newPlayer.mapIndex = 0;
|
||||||
};
|
newPlayer.handle = packet.playerInfo.handle;
|
||||||
|
newPlayer.avatar = packet.playerInfo.avatar;
|
||||||
|
newPlayer.position = {0,0};
|
||||||
|
newPlayer.motion = {0,0};
|
||||||
|
|
||||||
//push this information
|
//push this player
|
||||||
clients[newClient.index] = newClient;
|
playerMap[playerCounter] = newPlayer;
|
||||||
|
|
||||||
//send the player their information
|
//send the client their info
|
||||||
Packet p;
|
packet.playerInfo.playerIndex = playerCounter;
|
||||||
p.meta.type = Packet::Type::JOIN_RESPONSE;
|
packet.playerInfo.position = playerMap[playerCounter].position;
|
||||||
p.meta.clientIndex = newClient.index;
|
packet.playerInfo.motion = playerMap[playerCounter].motion;
|
||||||
|
|
||||||
//TODO: resource list
|
//actually send to everyone
|
||||||
|
PumpPacket(packet);
|
||||||
|
|
||||||
netUtil->Send(&newClient.address, &p, sizeof(Packet));
|
//finish this routine
|
||||||
|
playerCounter++;
|
||||||
//debugging
|
|
||||||
cout << "New connection: index " << newClient.index << endl;
|
|
||||||
cout << "number of clients: " << clients.size() << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::HandleDisconnection(Packet& disconnect) {
|
void ServerApplication::HandlePlayerDelete(NetworkPacket packet) {
|
||||||
//disconnect a client (redundant message)
|
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
|
||||||
netUtil->Send(&clients[disconnect.meta.clientIndex].address, &disconnect, sizeof(Packet));
|
throw(std::runtime_error("Cannot delete a non-existant player"));
|
||||||
clients.erase(disconnect.meta.clientIndex);
|
|
||||||
|
|
||||||
//TODO remove the player...
|
|
||||||
//remove if(...)
|
|
||||||
|
|
||||||
//remove the player from other clients
|
|
||||||
|
|
||||||
//debugging
|
|
||||||
cout << "Lost connection: index " << disconnect.meta.clientIndex << endl;
|
|
||||||
cout << "number of clients: " << clients.size() << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::AddPlayer(Packet& p) {
|
//delete players
|
||||||
//add the player
|
erase_if(playerMap, [&](pair<int, PlayerEntry> it) -> bool {
|
||||||
PlayerEntry newPlayer = {
|
if (it.first == packet.playerInfo.playerIndex) {
|
||||||
uniqueIndex++,
|
NetworkPacket delPacket;
|
||||||
p.meta.clientIndex,
|
|
||||||
p.playerInfo.handle,
|
|
||||||
p.playerInfo.avatar,
|
|
||||||
p.playerInfo.position,
|
|
||||||
p.playerInfo.motion
|
|
||||||
};
|
|
||||||
|
|
||||||
players[newPlayer.index] = newPlayer;
|
//data to delete one specific player
|
||||||
|
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
|
||||||
|
delPacket.playerInfo.playerIndex = it.first;
|
||||||
|
|
||||||
//prep for relay
|
//send to all
|
||||||
p.playerInfo.index = newPlayer.index;
|
PumpPacket(delPacket);
|
||||||
|
|
||||||
//debugging
|
return true;
|
||||||
cout << "New player " << newPlayer.handle << " has joined the game" << endl;
|
}
|
||||||
cout << "Number of players: " << players.size() << endl;
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::RemovePlayer(Packet& p) {
|
void ServerApplication::HandlePlayerUpdate(NetworkPacket packet) {
|
||||||
if (players.find(p.playerInfo.index) == players.end()) {
|
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
|
||||||
throw(runtime_error("Player to delete not found"));
|
throw(std::runtime_error("Cannot update a non-existant player"));
|
||||||
}
|
}
|
||||||
|
|
||||||
players.erase(p.playerInfo.index);
|
//server is the slave to the clients, but only for now
|
||||||
|
playerMap[packet.playerInfo.playerIndex].position = packet.playerInfo.position;
|
||||||
|
playerMap[packet.playerInfo.playerIndex].motion = packet.playerInfo.motion;
|
||||||
|
|
||||||
|
PumpPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerApplication::UpdatePlayer(Packet& p) {
|
void ServerApplication::HandleRegionRequest(NetworkPacket packet) {
|
||||||
if (players.find(p.playerInfo.index) == players.end()) {
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
throw(runtime_error("Player to update not found"));
|
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) {
|
||||||
|
//I don't really like this, but it'll do for now
|
||||||
|
char buffer[PACKET_BUFFER_SIZE];
|
||||||
|
serialize(&packet, buffer);
|
||||||
|
for (auto& it : clientMap) {
|
||||||
|
network.Send(&it.second.address, buffer, PACKET_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
players[p.playerInfo.index].position = p.playerInfo.position;
|
|
||||||
players[p.playerInfo.index].motion = p.playerInfo.motion;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,73 +22,90 @@
|
|||||||
#ifndef SERVERAPPLICATION_HPP_
|
#ifndef SERVERAPPLICATION_HPP_
|
||||||
#define SERVERAPPLICATION_HPP_
|
#define SERVERAPPLICATION_HPP_
|
||||||
|
|
||||||
#include "packet.hpp"
|
//maps
|
||||||
#include "singleton.hpp"
|
#include "map_generator.hpp"
|
||||||
#include "network_queue.hpp"
|
#include "map_file_format.hpp"
|
||||||
|
#include "region_pager.hpp"
|
||||||
|
|
||||||
#include "config_Utility.hpp"
|
//networking
|
||||||
|
#include "network_packet.hpp"
|
||||||
#include "udp_network_utility.hpp"
|
#include "udp_network_utility.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
|
//common
|
||||||
|
#include "config_utility.hpp"
|
||||||
#include "vector2.hpp"
|
#include "vector2.hpp"
|
||||||
|
|
||||||
#include "SDL/SDL_thread.h"
|
//APIs
|
||||||
|
#include "lua/lua.hpp"
|
||||||
|
#include "sqlite3/sqlite3.h"
|
||||||
|
#include "SDL/SDL.h"
|
||||||
|
|
||||||
|
//STL
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
struct ClientEntry {
|
struct ClientEntry {
|
||||||
int index;
|
|
||||||
IPaddress address;
|
IPaddress address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerEntry {
|
struct PlayerEntry {
|
||||||
int index;
|
|
||||||
int clientIndex;
|
int clientIndex;
|
||||||
|
int mapIndex;
|
||||||
std::string handle;
|
std::string handle;
|
||||||
std::string avatar;
|
std::string avatar;
|
||||||
Vector2 position;
|
Vector2 position;
|
||||||
Vector2 motion;
|
Vector2 motion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//The main application class
|
||||||
class ServerApplication {
|
class ServerApplication {
|
||||||
public:
|
public:
|
||||||
ServerApplication();
|
//standard functions
|
||||||
~ServerApplication();
|
ServerApplication() = default;
|
||||||
void Init();
|
~ServerApplication() = default;
|
||||||
void Proc();
|
|
||||||
|
void Init(int argc, char** argv);
|
||||||
|
void Loop();
|
||||||
void Quit();
|
void Quit();
|
||||||
|
|
||||||
ServerApplication(ServerApplication const&) = delete;
|
|
||||||
ServerApplication(ServerApplication const&&) = delete;
|
|
||||||
private:
|
private:
|
||||||
//game loop
|
void HandlePacket(NetworkPacket);
|
||||||
void UpdateWorld(double delta);
|
|
||||||
|
|
||||||
//network loop
|
//high cohesion utility functions
|
||||||
int HandlePacket(Packet);
|
void HandleBroadcastRequest(NetworkPacket);
|
||||||
void RelayPacket(Packet&);
|
void HandleJoinRequest(NetworkPacket);
|
||||||
|
void HandleDisconnect(NetworkPacket);
|
||||||
|
void HandleSynchronize(NetworkPacket);
|
||||||
|
void HandleShutdown(NetworkPacket);
|
||||||
|
void HandlePlayerNew(NetworkPacket);
|
||||||
|
void HandlePlayerDelete(NetworkPacket);
|
||||||
|
void HandlePlayerUpdate(NetworkPacket);
|
||||||
|
void HandleRegionRequest(NetworkPacket);
|
||||||
|
|
||||||
void SynchronizeEverything(Packet&);
|
void PumpPacket(NetworkPacket);
|
||||||
|
|
||||||
void HandleBroadcast(Packet&);
|
//maps
|
||||||
void HandleConnection(Packet&);
|
RegionPager<LuaGenerator, LuaFormat> mapPager;
|
||||||
void HandleDisconnection(Packet&);
|
|
||||||
|
|
||||||
void AddPlayer(Packet&);
|
//networking
|
||||||
void RemovePlayer(Packet&);
|
UDPNetworkUtility network;
|
||||||
void UpdatePlayer(Packet&);
|
|
||||||
|
|
||||||
//services
|
//database
|
||||||
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get();
|
sqlite3* database = nullptr;
|
||||||
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get();
|
|
||||||
|
|
||||||
//members
|
//lua
|
||||||
std::map<int, ClientEntry> clients;
|
lua_State* luaState = nullptr;
|
||||||
std::map<int, PlayerEntry> players;
|
|
||||||
|
|
||||||
bool running = false;
|
//misc
|
||||||
|
bool running = true;
|
||||||
|
ConfigUtility config;
|
||||||
|
|
||||||
int uniqueIndex = 0;
|
std::map<int, ClientEntry> clientMap;
|
||||||
|
std::map<int, PlayerEntry> playerMap;
|
||||||
|
|
||||||
|
int clientCounter = 0;
|
||||||
|
int playerCounter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int main(int, char**) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||