Compare commits

..

78 Commits

Author SHA1 Message Date
Kayne Ruse 31cca61d1c Added position data to player objects 2013-12-31 02:25:16 +11:00
Kayne Ruse 071e0d9021 I'm sick of multithreading.
I'm also sick of bastards on the internet.
2013-12-30 14:11:44 +11:00
Kayne Ruse a494bfbb38 Fixed horrible naming convention 2013-12-25 22:09:59 +11:00
Kayne Ruse baadf554cd BUGFIX: Solved server failure
Cause:

server/server_application.cpp: line 93

The last argument to std::pair was simply a call to WorldRoom's
contructor. This created a temporary object that fufilled this line, but
after the new std::pair object was added to worldRoomMap, this WorldRoom
object went out of scope.

server/server_application.cpp: line 96

When OpenRoom() was called using an object that was out of scope, the
entire server simply failed.

Solution:

Changed worldRoomMap to hold a pointer to a WorldRoom object, rather than the
object itself. The new and delete operators should be used to create and
delete WorldRoom objects respectfully.
2013-12-14 00:23:20 +11:00
Kayne Ruse 9df16fede0 WARNING: Server fails on startup
For some reason, when trying to initiate the room thread, the entire
server simply fails. There is no crash, no error message, or anything. I
have no idea what's wrong.
2013-12-11 22:22:01 +11:00
Kayne Ruse dd0ad31ac6 Tweaked README.md 2013-12-11 18:54:51 +11:00
Kayne Ruse be26c9d103 Started working on multithreaded rooms 2013-12-08 15:55:49 +11:00
Kayne Ruse a448c8fb68 Added the nightly build link to the readme 2013-12-07 03:28:41 +11:00
Kayne Ruse de1a6a050f Fixed jittery lag and client closing issues 2013-12-07 03:24:39 +11:00
Kayne Ruse 49c9abe91b Added controls, it's now MP capable 2013-12-07 02:36:48 +11:00
Kayne Ruse 3b05476689 Connections and disconnections are working across different clients 2013-12-07 01:33:27 +11:00
Kayne Ruse 1c032bfc47 Implemented client-side player creation; incomplete 2013-12-06 23:03:46 +11:00
Kayne Ruse 1a7457f650 Imported and refactored PlayerCharacter from the old branch 2013-12-06 21:00:35 +11:00
Kayne Ruse e640eda771 Moved client scenes to a sub directory, reworked build process 2013-12-06 20:22:55 +11:00
Kayne Ruse fc2b67608f Added new graphics stuff, adjusted build process 2013-12-06 18:29:55 +11:00
Kayne Ruse a3a990cc01 Added player support to the server
This code is essentially copied from the old branch, since the two
branches are now functionally identical. How much time have I wasted
rewriting this?
2013-12-06 17:47:03 +11:00
Kayne Ruse f6a4674a2f Moved networking code into high cohesion functions 2013-12-02 17:54:47 +11:00
Kayne Ruse 865620b4a8 Renamed some things, and removed Client::index 2013-12-01 18:36:18 +11:00
Kayne Ruse 1e0ed350fc Removed Multithreading, simplifying the server
Networking and multithreading working at the same time is really fucking
hard. It's better to just have the one thread, and not worry about speed
at this stage.
2013-12-01 15:21:00 +11:00
Kayne Ruse 6ccc874583 Implemented the log on and log off systems
This is a pretty straight forward port of the old version, including the
incredibly hacky server list. But I just need to remember that this is a
prototype.
2013-11-23 17:53:36 +11:00
Kayne Ruse ca86dc5fb8 Added a delay, to give the machine a rest 2013-11-23 01:25:49 +11:00
Kayne Ruse e3605e4dc5 The client is receiving the list of servers 2013-11-22 23:19:29 +11:00
Kayne Ruse cb9aef95ec Reworked NetworkQueue as a template class 2013-11-22 19:57:24 +11:00
Kayne Ruse 09f97de0e6 Added HandlePacket() to the lobby 2013-11-22 19:56:15 +11:00
Kayne Ruse f5466b9982 Added config based directories 2013-11-17 00:13:16 +11:00
Kayne Ruse e176a60d28 client to server contact 2013-11-16 23:46:59 +11:00
Kayne Ruse dc24d1b059 Committing the empty WorldRoom class 2013-11-13 02:03:25 +11:00
Kayne Ruse fa3fc18ddf Imported and updated ConfigUtility 2013-11-09 21:13:00 +11:00
Kayne Ruse c2941cd3e8 Moved the thread out of the NetworkQueue class 2013-11-09 20:04:06 +11:00
Kayne Ruse bf15a5d957 Minor tweak 2013-11-09 16:32:35 +11:00
Kayne Ruse f01463bab3 Added and tested the network queue in the server
This is a reimplementation of the old network queue, but using a class.
This still uses a separate thread, so that packets can wait if there's any
lag. Really, thinking about it, I wonder how necessary this was.

On the upside, no singletons this time. Which means that you can have
several instances of UDPNetworkManager. That's unintentional, but good to
know.
2013-11-03 00:22:41 +11:00
Kayne Ruse 54cd26b76f Removed a lot of rubbish from the server 2013-11-02 19:00:08 +11:00
Kayne Ruse 2bd8adaf69 Added an empty navigation shell to the client 2013-10-27 22:00:09 +11:00
Kayne Ruse 26eba2def6 Moved some common/* files into directories 2013-10-27 20:17:37 +11:00
Kayne Ruse 43852ce755 Hooked the two scenes together
What the hell am I doing?
2013-10-27 00:43:37 +11:00
Kayne Ruse 81fab06e3b Dummied out the load & save functions 2013-10-22 20:22:35 +11:00
Kayne Ruse 77a90f9c0c Slight refactoring 2013-10-22 20:19:09 +11:00
Kayne Ruse bc32f2a2f0 The editor scene now works correctly with the TileSheetManager 2013-10-22 19:43:20 +11:00
Kayne Ruse 76bfecd466 RegionPager now uses a reference to TileSheetManager 2013-10-22 19:35:24 +11:00
Kayne Ruse d4eb1e7b8d Checking in the test scene and test tilesets 2013-10-22 19:22:18 +11:00
Kayne Ruse 2ec307510d Revised TileSheet & TileSheetManager 2013-10-22 19:18:35 +11:00
Kayne Ruse 0b4e6003d6 Created the TileSheetManager class
This class will manage the large(ish) number of tile sheets for a specific
map.
2013-10-21 23:53:36 +11:00
Kayne Ruse 7e603ffa89 Moved the map systems into their own directory 2013-10-17 23:33:02 +11:00
Kayne Ruse 6fc8570cf4 Added the saving function 2013-10-17 23:10:43 +11:00
Kayne Ruse 0bfd916df4 Fixed inverted camera, and added RegionPager::Prune() 2013-10-17 22:18:42 +11:00
Kayne Ruse 88aee0f4f5 Created the loadGameMap() function, still incomplete
Although the overall logic of this function is finished, I still need to
write the callbacks for RegionPager's onNew and onDelete.

I've also tested this using a hand written save/index file. I've written
up a map file format by hand, and I'll be implementing it over the next
few commits.
2013-10-14 21:12:09 +11:00
Kayne Ruse 0d3c3243a0 Added a debug display 2013-10-11 20:07:57 +11:00
Kayne Ruse 871b1136c2 Pager and menu bar working together without interfering with each other 2013-10-11 01:14:02 +11:00
Kayne Ruse f64c935ffe Imported revamped GUI classes, moved map classes 2013-10-11 00:30:31 +11:00
Kayne Ruse 600ec6789b Removed debug code from the editor 2013-10-07 02:32:36 +11:00
Kayne Ruse 65a3937592 Imported the rsc/ folder from the old branch 2013-10-07 01:32:29 +11:00
Kayne Ruse 719c8f49a6 Added region highlighting 2013-10-06 19:22:26 +11:00
Kayne Ruse 29928c0b92 Added a draw function to the pager
I'm also committing some simple debugging code in the scene.
2013-10-04 02:18:10 +10:00
Kayne Ruse a88a1f7cf7 Systems are working correctly, but needs cleaning 2013-10-04 00:34:57 +10:00
Kayne Ruse 46efbfbe9a Forgot to add the license 2013-10-03 23:20:04 +10:00
Kayne Ruse 26ff8dcc8f Created RegionPager 2013-10-03 23:04:16 +10:00
Kayne Ruse 9c91e9d5fd Decoupled the TileSheet class from the Map class
I moved the rangeEnd variable into the TileSheet class, making it static.
I also tweaked the return types for a few functions in Region, and removed
the sheetIndex member from Tile.
2013-10-03 21:29:11 +10:00
Kayne Ruse 3628d3c1fd Finished the delcaration of the Map class
This is actually a lot harder than I was expecting. When I program, I
approach from the angle of "What do I need to do?" rather than "how do I do
this?" At least this is finally done, so I can get to the implementation
stage. But, as I progress, I'll need to keep in mind what I need for the
index file.

Actually, I just realized that I didn't write the index functions. Well,
it should be interesting, at least.
2013-10-01 23:02:46 +10:00
Kayne Ruse 6c9406147a Added width & height members to Tile, moved local functions to utility.*pp
I've added more members to the Tile structure, namely the width & height
of the tile. This is to fix a circular logic problem, which is too
abstract for this commit message ;)

I've also moved the local/static/inline/etc. utility functions to their
own module in the common directory, because this is just cleaner that
redefining the same code a dozen times.

The map's logic is still the same, but I need to keep moving; I've been
procrastinating far too much.
2013-10-01 21:46:34 +10:00
Kayne Ruse aae244de39 Code tweak 2013-09-25 21:27:00 +10:00
Kayne Ruse d5b14c2679 Created the TileSheet class
This is incomplete on it's own, but used as part of the whole map system,
it should work well. This class keeps track of various, seemingly
unrelated states, which are used as part of the larger map system.

Also, fixed Region's members being public.
2013-09-25 20:39:59 +10:00
Kayne Ruse a54fbfb9e9 Added static linking 2013-09-21 16:26:01 +10:00
Kayne Ruse 9cbbfe77b7 After some testing Region seems OK 2013-09-19 22:52:26 +10:00
Kayne Ruse 9b64c67068 Finished a prototype of Region, needs testing 2013-09-19 16:52:15 +10:00
Kayne Ruse de0227a1cf Demonstration of Tile & Region classes 2013-09-19 01:22:52 +10:00
Kayne Ruse 1dfeabf195 SDL_net is working 2013-09-09 12:15:26 +10:00
Kayne Ruse 6c5197f3f2 The server runs the setup scripts on startup 2013-09-05 23:02:48 +10:00
Kayne Ruse 09453cc24e Added lua and SQL, but removed lsqlite3.c
lsqlite3.c looked like a good idea for connnecting SQL and lua, but I
couldn't get it to work and rather than struggle on this, I'll write my
own library later on.
2013-09-05 20:08:50 +10:00
Kayne Ruse 4b62310158 Revised build process to include the common/ directory 2013-09-04 20:49:55 +10:00
Kayne Ruse 43f2190c3e Created the database setup script 2013-09-04 19:17:16 +10:00
Kayne Ruse 3225da6b13 Added client scenes 2013-08-31 03:27:11 +10:00
Kayne Ruse 0c233b8764 Added readme.md 2013-08-29 21:55:09 +10:00
Kayne Ruse 027d0125ef Boilerplate, boilerplate, boilerplate!!!
I've created a project for client & editor programs, by simply copying one
to the other. Right now, the client still has the editor scene, but I'll
switch that out soon.

I've also added a license header to the server's source. I don't remember
what else I did, but at this point it should theoretically build out of
the box.
2013-08-29 21:17:43 +10:00
Kayne Ruse e4884c3e18 Added more placeholder files 2013-08-29 20:35:02 +10:00
Kayne Ruse b675f516e7 Beginning to create the placeholder classes 2013-08-29 19:57:25 +10:00
Kayne Ruse d5f7363c33 Minor rename 2013-08-25 13:59:13 +10:00
Kayne Ruse 7458962ad4 Rearranged the logic 2013-08-24 23:20:43 +10:00
Kayne Ruse 0a0b61287e Started working on the room system 2013-08-11 20:39:08 +10:00
92 changed files with 3891 additions and 1746 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
#Editor generated files #Editor generated files
#*.sln *.sln
#*.vcproj *.vcproj
*.suo *.suo
*.ncb *.ncb
*.user *.user
+12 -9
View File
@@ -1,17 +1,20 @@
_This project is currently in it's early prototype stage. You can see other versions in various branches or tagged as prototype-X._ You can find the [latest nightly build 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, 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://docs.google.com/document/d/17SjOTdacKKWX0Z-UkaiFnVnjfEeMsc5LRmARtnjh5UI/edit?usp=sharing)
[Tortuga Technical Document](https://docs.google.com/document/d/1ASTfM_1e0yE1cFP-IZey_rHEC6k2kmVY56X4K407sw0/edit?usp=sharing)
## Copyright ## Copyright
+8
View File
@@ -0,0 +1,8 @@
#ifndef CHANNELS_HPP_
#define CHANNELS_HPP_
enum Channels {
SERVER = 0
};
#endif
+44 -71
View File
@@ -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_HWSURFACE);
//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, sizeof(NetworkPacket));
//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); Clock::duration delta(16 * Clock::duration::period::den / std::milli::den);
Clock::time_point simTime = Clock::now(); Clock::time_point simTime = Clock::now();
Clock::time_point realTime; Clock::time_point realTime;
@@ -110,10 +89,8 @@ 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) {
@@ -124,20 +101,16 @@ void ClientApplication::Proc() {
//draw the game to the screen //draw the game to the screen
activeScene->RenderFrame(); activeScene->RenderFrame();
//give the computer a break
SDL_Delay(10);
} }
UnloadScene(); UnloadScene();
} }
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();
} }
@@ -151,24 +124,24 @@ void ClientApplication::LoadScene(SceneList sceneIndex) {
switch(sceneIndex) { switch(sceneIndex) {
//add scene creation calls here //add scene creation calls here
case SceneList::INCOMBAT:
activeScene = new InCombat();
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::FIRST:
case SceneList::SPLASHSCREEN: case SceneList::SPLASHSCREEN:
activeScene = new 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:
activeScene = new InCombat();
break; break;
default: default:
+10 -15
View File
@@ -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
-326
View File
@@ -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));
}
-244
View File
@@ -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);
}
+5 -10
View File
@@ -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;
} }
+12 -6
View File
@@ -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
+36 -33
View File
@@ -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;
} }
} }
+12 -9
View File
@@ -24,21 +24,26 @@
#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 FaceDirection(CardinalDirection);
void FaceDirection();
void DrawTo(SDL_Surface* const dest) { sprite.DrawTo(dest, position.x, position.y); } 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; }
Vector2 ShiftPosition(Vector2 v) { return position += v; } Vector2 ShiftPosition(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
+5 -5
View File
@@ -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&);
+315
View File
@@ -0,0 +1,315 @@
/* 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 <stdexcept>
//-------------------------
//Public access members
//-------------------------
InWorld::InWorld(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
disconnectButton.SetImage(&image);
disconnectButton.SetFont(&font);
shutDownButton.SetImage(&image);
shutDownButton.SetFont(&font);
//set the button positions
disconnectButton.SetX(50);
disconnectButton.SetY(50 + image.GetClipH() * 0);
shutDownButton.SetX(50);
shutDownButton.SetY(50 + image.GetClipH() * 1);
//set the button texts
disconnectButton.SetText("Disconnect");
shutDownButton.SetText("Shut Down");
//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
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
//request a sync
packet.meta.type = NetworkPacket::Type::SYNCHRONIZE;
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
}
InWorld::~InWorld() {
//
}
//-------------------------
//Frame loop
//-------------------------
void InWorld::FrameStart() {
//
}
void InWorld::Update(double delta) {
//suck in all waiting packets
NetworkPacket packet;
while(network.Receive()) {
memcpy(&packet, network.GetInData(), sizeof(NetworkPacket));
packet.meta.srcAddress = network.GetInPacket()->address;
HandlePacket(packet);
}
for (auto& it : playerCharacters) {
it.second.Update(delta);
}
}
void InWorld::FrameEnd() {
//
}
void InWorld::Render(SDL_Surface* const screen) {
for (auto& it : playerCharacters) {
it.second.DrawTo(screen);
}
disconnectButton.DrawTo(screen);
shutDownButton.DrawTo(screen);
}
//-------------------------
//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;
}
}
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;
//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];
}
}
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::SendState() {
NetworkPacket packet;
packet.meta.type = NetworkPacket::Type::PLAYER_UPDATE;
packet.playerInfo.clientIndex = clientIndex;
packet.playerInfo.playerIndex = playerIndex;
// snprintf(packet.playerInfo.handle, PACKET_STRING_SIZE, "%s", config["player.handle"].c_str());
// snprintf(packet.playerInfo.avatar, PACKET_STRING_SIZE, "%s", config["player.avatar"].c_str());
packet.playerInfo.position = localCharacter->GetPosition();
packet.playerInfo.motion = localCharacter->GetMotion();
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
}
void InWorld::RequestDisconnect() {
//send a disconnect request
NetworkPacket packet;
packet.meta.type = NetworkPacket::Type::DISCONNECT;
packet.clientInfo.index = clientIndex;
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
}
void InWorld::RequestShutDown() {
//send a shutdown request
NetworkPacket packet;
packet.meta.type = NetworkPacket::Type::SHUTDOWN;
packet.clientInfo.index = clientIndex;
network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket));
}
@@ -24,26 +24,20 @@
#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 "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 "image.hpp"
#include "raster_font.hpp" #include "raster_font.hpp"
#include "frame_rate.hpp" #include "button.hpp"
#include "player_character.hpp"
#include <map> #include <map>
class InWorld : public BaseScene { class InWorld : public BaseScene {
public: public:
//Public access members //Public access members
InWorld(); InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const);
~InWorld(); ~InWorld();
protected: protected:
@@ -61,28 +55,29 @@ protected:
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 HandleDisconnect(NetworkPacket);
void Disconnect(); void HandlePlayerNew(NetworkPacket);
void ExitGame(); void HandlePlayerDelete(NetworkPacket);
void HandlePlayerUpdate(NetworkPacket);
void HandleDisconnection(Packet&);
void AddPlayer(Packet&);
void RemovePlayer(Packet&);
void UpdatePlayer(Packet&);
void SendState(); void SendState();
void RequestDisconnect();
void RequestShutDown();
//services //global
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get(); ConfigUtility& config;
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get(); UDPNetworkUtility& network;
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get(); int& clientIndex;
InformationManager* infoMgr = Singleton<InformationManager>::Get();
//members //members
Image image;
RasterFont font; RasterFont font;
Button disconnectButton;
Button shutDownButton;
std::map<int, PlayerCharacter> playerCharacters; std::map<int, PlayerCharacter> playerCharacters;
PlayerCharacter* localCharacter = nullptr;
int playerIndex = -1;
}; };
#endif #endif
+196
View File
@@ -0,0 +1,196 @@
/* 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()) {
memcpy(&packet, network.GetInData(), sizeof(NetworkPacket));
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) {
//broadcast to the network, or a specific server
NetworkPacket packet;
packet.meta.type = NetworkPacket::Type::BROADCAST_REQUEST;
network.Send(config["server.host"].c_str(), config.Int("server.port"), reinterpret_cast<void*>(&packet), sizeof(NetworkPacket));
//reset the server list
serverInfo.clear();
selection = nullptr;
}
else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) {
//join the selected server
NetworkPacket packet;
packet.meta.type = NetworkPacket::Type::JOIN_REQUEST;
network.Send(&selection->address, &packet, sizeof(NetworkPacket));
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,38 +19,26 @@
* 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 LOBBYMENU_HPP_
#define LOBBY_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 "button.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 "udp_network_utility.hpp" #include "udp_network_utility.hpp"
#include "button.hpp" #include "network_packet.hpp"
#include "raster_font.hpp"
#include <vector> #include <vector>
#include <string>
struct ServerEntry { class LobbyMenu : public BaseScene {
std::string name;
IPaddress address;
//TODO: player count
};
class Lobby : public BaseScene {
public: public:
//Public access members //Public access members
Lobby(); LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const);
~Lobby(); ~LobbyMenu();
protected: protected:
//Frame loop //Frame loop
@@ -66,28 +54,32 @@ protected:
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 BroadcastNetwork();
void PushServer(Packet&);
void ConnectToServer(ServerEntry*);
void BeginGame(Packet&);
//services //global
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get(); ConfigUtility& config;
SurfaceManager* surfaceMgr = Singleton<SurfaceManager>::Get(); UDPNetworkUtility& network;
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get(); int& clientIndex;
InformationManager* infoMgr = Singleton<InformationManager>::Get();
//members //members
Button refreshButton; Image image;
Button joinButton;
Button backButton;
RasterFont font; RasterFont font;
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; SDL_Rect listBox;
std::vector<ServerEntry> serverList; ServerInformation* selection = nullptr;
ServerEntry* selectedServer = 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();
@@ -98,6 +113,10 @@ void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) { switch(key.keysym.sym) {
case SDLK_ESCAPE: case SDLK_ESCAPE:
QuitEvent(); QuitEvent();
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;
+43
View File
@@ -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
@@ -19,59 +19,84 @@
* 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 "options_menu.hpp"
#include <iostream>
using namespace std;
//------------------------- //-------------------------
//Public access members //Public access members
//------------------------- //-------------------------
OptionScreen::OptionScreen() { OptionsMenu::OptionsMenu(ConfigUtility* const argConfig):
#ifdef DEBUG config(*argConfig)
cout << "entering OptionScreen" << endl; {
#endif //setup the utility objects
backButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Back"); 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");
} }
OptionScreen::~OptionScreen() { OptionsMenu::~OptionsMenu() {
#ifdef DEBUG //
cout << "leaving OptionScreen" << endl;
#endif
} }
//------------------------- //-------------------------
//Frame loop //Frame loop
//------------------------- //-------------------------
void OptionScreen::Render(SDL_Surface* const screen) { void OptionsMenu::FrameStart() {
//
}
void OptionsMenu::Update(double delta) {
//
}
void OptionsMenu::FrameEnd() {
//
}
void OptionsMenu::Render(SDL_Surface* const screen) {
backButton.DrawTo(screen); backButton.DrawTo(screen);
font.DrawStringTo("Oh, were you looking for the options screen?", screen, 50, 30);
} }
//------------------------- //-------------------------
//Event handlers //Event handlers
//------------------------- //-------------------------
void OptionScreen::MouseMotion(SDL_MouseMotionEvent const& motion) { void OptionsMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
backButton.MouseMotion(motion); backButton.MouseMotion(motion);
} }
void OptionScreen::MouseButtonDown(SDL_MouseButtonEvent const& button) { void OptionsMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
backButton.MouseButtonDown(button); backButton.MouseButtonDown(button);
} }
void OptionScreen::MouseButtonUp(SDL_MouseButtonEvent const& button) { void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (backButton.MouseButtonUp(button) == Button::State::HOVER) { if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::MAINMENU); SetNextScene(SceneList::MAINMENU);
} }
} }
void OptionScreen::KeyDown(SDL_KeyboardEvent const& key) { void OptionsMenu::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) { switch(key.keysym.sym) {
case SDLK_ESCAPE: case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU); SetNextScene(SceneList::MAINMENU);
break; break;
} }
} }
void OptionsMenu::KeyUp(SDL_KeyboardEvent const& key) {
//
}
@@ -19,32 +19,42 @@
* 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 OPTIONSMENU_HPP_
#define OPTIONSCREEN_HPP_ #define OPTIONSMENU_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 OptionScreen : public BaseScene { class OptionsMenu : public BaseScene {
public: public:
/* Public access members */ //Public access members
OptionScreen(); OptionsMenu(ConfigUtility* const);
~OptionScreen(); ~OptionsMenu();
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
ConfigUtility& config;
//members
Image image;
RasterFont font;
Button backButton; Button backButton;
}; };
+51
View File
@@ -0,0 +1,51 @@
/* 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"
//-------------------------
//Public access members
//-------------------------
SplashScreen::SplashScreen(ConfigUtility* const argConfig):
config(*argConfig)
{
logo.LoadSurface(config["dir.logos"] + "krstudios.bmp");
startTick = std::chrono::steady_clock::now();
}
SplashScreen::~SplashScreen() {
//
}
//-------------------------
//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
-86
View File
@@ -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
}
+30 -1
View File
@@ -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";
}
+11 -19
View File
@@ -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;
} }
+80 -12
View File
@@ -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);
} }
+10 -3
View File
@@ -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();
+13 -8
View File
@@ -1,23 +1,25 @@
#config #config
LOCALLIBS=../lib/libCommon.a INCLUDES+=. ..
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
+102
View File
@@ -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 &image; } //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
+16 -7
View File
@@ -1,23 +1,29 @@
#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 network
$(MAKE) -C ui
$(OBJ): | $(OBJDIR) $(OBJ): | $(OBJDIR)
@@ -32,6 +38,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
+43
View File
@@ -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
+123
View File
@@ -0,0 +1,123 @@
/* 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 "region.hpp"
#include "utility.hpp"
#include <stdexcept>
#include <sstream>
Region::Region(int _x, int _y, int _w, int _h):
x(_x),
y(_y),
width(_w),
height(_h)
{
//make sure that the region's position lines up
if (x != snapToBase(width, x) || y != snapToBase(height, y)) {
std::ostringstream os;
os << "Region is unaligned; x: " << x << ", y: " << y << ", width: " << width << ", height: " << height;
throw(std::runtime_error(os.str()));
}
}
int Region::NewTileR(Tile const& tile) {
//return 1 for overwrite, 0 for insert
if (!InBoundsR(tile.x, tile.y)) {
std::ostringstream os;
os << "New tile location out of bounds: " <<
"(" << x << "," << y << ")->" <<
"(" << tile.x << "," << tile.y << ")"
;
throw(std::runtime_error(os.str()));
}
int ret = tiles.erase(tile);
tiles.insert(tile);
return ret;
}
Tile Region::GetTileR(int tx, int ty, int minDepth) {
std::set<Tile>::iterator ptr = tiles.begin();
//skip the tiles that are too deep
while(ptr != tiles.end()) {
if (ptr->depth >= minDepth) {
break;
}
ptr++;
}
//find the first tile here
while(ptr != tiles.end()) {
//bounds
if ((ptr->x <= tx) && (ptr->y <= ty) && (ptr->x + ptr->width > tx) && (ptr->y + ptr->height > ty)) {
break;
}
ptr++;
}
//found it
if (ptr != tiles.end()) {
return *ptr;
}
//a tileIndex of -1 is an error code, the rest is for show
return {0,0,0,-1,-1,-1};
}
int Region::DeleteTileR(Tile const& tile) {
if (!InBoundsR(tile.x, tile.y)) {
throw(std::runtime_error("Deleted tile location out of bounds"));
std::ostringstream os;
os << "Deleted tile location out of bounds: " <<
"(" << x << "," << y << ")->" <<
"(" << tile.x << "," << tile.y << ")"
;
throw(std::runtime_error(os.str()));
}
//sentinel/error code
if (tile.tileIndex == -1) {
return 0;
}
return tiles.erase(tile);
}
bool operator<(Region const& lhs, Region const& rhs) {
//sort by y -> x
if (lhs.y == rhs.y) {
return lhs.x < rhs.x;
}
return lhs.y < rhs.y;
}
inline bool operator>(Region const& lhs, Region const& rhs) {
//wrap the other operator
return rhs < lhs;
}
inline bool operator==(Region const& lhs, Region const& rhs) {
//comparisons work on the location ONLY
//this function is redundant as far as the std::set object is concerned
return (lhs.x == rhs.x) && (lhs.y == rhs.y);
}
+112
View File
@@ -0,0 +1,112 @@
/* 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 REGION_HPP_
#define REGION_HPP_
#include "tile.hpp"
#include <set>
/* A single section of the map.
* This class stores the tiles relative to it's own position, but
* there are functions for referencing the tiles' absolute position.
* These functions simply wrap the normal functions.
*/
class Region {
public:
Region() = delete;
Region(int x, int y, int width, int height);
~Region() = default;
//create and insert a new tile, overwriting an existing tile at that location
int NewTileR(Tile const& tile);
int NewTileA(Tile const& tile) {
//these can change, if the Tile class is changed
return NewTileR({
tile.x - x,
tile.y - y,
tile.depth,
tile.width,
tile.height,
tile.tileIndex
});
}
//find the first tile at this location, with the specified minimum depth
Tile GetTileR(int tx, int ty, int minDepth);
Tile GetTileA(int tx, int ty, int minDepth) {
return GetTileR(tx - x, ty - y, minDepth);
}
//wrap the other delete functions
int DeleteTileR(int tx, int ty, int minDepth) {
return DeleteTileR(GetTileR(tx, ty, minDepth));
}
int DeleteTileA(int tx, int ty, int minDepth) {
//explicitly skip one function call by adjusting from A to R
return DeleteTileR(GetTileR(tx - x, ty - y, minDepth));
}
//delete the specified tile
int DeleteTileR(Tile const& tile);
int DeleteTileA(Tile const& tile) {
//these can change, if the Tile class is changed
return DeleteTileR({
tile.x - x,
tile.y - y,
tile.depth,
tile.width,
tile.height,
tile.tileIndex
});
}
//find if the specified location exists within the region's bounds
bool InBoundsR(int i, int j) {
return (i >= 0) && (j >= 0) && (i < width) && (j < height);
}
bool InBoundsA(int i, int j) {
return InBoundsR(i - x, j - y);
}
//Raw accessors & mutators
int GetX() const { return x; }
int GetY() const { return y; }
int GetWidth() const { return width; }
int GetHeight() const { return height; }
std::set<Tile>* GetTiles() { return &tiles; }
//sorting the regions by the locations
friend bool operator<(Region const& lhs, Region const& rhs);
friend bool operator>(Region const& lhs, Region const& rhs);
friend bool operator==(Region const& lhs, Region const& rhs);
private:
int const x;
int const y;
int const width;
int const height;
std::set<Tile> tiles;
};
#endif
+121
View File
@@ -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.
*/
#include "region_pager.hpp"
#include "utility.hpp"
#include <stdexcept>
#include <string>
RegionPager::RegionPager() {
//
}
RegionPager::~RegionPager() {
if (onDelete) {
for (auto& i : regionList) {
onDelete(&i);
}
}
}
Region* RegionPager::NewRegion(int x, int y) {
for (auto& i : regionList) {
if (i.GetX() == x && i.GetY() == y) {
throw(std::runtime_error("Duplicate Regions detected"));
}
}
regionList.push_front({x, y, regionWidth, regionHeight});
if (onNew) {
onNew(&regionList.front());
}
return &regionList.front();
}
Region* RegionPager::GetRegion(int x, int y) {
for (auto& i : regionList) {
if (i.GetX() == x && i.GetY() == y) {
return &i;
}
}
//create, insert and return
regionList.push_front({x, y, regionWidth, regionHeight});
if (onNew) {
onNew(&regionList.front());
}
return &regionList.front();
}
void RegionPager::DeleteRegion(int x, int y) {
for (std::list<Region>::iterator i = regionList.begin(); i != regionList.end(); i++) {
if (i->GetX() == x && i->GetY() == y) {
if (onDelete) {
onDelete(&(*i));
}
regionList.erase(i);
break;
}
}
}
void RegionPager::DrawTo(SDL_Surface* const dest, TileSheetManager* const sheetMgr, int camX, int camY) {
for (auto& regionIter : regionList) {
#ifdef DEBUG
//draw the region's location
SDL_Rect box = {
Sint16(regionIter.GetX() - camX),
Sint16(regionIter.GetY() - camY),
Uint16(regionIter.GetWidth()),
Uint16(regionIter.GetHeight())
};
SDL_FillRect(dest, &box, SDL_MapRGB(dest->format, 10, 10, 20));
#endif
//draw each tile
for (auto& tileIter : *regionIter.GetTiles()) {
sheetMgr->DrawTo(
dest,
tileIter.x + regionIter.GetX() - camX,
tileIter.y + regionIter.GetY() - camY,
tileIter.tileIndex
);
}
}
}
void RegionPager::Prune(int left, int top, int right, int bottom) {
std::list<Region>::iterator it = regionList.begin();
while(it != regionList.end()) {
if (it->GetX() >= right || it->GetY() >= bottom || it->GetX() + it->GetWidth() < left || it->GetY() + it->GetHeight() < top) {
if (onDelete) {
onDelete(&(*it));
}
regionList.erase(it);
it = regionList.begin();
continue;
}
it++;
}
}
+69
View File
@@ -0,0 +1,69 @@
/* 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 REGIONPAGER_HPP_
#define REGIONPAGER_HPP_
#include "region.hpp"
#include "tile_sheet_manager.hpp"
#include <list>
class RegionPager {
public:
//for simplicity and consistency
typedef void (*regionCallback_t)(Region* const);
RegionPager();
~RegionPager();
//these parameters MUST be multiples of the width & height
Region* NewRegion(int x, int y);
Region* GetRegion(int x, int y);
void DeleteRegion(int x, int y);
//call this to draw to the screen
void DrawTo(SDL_Surface* const, TileSheetManager* const, int camX, int camY);
//callback hooks
void SetOnNew(regionCallback_t f) { onNew = f; }
void SetOnDelete(regionCallback_t f) { onDelete = f; }
//params: Absolute values
void Prune(int left, int top, int right, int bottom);
//accessors and mutators
int SetWidth(int i) { return regionWidth = i; }
int SetHeight(int i) { return regionHeight = i; }
int GetWidth() const { return regionWidth; }
int GetHeight() const { return regionHeight; }
std::list<Region>* GetRegions() { return &regionList; }
private:
std::list<Region> regionList;
int regionWidth = 0, regionHeight = 0;
regionCallback_t onNew = nullptr;
regionCallback_t onDelete = nullptr;
};
#endif
+17 -14
View File
@@ -19,23 +19,26 @@
* 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 "tile.hpp"
void SpriteSheet::Update(double delta) { bool operator<(Tile const& lhs, Tile const& rhs) {
if (delay && (ticks += delta) >= delay) { //sort by depth -> y -> x
if (++currentFrame >= maxFrames) { if (lhs.depth == rhs.depth) {
currentFrame = 0; if (lhs.y == rhs.y) {
return lhs.x < rhs.x;
} }
ticks = 0; return lhs.y < rhs.y;
} }
image.SetClipX(currentFrame * image.GetClipW()); return lhs.depth < rhs.depth;
image.SetClipY(currentStrip * image.GetClipH());
} }
SDL_Surface* SpriteSheet::SetSurface(SDL_Surface* const s, Uint16 w, Uint16 h) { inline bool operator>(Tile const& lhs, Tile const& rhs) {
image.SetSurface(s); //wrap the other operator
image.SetClip({0, 0, w, h}); return rhs < lhs;
currentFrame = 0; maxFrames = image.GetSurface()->w / image.GetClipW(); }
currentStrip = 0; maxStrips = image.GetSurface()->h / image.GetClipH();
delay = ticks = 0; inline bool operator==(Tile const& lhs, Tile const& rhs) {
//comparisons work on the location ONLY
//this function is redundant as far as the std::set object is concerned
return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.depth == rhs.depth);
} }
+50
View File
@@ -0,0 +1,50 @@
/* 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 TILE_HPP_
#define TILE_HPP_
//explicitly a POD
struct Tile {
//position relative to the Region
int x, y, depth;
//graphics
int width, height;
int tileIndex;
Tile() = default;
Tile(int _x, int _y, int _depth, int _width, int _height, int _tileIndex) {
//The order of the arguments should be explicit
x = _x;
y = _y;
depth = _depth;
width = _width;
height = _height;
tileIndex = _tileIndex;
}
};
bool operator<(Tile const& lhs, Tile const& rhs);
bool operator>(Tile const& lhs, Tile const& rhs);
bool operator==(Tile const& lhs, Tile const& rhs);
#endif
+59
View File
@@ -0,0 +1,59 @@
/* 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 "tile_sheet.hpp"
#include <stdexcept>
void TileSheet::Load(std::string fname, Uint16 w, Uint16 h) {
//setup the image
image.LoadSurface(fname);
image.SetClipW(w);
image.SetClipH(h);
//get the tile counts
xCount = image.GetSurface()->w / w;
yCount = image.GetSurface()->h / h;
totalCount = xCount * yCount;
//set begin & end (usually temporary)
begin = 0;
end = totalCount;
}
void TileSheet::Unload() {
image.FreeSurface();
totalCount = xCount = yCount = 0;
begin = end = -1;
}
void TileSheet::DrawTo(SDL_Surface* const dest, int x, int y, int tileIndex) {
if (!InRange(tileIndex)) {
throw(std::invalid_argument("Tile index out of range"));
}
Sint16 clipX = (tileIndex-begin) % xCount * image.GetClipW();
Sint16 clipY = (tileIndex-begin) / xCount * image.GetClipH();
image.SetClipX(clipX);
image.SetClipY(clipY);
image.DrawTo(dest, x, y);
}
+70
View File
@@ -0,0 +1,70 @@
/* 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 TILESHEET_HPP_
#define TILESHEET_HPP_
#include "image.hpp"
#include <string>
/* The TileSheet class is used for drawing tiles of the map to the screen.
* This class also tracks the range of the tile images.
*/
class TileSheet {
public:
TileSheet() = default;
~TileSheet() = default;
//these load/set functions need to be followed by bookkeeping code
//w & h are the width & height of individual tiles
//TODO: rename these
void Load(std::string fname, Uint16 w, Uint16 h);
void Unload();
void DrawTo(SDL_Surface* const dest, int x, int y, int tileIndex);
bool InRange(int i) { return i >= begin && i < end; }
//accessors and mutators
Image* GetImage() { return &image; }
int GetTileW() const { return image.GetClipW(); }
int GetTileH() const { return image.GetClipH(); }
int GetTotalCount() const { return totalCount; }
int GetXCount() const { return xCount; }
int GetYCount() const { return yCount; }
int SetBegin(int i) { return begin = i; }
int SetEnd(int i) { return end = i; }
int GetBegin() const { return begin; }
int GetEnd() const { return end; }
private:
Image image;
//these are generated and used by internal processes
int totalCount = 0, xCount = 0, yCount = 0;
int begin = -1, end = -1;
};
#endif
+73
View File
@@ -0,0 +1,73 @@
/* 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 "tile_sheet_manager.hpp"
#include "utility.hpp"
#include <stdexcept>
TileSheet* TileSheetManager::LoadSheet(std::string fname, Uint16 w, Uint16 h) {
//get the key
std::string key = truncatePath(fname);
//don't override what's already here
if (sheetMap.find(key) != sheetMap.end()) {
throw(std::runtime_error("Cannot load duplicate tile sheets"));
}
//load & setup the sheet object
sheetMap[key].Load(fname, w, h);
sheetMap[key].SetBegin(rangeEnd);
rangeEnd += sheetMap[key].GetTotalCount();
sheetMap[key].SetEnd(rangeEnd);
//you can modify the object, say, during the save & load routines...
return &sheetMap[key];
}
TileSheet* TileSheetManager::GetSheet(std::string name) {
return &sheetMap.at(name);
}
TileSheet* TileSheetManager::GetSheetByIndex(int tileIndex) {
for (auto& it : sheetMap) {
if (it.second.InRange(tileIndex)) {
return &it.second;
}
}
return nullptr;
}
void TileSheetManager::UnloadSheet(std::string name) {
sheetMap.erase(name);
}
void TileSheetManager::DrawTo(SDL_Surface* const dest, int x, int y, int tileIndex) {
for (auto& it : sheetMap) {
if (it.second.InRange(tileIndex)) {
it.second.DrawTo(dest, x, y, tileIndex);
return;
}
}
//No matching tile index
throw(std::invalid_argument("Tile index is out of range of all tile sheets"));
}
@@ -19,31 +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.
*/ */
#ifndef SURFACEMANAGER_HPP_ #ifndef TILESHEETMANAGER_HPP_
#define SURFACEMANAGER_HPP_ #define TILESHEETMANAGER_HPP_
#include "SDL/SDL.h" #include "tile_sheet.hpp"
#include <map> #include <map>
#include <string> #include <string>
class SurfaceManager { class TileSheetManager {
public: public:
SurfaceManager() = default; TileSheetManager() = default;
~SurfaceManager() noexcept { FreeAll(); } ~TileSheetManager() = default;
SDL_Surface* Load(std::string key, std::string fname); TileSheet* LoadSheet(std::string fname, Uint16 w, Uint16 h);
SDL_Surface* Reload(std::string key, std::string fname); TileSheet* GetSheet(std::string name);
SDL_Surface* Get(std::string key); TileSheet* GetSheetByIndex(int tileIndex);
SDL_Surface* Set(std::string key, SDL_Surface* ptr); void UnloadSheet(std::string name);
void Free(std::string key);
void FreeAll();
SDL_Surface* operator[](std::string key) { return Get(key); }; void DrawTo(SDL_Surface* const, int x, int y, int tileIndex);
int SetRangeEnd(int i) { return rangeEnd += i; }
int GetRangeEnd() const { return rangeEnd; }
std::map<std::string, TileSheet>* GetSheetMap() { return &sheetMap; }
private: private:
SDL_Surface* LoadSurface(std::string key, std::string fname); std::map<std::string, TileSheet> sheetMap;
typedef std::map<std::string, SDL_Surface*> MapType; int rangeEnd = 0;
MapType surfaceMap;
}; };
#endif #endif
+43
View File
@@ -0,0 +1,43 @@
#config
INCLUDES+=. ..
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,42 +19,54 @@
* 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 "SDL/SDL_net.h" #include "SDL/SDL_net.h"
#include "vector2.hpp"
#define PACKET_STRING_SIZE 100 #define PACKET_STRING_SIZE 100
#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,
}; };
//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
@@ -65,24 +77,28 @@ union Packet {
//TODO: player count //TODO: player count
}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 //defaults
Packet() { 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)
@@ -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) {
-110
View File
@@ -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);
}
-34
View File
@@ -1,34 +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.
*/
#ifndef NETWORKQUEUE_HPP_
#define NETWORKQUEUE_HPP_
#include "packet.hpp"
void beginQueueThread();
void endQueueThread();
void killQueueThread();
Packet peekNetworkPacket();
Packet popNetworkPacket();
void flushNetworkQueue();
#endif
-81
View File
@@ -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;
}
+18 -26
View File
@@ -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;
} }
} }
+36 -22
View File
@@ -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 &image; }
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;
}; };
+43
View File
@@ -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
+139
View File
@@ -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;
}
+91
View File
@@ -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
image.SetClipW(image.GetSurface()->w/16); * restrictive; I suggest using a 3rd party library.
image.SetClipH(image.GetSurface()->h/16); */
}
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.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;
}; };
+59
View File
@@ -0,0 +1,59 @@
/* 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 "utility.hpp"
#include <algorithm>
int snapToBase(int base, int x) {
//snap to a grid
if (x < 0) {
x++;
return x - x % base - base;
}
return x - x % base;
}
std::string truncatePath(std::string pathname) {
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
+8 -3
View File
@@ -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; }
+139
View File
@@ -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
}
+74
View File
@@ -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
+130
View File
@@ -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;
}
+53
View File
@@ -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
+282
View File
@@ -0,0 +1,282 @@
/* 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", "-Save As...", "-Close", "Exit"},
{"Edit", "-Set Tile", "-Load Sheet", "-Delete Sheet", "-Metadata", "-Run Script"},
{"Debugging", "Debug On", "Debug Off", "Toggle Debug", "Testificate"}
});
//setup the pager
pager.SetOnNew([](Region* const ptr){
printf("New Region: %d, %d\n", ptr->GetX(), ptr->GetY());
});
pager.SetOnDelete([](Region* const ptr){
printf("Delete Region: %d, %d\n", ptr->GetX(), ptr->GetY());
});
//Set a resonable size for the regions
pager.SetWidth(32*4);
pager.SetHeight(32*4);
sheetMgr.LoadSheet(config["dir.tilesets"] + "terrain.bmp", 32, 32);
}
EditorScene::~EditorScene() {
//
}
//-------------------------
//Frame loop
//-------------------------
void EditorScene::FrameStart() {
//
}
void EditorScene::Update(double delta) {
pager.Prune(camera.x, camera.y, camera.x + GetScreen()->w, camera.y + GetScreen()->h);
}
void EditorScene::FrameEnd() {
//
}
void EditorScene::Render(SDL_Surface* const screen) {
//draw the map
pager.DrawTo(screen, &sheetMgr, camera.x, camera.y);
//draw a big bar across the top
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
font.DrawStringTo(
str,
debugInfo.GetSurface(),
debugInfo.GetClipW() - str.size() * font.GetCharW(),
font.GetCharH() * line
);
}
//-------------------------
//Event handlers
//-------------------------
void EditorScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
menuBar.MouseMotion(motion);
if (motion.state & SDL_BUTTON_LMASK && motion.y >= buttonImage.GetClipH()) {
Region* regionPtr = pager.GetRegion(
snapToBase(pager.GetWidth(), motion.x + camera.x),
snapToBase(pager.GetHeight(), motion.y + camera.y)
);
TileSheet* sheetPtr = sheetMgr.GetSheetByIndex(tileCounter);
regionPtr->NewTileA({
snapToBase(sheetPtr->GetTileW(), motion.x + camera.x), //x
snapToBase(sheetPtr->GetTileH(), motion.y + camera.y), //y
0, //depth
sheetPtr->GetTileW(), //width
sheetPtr->GetTileH(), //height
tileCounter++ //value
});
}
if (motion.state & SDL_BUTTON_RMASK) {
camera.x -= motion.xrel;
camera.y -= motion.yrel;
}
}
void EditorScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
menuBar.MouseButtonDown(button);
if (button.button == SDL_BUTTON_LEFT && button.y >= buttonImage.GetClipH()) {
Region* regionPtr = pager.GetRegion(
snapToBase(pager.GetWidth(), button.x + camera.x),
snapToBase(pager.GetHeight(), button.y + camera.y)
);
TileSheet* sheetPtr = sheetMgr.GetSheetByIndex(tileCounter);
regionPtr->NewTileA({
snapToBase(sheetPtr->GetTileW(), button.x + camera.x), //x
snapToBase(sheetPtr->GetTileH(), button.y + camera.y), //y
0, //depth
sheetPtr->GetTileW(), //width
sheetPtr->GetTileH(), //height
tileCounter++ //value
});
}
}
void EditorScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
int entry, drop;
menuBar.MouseButtonUp(button, &entry, &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: SAVE AS
break;
case 4:
//TODO: CLOSE
break;
case 5: {
//Quit
SDL_Event e;
e.type = SDL_QUIT;
SDL_PushEvent(&e);
}
break;
}
break;
case 1: //Edit
switch(drop) {
case 0:
//TODO: SET TILE
break;
case 1:
//TODO: LOAD SHEET
break;
case 2:
//TODO: DELETE SHEET
break;
case 3:
//TODO: METADATA
break;
case 4:
//TODO: RUN 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;
}
}
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) {
//
}
+80
View File
@@ -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 "region_pager.hpp"
#include "tile_sheet_manager.hpp"
#include "config_utility.hpp"
#include "image.hpp"
#include "raster_font.hpp"
#include "menu_bar.hpp"
//#include "map_loader.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&);
//globals
ConfigUtility& config;
//debugging tools
void DrawToDebugInfo(std::string, int line);
Image debugInfo;
bool debugOpen = true;
RegionPager pager;
TileSheetManager sheetMgr;
RasterFont font;
Image buttonImage;
MenuBar menuBar;
struct {
int x = 0, y = 0;
} camera;
int tileCounter = 0;
};
#endif
+16 -18
View File
@@ -19,26 +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.
*/ */
#include "frame_rate.hpp" #include "editor_application.hpp"
#include <chrono> #include <stdexcept>
#include <iostream>
typedef std::chrono::high_resolution_clock Clock; using namespace std;
static int frameCount = 0; int main(int, char**) {
static int lastFrameRate = 0; cout << "Beginning editor" << endl;
static Clock::time_point tick = Clock::now(); try {
EditorApplication::GetInstance()->Init();
int clockFrameRate() { EditorApplication::GetInstance()->Proc();
frameCount++; EditorApplication::GetInstance()->Quit();
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
lastFrameRate = frameCount;
frameCount = 0;
tick = Clock::now();
} }
return lastFrameRate; catch(exception& e) {
} cerr << "Fatal exception thrown: " << e.what() << endl;
return 1;
int getFrameRate() { }
return lastFrameRate; cout << "Clean exit" << endl;
return 0;
} }
+43
View File
@@ -0,0 +1,43 @@
#config
INCLUDES+=../common ../common/graphics ../common/map ../common/ui
LIBS+=../libcommon.a -lmingw32 -lSDLmain -lSDL
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
+10 -8
View File
@@ -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
+107
View File
@@ -0,0 +1,107 @@
/* 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 "testificate_scene.hpp"
#include <iostream>
using std::cout;
using std::endl;
//-------------------------
//Public access members
//-------------------------
TestificateScene::TestificateScene(ConfigUtility* const arg1):
config(*arg1)
{
sheetMgr.LoadSheet(config["dir.tilesets"] + "grass.bmp", 32, 32);
sheetMgr.LoadSheet(config["dir.tilesets"] + "longgrass.bmp", 32, 32);
sheetMgr.LoadSheet(config["dir.tilesets"] + "sand.bmp", 32, 32);
sheetMgr.LoadSheet(config["dir.tilesets"] + "dirt.bmp", 32, 32);
sheetMgr.LoadSheet(config["dir.tilesets"] + "water.bmp", 32, 32);
cout << "Range End: " << sheetMgr.GetRangeEnd() << endl;
pager.SetWidth(128);
pager.SetHeight(128);
pager.GetRegion(0, 0)->NewTileR({0, 0, 0, 32, 32, 0});
}
TestificateScene::~TestificateScene() {
//
}
//-------------------------
//Frame loop
//-------------------------
void TestificateScene::FrameStart() {
//
}
void TestificateScene::Update(double delta) {
//
}
void TestificateScene::FrameEnd() {
//
}
void TestificateScene::Render(SDL_Surface* const screen) {
//dump all tile graphics to the screen
for (int i = 0; i < sheetMgr.GetRangeEnd(); i++) {
sheetMgr.DrawTo(screen, i * 32 % screen->w, i * 32 / screen->w * 32, i);
}
// pager.DrawTo(screen, &sheetMgr, 0, 0);
}
//-------------------------
//Event handlers
//-------------------------
void TestificateScene::MouseMotion(SDL_MouseMotionEvent const& motion) {
//
}
void TestificateScene::MouseButtonDown(SDL_MouseButtonEvent const& button) {
//
}
void TestificateScene::MouseButtonUp(SDL_MouseButtonEvent const& button) {
//
}
void TestificateScene::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
// QuitEvent();
SetNextScene(SceneList::EDITORSCENE);
break;
}
}
void TestificateScene::KeyUp(SDL_KeyboardEvent const& key) {
//
}
+59
View File
@@ -0,0 +1,59 @@
/* 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 TESTIFICATESCENE_HPP_
#define TESTIFICATESCENE_HPP_
#include "base_scene.hpp"
#include "config_utility.hpp"
#include "tile_Sheet_manager.hpp"
#include "region_pager.hpp"
class TestificateScene : public BaseScene {
public:
//Public access members
TestificateScene(ConfigUtility* const);
~TestificateScene();
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&);
//globals
ConfigUtility& config;
//members
TileSheetManager sheetMgr;
RegionPager pager;
};
#endif
+12 -6
View File
@@ -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)
+15 -11
View File
@@ -1,20 +1,24 @@
#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/
#player options
player.handle = username
player.avatar = elliot2.bmp
#debugging #debugging
debug = true
avatar = elliot
handle = UserName
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File
View File
+73
View File
@@ -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)
);
+14 -4
View File
@@ -19,10 +19,20 @@
* 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 FRAMERATE_HPP_ #ifndef CLIENT_HPP_
#define FRAMERATE_HPP_ #define CLIENT_HPP_
int clockFrameRate(); #include "SDL/SDL_net.h"
int getFrameRate();
#include <map>
/* Hold the client info.
*/
struct Client {
IPaddress address;
};
typedef std::map<int, Client> ClientMap;
#endif #endif
+5 -7
View File
@@ -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;
} }
+11 -6
View File
@@ -1,15 +1,17 @@
#config #config
LOCALLIBS=../lib/libCommon.a INCLUDES+=. ../common ../common/map ../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
+17 -12
View File
@@ -19,20 +19,25 @@
* 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 PLAYER_HPP_
#define SINGLETON_HPP_ #define PLAYER_HPP_
template<typename T> #include "vector2.hpp"
class Singleton {
public: #include <string>
static T* Get() { #include <map>
return &instance;
} /* Hold the player info.
private: */
static T instance;
struct Player {
int clientIndex;
std::string handle;
std::string avatar;
Vector2 position;
Vector2 motion;
}; };
template<typename T> typedef std::map<int, Player> PlayerMap;
T Singleton<T>::instance;
#endif #endif
+202 -220
View File
@@ -21,24 +21,17 @@
*/ */
#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;
//------------------------- //-------------------------
//Quick and dirty //Define the ServerApplication
//-------------------------
static std::string itos(int i) {
char buffer[20];
snprintf(buffer, 20, "%d", i);
return std::string(buffer);
}
//-------------------------
//Public access members
//------------------------- //-------------------------
ServerApplication::ServerApplication() { ServerApplication::ServerApplication() {
@@ -49,270 +42,259 @@ ServerApplication::~ServerApplication() {
// //
} }
/* ServerApplication::Init() void ServerApplication::Init(int argc, char** argv) {
* This function initializes the entire program. There are a number of things //TODO: proper command line option parsing
* 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 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 config
//load the config file config.Load("rsc\\config.cfg");
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));
}
//check the port is valid //Init SDL
if (configUtil->Int("server.port") <= 0) { if (SDL_Init(0)) {
throw(runtime_error("Cannot open the server on an invalid port or port 0")); throw(runtime_error("Failed to initialize SDL"));
} }
cout << "initialized SDL" << endl;
//initialize the APIs //Init SDL_net
if (SDLNet_Init()) { if (SDLNet_Init()) {
throw(runtime_error("Failed to initialize SDL_net")); throw(runtime_error("Failed to init SDL_net"));
} }
network.Open(config.Int("server.port"), sizeof(NetworkPacket));
cout << "initialized SDL_net" << endl;
//initiate the remaining singletons //Init SQL
netUtil->Open(configUtil->Int("server.port"), sizeof(Packet)); string dbname = (config["server.dbname"].size()) ? config["server.dbname"] : std::string(argv[0]) + ".db"; //fancy and unnecessary
int ret = sqlite3_open_v2(dbname.c_str(), &database, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_FULLMUTEX, nullptr);
if (ret != SQLITE_OK || !database) {
throw(runtime_error("Failed to open the server database"));
}
cout << "initialized SQL" << endl;
cout << "Database filename: " << dbname << endl;
//create the threads //TODO: move this into a function?
beginQueueThread(); //Run setup scripts
ifstream is("rsc\\scripts\\setup_server.sql");
//output the server information if (!is.is_open()) {
cout << configUtil->String("server.name") << endl; throw(runtime_error("Failed to run database setup script"));
cout << "Open on port " << configUtil->String("server.port") << endl; }
string script;
//disable this for debugging getline(is, script, '\0');
running = true; is.close();
sqlite3_exec(database, script.c_str(), nullptr, nullptr, nullptr);
} }
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) {
//suck in the waiting packets & process them
try { try {
//process all packets on the network queue while(network.Receive()) {
while(HandlePacket(popNetworkPacket())); memcpy(&packet, network.GetInData(), sizeof(NetworkPacket));
packet.meta.srcAddress = network.GetInPacket()->address;
HandlePacket(packet);
}
} }
catch(exception& e) { catch(exception& e) {
//handle any errors
cerr << "Network Error: " << e.what() << endl; cerr << "Network Error: " << e.what() << endl;
continue;
} }
//get the time since last update //give the computer a break
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 //members
endQueueThread(); network.Close();
//clean up the singletons //APIs
netUtil->Close(); sqlite3_close_v2(database);
//deinitialize the APIs
SDLNet_Quit(); SDLNet_Quit();
SDL_Quit();
} }
//------------------------- void ServerApplication::HandlePacket(NetworkPacket packet) {
//Game loop switch(packet.meta.type) {
//------------------------- case NetworkPacket::Type::BROADCAST_REQUEST:
HandleBroadcastRequest(packet);
break;
void ServerApplication::UpdateWorld(double delta) { case NetworkPacket::Type::JOIN_REQUEST:
//the recalc here each loop is a stopgap, see issue #9 for details HandleJoinRequest(packet);
for (auto& it : players) { break;
if (it.second.motion.x != 0 && it.second.motion.y != 0) {
constexpr double d = 1.0/sqrt(2);
it.second.position += it.second.motion * delta * d;
}
else {
it.second.position += it.second.motion * delta;
}
}
}
//------------------------- case NetworkPacket::Type::DISCONNECT:
//Network loop HandleDisconnect(packet);
//------------------------- break;
int ServerApplication::HandlePacket(Packet p) { case NetworkPacket::Type::SYNCHRONIZE:
switch(p.meta.type) { HandleSynchronize(packet);
case Packet::Type::NONE:
//DO NOTHING
return 0;
break; break;
case Packet::Type::PING:
//quick pong case NetworkPacket::Type::SHUTDOWN:
p.meta.type = Packet::Type::PONG; HandleShutdown(packet);
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
break; break;
case Packet::Type::PONG:
// case NetworkPacket::Type::PLAYER_NEW:
HandlePlayerNew(packet);
break; break;
case Packet::Type::BROADCAST_REQUEST:
HandleBroadcast(p); case NetworkPacket::Type::PLAYER_DELETE:
HandlePlayerDelete(packet);
break; break;
// case PacketType::BROADCAST_RESPONSE:
// // case NetworkPacket::Type::PLAYER_UPDATE:
// break; HandlePlayerUpdate(packet);
case Packet::Type::JOIN_REQUEST:
HandleConnection(p);
break;
// case PacketType::JOIN_RESPONSE:
// //
// break;
case Packet::Type::DISCONNECT:
HandleDisconnection(p);
break;
case Packet::Type::SYNCHRONIZE:
SynchronizeEverything(p);
break;
case Packet::Type::PLAYER_NEW:
AddPlayer(p);
RelayPacket(p);
break;
case Packet::Type::PLAYER_DELETE:
RemovePlayer(p);
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) { void ServerApplication::HandleBroadcastRequest(NetworkPacket packet) {
//send all known data to this client //send back the server's name
//TODO multithreading? packet.meta.type = NetworkPacket::Type::BROADCAST_RESPONSE;
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
network.Send(&packet.meta.srcAddress, &packet, sizeof(NetworkPacket));
}
//all players void ServerApplication::HandleJoinRequest(NetworkPacket packet) {
Packet p; //TODO: prevent duplicate logins from the same address?
p.meta.type = Packet::Type::PLAYER_UPDATE;
for (auto& it : players) {
p.meta.clientIndex = it.second.clientIndex;
p.playerInfo.index = it.second.index; //create the new client, filling it with the correct info
snprintf(p.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str()); Client newClient;
snprintf(p.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str()); newClient.address = packet.meta.srcAddress;
p.playerInfo.position = it.second.position;
p.playerInfo.motion = it.second.motion;
netUtil->Send(&clients[sync.meta.clientIndex].address, &p, sizeof(Packet)); //push the new client
clientMap[clientCounter] = newClient;
//send the client their info
packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE;
packet.clientInfo.index = clientCounter;
network.Send(&newClient.address, &packet, sizeof(NetworkPacket));
//finished this routine
clientCounter++;
cout << "connect, total: " << clientMap.size() << endl;
}
void ServerApplication::HandleDisconnect(NetworkPacket packet) {
//disconnect the specified client
network.Send(&clientMap[packet.clientInfo.index].address, &packet, sizeof(NetworkPacket));
clientMap.erase(packet.clientInfo.index);
//delete players
erase_if(playerMap, [&](pair<int, Player> it) -> bool {
if (it.second.clientIndex == packet.clientInfo.index) {
NetworkPacket delPacket;
//data to delete one specific player
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
delPacket.playerInfo.playerIndex = it.first;
//send to all
PumpPacket(delPacket);
return true;
}
return false;
});
cout << "disconnect, total: " << clientMap.size() << endl;
}
void ServerApplication::HandleSynchronize(NetworkPacket packet) {
//send all the server's data to this client
NetworkPacket newPacket;
//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;
network.Send(&clientMap[packet.clientInfo.index].address, &newPacket, sizeof(NetworkPacket));
} }
} }
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);
cout << "shutting down" << endl;
} }
void ServerApplication::HandleConnection(Packet& request) { void ServerApplication::HandlePlayerNew(NetworkPacket packet) {
//create the entries //create the new player object
ClientEntry newClient = { Player newPlayer;
uniqueIndex++, newPlayer.clientIndex = packet.playerInfo.clientIndex;
request.meta.address 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) {
//add the player
PlayerEntry newPlayer = {
uniqueIndex++,
p.meta.clientIndex,
p.playerInfo.handle,
p.playerInfo.avatar,
p.playerInfo.position,
p.playerInfo.motion
};
players[newPlayer.index] = newPlayer;
//prep for relay
p.playerInfo.index = newPlayer.index;
//debugging
cout << "New player " << newPlayer.handle << " has joined the game" << endl;
cout << "Number of players: " << players.size() << endl;
}
void ServerApplication::RemovePlayer(Packet& p) {
if (players.find(p.playerInfo.index) == players.end()) {
throw(runtime_error("Player to delete not found"));
} }
players.erase(p.playerInfo.index); //delete players
erase_if(playerMap, [&](pair<int, Player> it) -> bool {
if (it.first == packet.playerInfo.playerIndex) {
NetworkPacket delPacket;
//data to delete one specific player
delPacket.meta.type = NetworkPacket::Type::PLAYER_DELETE;
delPacket.playerInfo.playerIndex = it.first;
//send to all
PumpPacket(delPacket);
return true;
}
return false;
});
} }
void ServerApplication::UpdatePlayer(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 update not found")); throw(std::runtime_error("Cannot update a non-existant player"));
}
//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::PumpPacket(NetworkPacket packet) {
//send this packet to all clients
for (auto& it : clientMap) {
network.Send(&it.second.address, &packet, sizeof(NetworkPacket));
} }
players[p.playerInfo.index].position = p.playerInfo.position;
players[p.playerInfo.index].motion = p.playerInfo.motion;
} }
+40 -46
View File
@@ -22,73 +22,67 @@
#ifndef SERVERAPPLICATION_HPP_ #ifndef SERVERAPPLICATION_HPP_
#define SERVERAPPLICATION_HPP_ #define SERVERAPPLICATION_HPP_
#include "packet.hpp" //networking
#include "singleton.hpp" #include "network_packet.hpp"
#include "network_queue.hpp"
#include "config_Utility.hpp"
#include "udp_network_utility.hpp" #include "udp_network_utility.hpp"
//APIs
#include "sqlite3/sqlite3.h"
#include "SDL/SDL.h"
//misc
#include "config_utility.hpp"
#include "vector2.hpp" #include "vector2.hpp"
#include "SDL/SDL_thread.h" #include "client.hpp"
#include "player.hpp"
//STL
#include <map> #include <map>
#include <string> #include <string>
#include <algorithm>
struct ClientEntry {
int index;
IPaddress address;
};
struct PlayerEntry {
int index;
int clientIndex;
std::string handle;
std::string avatar;
Vector2 position;
Vector2 motion;
};
//The main application class
class ServerApplication { class ServerApplication {
public: public:
//standard functions
ServerApplication(); ServerApplication();
~ServerApplication(); ~ServerApplication();
void Init();
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 SynchronizeEverything(Packet&); void PumpPacket(NetworkPacket);
void HandleBroadcast(Packet&); //networking
void HandleConnection(Packet&); UDPNetworkUtility network;
void HandleDisconnection(Packet&);
void AddPlayer(Packet&); //database
void RemovePlayer(Packet&); sqlite3* database = nullptr;
void UpdatePlayer(Packet&);
//services //misc
ConfigUtility* configUtil = Singleton<ConfigUtility>::Get(); bool running = true;
UDPNetworkUtility* netUtil = Singleton<UDPNetworkUtility>::Get(); ConfigUtility config;
//members //global lists
std::map<int, ClientEntry> clients; ClientMap clientMap;
std::map<int, PlayerEntry> players; PlayerMap playerMap;
bool running = false; int clientCounter = 0;
int playerCounter = 0;
int uniqueIndex = 0;
}; };
#endif #endif
-7
View File
@@ -1,7 +0,0 @@
#include <iostream>
using namespace std;
int main(int, char**) {
return 0;
}