Compare commits

..

35 Commits

Author SHA1 Message Date
Kayne Ruse 5e99192fbf Lose focus on a server after a button is released 2013-06-18 19:38:08 +10:00
Kayne Ruse 33adb4b1a5 Put the license header into all source files 2013-06-18 16:40:51 +10:00
Kayne Ruse 33474cc6c0 Smooth connection and disconnection complete
The clients can connect and disconnect from the server with known no
issues. There is no way to shutdown the server yet, but it might be
possible to kick someone else from the server soon.
2013-06-18 16:21:42 +10:00
Kayne Ruse e833129983 Added guards incase of multiple calls 2013-06-18 14:06:57 +10:00
Kayne Ruse fd65fec5f7 The client is registering with the server 2013-06-17 19:53:22 +10:00
Kayne Ruse 69f03cd250 Working on connection systems 2013-06-17 19:04:05 +10:00
Kayne Ruse 27ed91688a Added the meta field to Packet to support Packet's metadata 2013-06-17 18:37:27 +10:00
Kayne Ruse 68ec7323a3 I can't progress until I add the address information to the Packet struct 2013-06-17 17:51:26 +10:00
Kayne Ruse 7b11bf22cb Specified a minimum Packet size for the DEBUG build 2013-06-17 17:14:10 +10:00
Kayne Ruse d83a536f35 Added debug output 2013-06-17 15:57:12 +10:00
Kayne Ruse ea761fb5bb Fixed the bug
running was false when it was checked in networkQueue(), so the thread was
ending early.
2013-06-17 15:49:57 +10:00
Kayne Ruse 685ca94335 This has the odd quirk related to networkQueue() 2013-06-17 15:15:27 +10:00
Kayne Ruse 5b2fd80a61 Fixed the Packet::type bug
In popNetworkPacket(), a second Packet p was being created, which was
destroyed when it went out of scope, and the original Packet p was being
returned.
2013-06-17 11:01:00 +10:00
Kayne Ruse d1aac9ffd8 Added peekNetworkPacket() 2013-06-17 10:12:20 +10:00
Kayne Ruse 3d92fb77b3 Server is multithreaded, but no connection is visible
UDPNetworkUtility and ConfigUtility are now using the ServiceLocator
pattern in the server, and networkQueue() is running in a separate thread
in the server. However, there seems to be a problem somewhere, since the
broadcast request & response are not producing any visible output.
2013-06-17 10:03:12 +10:00
Kayne Ruse 009e7b845b Fixed network error, leaving try block in place for the time being
It seems that the union type Packet didn't initialize Packet::type to
PacketType::NONE using in class initialization. I've fixed this by moving
the initialization of Packet::type to Packet::Packet().

This might actually be a compiler error, I might need to let someone know.
2013-06-17 09:09:04 +10:00
Kayne Ruse 752dcadfa1 Merge branch 'master' into dev 2013-06-17 08:32:02 +10:00
Kayne Ruse 9599d82db3 Added binary files, since git can't find .gitconfig on my brother's PC 2013-06-17 08:31:35 +10:00
Kayne Ruse 7fef2501a3 Glitch with threading 2013-06-17 07:24:16 +10:00
Kayne Ruse 419c9d8765 Moved the common directory into the libs directory 2013-06-16 13:59:11 +10:00
Kayne Ruse a0fa874a29 The server list is being populated from the network 2013-06-13 12:55:26 +10:00
Kayne Ruse 5110ebc1b2 Changed the escape key & quit event's function slightly 2013-06-13 12:31:29 +10:00
Kayne Ruse 843053d307 Implemented the server list box, still messy 2013-06-13 12:26:27 +10:00
Kayne Ruse 2148c1f13e Menu framework in place 2013-06-12 21:56:17 +10:00
Kayne Ruse f3ec4d4d8e Splash screen loads and displays correctly 2013-06-12 19:48:46 +10:00
Kayne Ruse cbd388f4ed Started using ServiceLocator, experimental 2013-06-12 06:35:43 +10:00
Kayne Ruse 37a9e4268b Imported the rsc directory from prototype-1 2013-06-12 05:23:06 +10:00
Kayne Ruse dfe0b4985a Modified build requirements
SDL_net needs to be _installed_ to the computer, rather than simply linked to.
This source distribution should be enough for that.
2013-06-12 04:37:01 +10:00
Kayne Ruse 7ca7f7f015 Added broadcast handling 2013-06-10 18:06:24 +10:00
Kayne Ruse c21a95f3e9 working on the server's skeleton, still slow going 2013-06-10 17:23:26 +10:00
Kayne Ruse 0a48131de4 Added common and test directories 2013-06-09 17:06:32 +10:00
Kayne Ruse 78326a3bbd Added a note about the project's development stage 2013-06-09 14:16:33 +10:00
Kayne Ruse 253e9ec8fc Created server shell 2013-06-08 01:52:19 +10:00
Kayne Ruse a1b248d1d7 Created the client program's framework
There are six scenes here, each of which representing roughly one part of
the final program's backbone.
2013-06-08 01:36:19 +10:00
Kayne Ruse 2757911399 Libraries are building correctly 2013-06-07 04:10:31 +10:00
111 changed files with 3633 additions and 4267 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
#Editor generated files
*.sln
*.vcproj
#*.sln
#*.vcproj
*.suo
*.ncb
*.user
+16 -16
View File
@@ -1,24 +1,22 @@
You can find the [latest nightly build here](https://dl.dropboxusercontent.com/u/46669050/Tortuga.rar).
_This project is currently in it's early prototype stage. You can see other versions in various branches, tagged as prototype-X._
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.
Tortuga is a 3/4 top down multiplayer RPG set in a large archipelago occupied by warring pirate clans. The emphasis of this game is on multiplayer competition, exploration in an open world, and solo adventuring. The game runs on a Minecraft like server system with a goal of about 50-100 players on a single server. The player characters are tied to the server where they are created, and are susceptible to permadeath: deletion of a character upon death. The servers are designed to allow a large amount of modification by the hosts.
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.
## Libraries
## External Dependencies
* [SDL](http://www.libsdl.org/) - Simple DirectMedia Layer API
* [SDL_net](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension, slightly modified. This must be installed first.
* [Codebase](https://github.com/Ratstail91/Codebase) - generic reusable code modules
* [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
## Instructions
## Documentation
[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)
* 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.
* 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 GitHub wiki [here](https://github.com/Ratstail91/Tortuga/wiki).
## Copyright
The current version of Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
Copyright (c) 2013 Kayne Ruse
@@ -26,6 +24,8 @@ This software is provided 'as-is', without any express or implied warranty. In n
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.
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.
@@ -34,7 +34,7 @@ SDL_Surface* BaseScene::screen = nullptr;
//-------------------------
BaseScene::BaseScene() {
//
nextScene = SceneList::CONTINUE;
}
BaseScene::~BaseScene() {
@@ -28,18 +28,18 @@
class BaseScene {
public:
//Public access members
/* Public access members */
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* GetScreen();
SceneList SetNextScene(SceneList sceneIndex);
SceneList GetNextScene() const;
//Frame loop
/* Frame loop */
virtual void RunFrame(double delta);
virtual void RenderFrame();
@@ -50,7 +50,7 @@ protected:
virtual void FrameEnd() {}
virtual void Render(SDL_Surface* const screen) {}
//Event handlers
/* Event handlers */
virtual void QuitEvent() { SetNextScene(SceneList::QUIT); }
virtual void MouseMotion(SDL_MouseMotionEvent const&) {}
virtual void MouseButtonDown(SDL_MouseButtonEvent const&) {}
@@ -68,7 +68,7 @@ protected:
private:
static SDL_Surface* screen;
SceneList nextScene = SceneList::CONTINUE;
SceneList nextScene;
};
#endif
-8
View File
@@ -1,8 +0,0 @@
#ifndef CHANNELS_HPP_
#define CHANNELS_HPP_
enum Channels {
SERVER = 0
};
#endif
@@ -21,16 +21,24 @@
*/
#include "in_combat.hpp"
#include <iostream>
using namespace std;
//-------------------------
//Public access members
//-------------------------
InCombat::InCombat() {
//
#ifdef DEBUG
cout << "entering InCombat" << endl;
#endif
}
InCombat::~InCombat() {
//
#ifdef DEBUG
cout << "leaving InCombat" << endl;
#endif
}
//-------------------------
@@ -26,18 +26,18 @@
class InCombat : public BaseScene {
public:
//Public access members
/* Public access members */
InCombat();
~InCombat();
protected:
//Frame loop
/* Frame loop */
void FrameStart();
void Update(double delta);
void FrameEnd();
void Render(SDL_Surface* const);
//Event handlers
/* Event handlers */
void MouseMotion(SDL_MouseMotionEvent const&);
void MouseButtonDown(SDL_MouseButtonEvent const&);
void MouseButtonUp(SDL_MouseButtonEvent const&);
+173
View File
@@ -0,0 +1,173 @@
/* 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;
//-------------------------
//Public access members
//-------------------------
InWorld::InWorld() {
#ifdef DEBUG
cout << "entering InWorld" << endl;
#endif
cout << "Client Index: " << infoMgr->GetClientIndex() << endl;
}
InWorld::~InWorld() {
#ifdef DEBUG
cout << "leaving InWorld" << endl;
#endif
}
//-------------------------
//Frame loop
//-------------------------
void InWorld::FrameStart() {
//
}
void InWorld::Update(double delta) {
while(HandlePacket(popNetworkPacket()));
}
void InWorld::FrameEnd() {
//
}
void InWorld::Render(SDL_Surface* const screen) {
//
}
//-------------------------
//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) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
ExitGame();
break;
}
}
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
//
}
//-------------------------
//Utilities
//-------------------------
int InWorld::HandlePacket(Packet p) {
switch(p.meta.type) {
case PacketType::NONE:
//DO NOTHING
return 0;
break;
case PacketType::PING:
//quick pong
p.meta.type = PacketType::PONG;
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
break;
case PacketType::PONG:
//
break;
// case PacketType::BROADCAST_REQUEST:
// //
// break;
// case PacketType::BROADCAST_RESPONSE:
// //
// break;
// case PacketType::JOIN_REQUEST:
// //
// break;
// case PacketType::JOIN_RESPONSE:
// //
// break;
case PacketType::DISCONNECT:
HandleDisconnection(p.disconnect);
break;
// case PacketType::SYNCHRONIZE:
// //
// break;
// case PacketType::PLAYER_NEW:
// //
// break;
// case PacketType::PLAYER_DELETE:
// //
// break;
// case PacketType::PLAYER_MOVE:
// //
// break;
default:
throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type))));
}
return 1;
}
void InWorld::Disconnect() {
//disconnect
Packet p;
p.meta.type = PacketType::DISCONNECT;
p.disconnect.clientIndex = infoMgr->GetClientIndex();
netUtil->Send(GAME_CHANNEL, reinterpret_cast<void*>(&p), sizeof(Packet));
netUtil->Unbind(GAME_CHANNEL);
endQueueThread();
//reset the client
infoMgr->ResetClientIndex();
}
void InWorld::ExitGame() {
Disconnect();
SetNextScene(SceneList::MAINMENU);
cout << "The game session has ended" << endl;
}
void InWorld::HandleDisconnection(::Disconnect& disconnect) {
Disconnect();
SetNextScene(SceneList::MAINMENU);
cout << "You have been disconnected" << endl;
}
@@ -23,21 +23,22 @@
#define INWORLD_HPP_
#include "base_scene.hpp"
#include "defines.hpp"
#include "service_locator.hpp"
#include "packet_type.hpp"
#include "network_queue.hpp"
#include "information_manager.hpp"
#include "config_utility.hpp"
#include "surface_manager.hpp"
#include "udp_network_utility.hpp"
#include "network_packet.hpp"
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
#include "player_character.hpp"
#include <map>
#include "raster_font.hpp"
class InWorld : public BaseScene {
public:
//Public access members
InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const);
InWorld();
~InWorld();
protected:
@@ -55,29 +56,20 @@ protected:
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
void HandlePacket(NetworkPacket);
void HandleDisconnect(NetworkPacket);
void HandlePlayerNew(NetworkPacket);
void HandlePlayerDelete(NetworkPacket);
void HandlePlayerUpdate(NetworkPacket);
//Utilities
int HandlePacket(Packet p);
void Disconnect();
void ExitGame();
void HandleDisconnection(::Disconnect&);
void SendState();
void RequestDisconnect();
void RequestShutDown();
//global
ConfigUtility& config;
UDPNetworkUtility& network;
int& clientIndex;
//services
ConfigUtility* configUtil = ServiceLocator<ConfigUtility>::Get();
SurfaceManager* surfaceMgr = ServiceLocator<SurfaceManager>::Get();
UDPNetworkUtility* netUtil = ServiceLocator<UDPNetworkUtility>::Get();
InformationManager* infoMgr = ServiceLocator<InformationManager>::Get();
//members
Image image;
RasterFont font;
Button disconnectButton;
Button shutDownButton;
std::map<int, PlayerCharacter> playerCharacters;
PlayerCharacter* localCharacter = nullptr;
int playerIndex = -1;
//...
};
#endif
@@ -19,25 +19,16 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef PLAYER_HPP_
#define PLAYER_HPP_
#ifndef INFORMATIONMANAGER_HPP_
#define INFORMATIONMANAGER_HPP_
#include "vector2.hpp"
#include <string>
#include <map>
/* Hold the player info.
*/
struct Player {
int clientIndex;
std::string handle;
std::string avatar;
Vector2 position;
Vector2 motion;
class InformationManager {
public:
int SetClientIndex(int i) { return clientIndex = i; }
int GetClientIndex() { return clientIndex; }
void ResetClientIndex() { clientIndex = -1; }
private:
int clientIndex = -1;
};
typedef std::map<int, Player> PlayerMap;
#endif
+234
View File
@@ -0,0 +1,234 @@
/* 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;
//-------------------------
//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, 100, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Join");
backButton.Setup(50, 150, 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 PacketType::NONE:
//DO NOTHING
return 0;
break;
case PacketType::PING:
//quick pong
p.meta.type = PacketType::PONG;
netUtil->Send(&p.meta.address, &p, sizeof(Packet));
break;
case PacketType::PONG:
//
break;
// case PacketType::BROADCAST_REQUEST:
// //
// break;
case PacketType::BROADCAST_RESPONSE:
PushServer(p.broadcastResponse);
break;
// case PacketType::JOIN_REQUEST:
// //
// break;
case PacketType::JOIN_RESPONSE:
BeginGame(p.joinResponse);
break;
// case PacketType::DISCONNECT:
// //
// break;
// case PacketType::SYNCHRONIZE:
// //
// break;
// case PacketType::PLAYER_NEW:
// //
// break;
// case PacketType::PLAYER_DELETE:
// //
// break;
// case PacketType::PLAYER_MOVE:
// //
// 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 = PacketType::BROADCAST_REQUEST;
netUtil->Send("255.255.255.255", configUtil->Int("server.port"), &p, sizeof(Packet));
serverList.clear();
}
void Lobby::PushServer(BroadcastResponse& bcast) {
ServerEntry entry;
entry.name = bcast.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 = PacketType::JOIN_REQUEST;
netUtil->Send(&server->address, reinterpret_cast<void*>(&p), sizeof(Packet));
}
void Lobby::BeginGame(JoinResponse& response) {
//should be downloading the resources here as well
infoMgr->SetClientIndex(response.clientIndex);
netUtil->Bind(&response.meta.address, GAME_CHANNEL);
SetNextScene(SceneList::INWORLD);
}
@@ -19,26 +19,35 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef LOBBYMENU_HPP_
#define LOBBYMENU_HPP_
#ifndef LOBBY_HPP_
#define LOBBY_HPP_
#include "base_scene.hpp"
#include "image.hpp"
#include "raster_font.hpp"
#include "button.hpp"
#include "defines.hpp"
#include "service_locator.hpp"
#include "packet_type.hpp"
#include "network_queue.hpp"
#include "information_manager.hpp"
#include "config_utility.hpp"
#include "surface_manager.hpp"
#include "udp_network_utility.hpp"
#include "network_packet.hpp"
#include "button.hpp"
#include "raster_font.hpp"
#include <vector>
#include <string>
class LobbyMenu : public BaseScene {
struct ServerEntry {
std::string name;
IPaddress address;
};
class Lobby : public BaseScene {
public:
//Public access members
LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const);
~LobbyMenu();
Lobby();
~Lobby();
protected:
//Frame loop
@@ -54,32 +63,28 @@ protected:
void KeyDown(SDL_KeyboardEvent const&);
void KeyUp(SDL_KeyboardEvent const&);
void HandlePacket(NetworkPacket);
//utilities
int HandlePacket(Packet p);
void BroadcastNetwork();
void PushServer(BroadcastResponse&);
void ConnectToServer(ServerEntry*);
void BeginGame(JoinResponse&);
//global
ConfigUtility& config;
UDPNetworkUtility& network;
int& clientIndex;
//services
ConfigUtility* configUtil = ServiceLocator<ConfigUtility>::Get();
SurfaceManager* surfaceMgr = ServiceLocator<SurfaceManager>::Get();
UDPNetworkUtility* netUtil = ServiceLocator<UDPNetworkUtility>::Get();
InformationManager* infoMgr = ServiceLocator<InformationManager>::Get();
//members
Image image;
Button refreshButton;
Button joinButton;
Button backButton;
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;
ServerInformation* selection = nullptr;
std::vector<ServerEntry> serverList;
ServerEntry* selectedServer = nullptr;
};
#endif
+11 -6
View File
@@ -19,7 +19,7 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "client_application.hpp"
#include "scene_manager.hpp"
#include <stdexcept>
#include <iostream>
@@ -27,16 +27,21 @@
using namespace std;
int main(int, char**) {
cout << "Beginning client" << endl;
#ifdef DEBUG
cout << "Beginning program" << endl;
#endif
try {
ClientApplication::GetInstance()->Init();
ClientApplication::GetInstance()->Proc();
ClientApplication::GetInstance()->Quit();
SceneManager app;
app.Init();
app.Proc();
app.Quit();
}
catch(exception& e) {
cerr << "Fatal exception thrown: " << e.what() << endl;
cerr << "Fatal error: " << e.what() << endl;
return 1;
}
#ifdef DEBUG
cout << "Clean exit" << endl;
#endif
return 0;
}
@@ -21,42 +21,27 @@
*/
#include "main_menu.hpp"
#include <iostream>
using namespace std;
//-------------------------
//Public access members
//-------------------------
MainMenu::MainMenu(ConfigUtility* const argConfig):
config(*argConfig)
{
//setup the utility objects
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
image.SetClipH(image.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
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() {
#ifdef DEBUG
cout << "entering MainMenu" << endl;
#endif
startButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Start");
optionsButton.Setup(50, 100, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Options");
quitButton.Setup(50, 150, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Quit");
}
MainMenu::~MainMenu() {
//
#ifdef DEBUG
cout << "leaving MainMenu" << endl;
#endif
}
//-------------------------
@@ -99,10 +84,10 @@ void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (startButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::LOBBYMENU);
SetNextScene(SceneList::LOBBY);
}
if (optionsButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::OPTIONSMENU);
SetNextScene(SceneList::OPTIONSCREEN);
}
if (quitButton.MouseButtonUp(button) == Button::State::HOVER) {
QuitEvent();
@@ -113,10 +98,6 @@ void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
QuitEvent();
break;
break;
}
}
void MainMenu::KeyUp(SDL_KeyboardEvent const& key) {
//
}
@@ -23,38 +23,32 @@
#define MAINMENU_HPP_
#include "base_scene.hpp"
#include "service_locator.hpp"
#include "config_utility.hpp"
#include "image.hpp"
#include "raster_font.hpp"
#include "surface_manager.hpp"
#include "button.hpp"
class MainMenu : public BaseScene {
public:
//Public access members
MainMenu(ConfigUtility* const);
/* Public access members */
MainMenu();
~MainMenu();
protected:
//Frame loop
/* Frame loop */
void FrameStart();
void Update(double delta);
void FrameEnd();
void Render(SDL_Surface* const);
//Event handlers
/* 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;
SurfaceManager* surfaceMgr = ServiceLocator<SurfaceManager>::Get();
//members
Image image;
RasterFont font;
Button startButton;
Button optionsButton;
Button quitButton;
+7 -12
View File
@@ -1,17 +1,16 @@
#config
INCLUDES+=. scenes ../common ../common/graphics ../common/map ../common/network ../common/ui
LIBS+=libclient.a ../libcommon.a -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL -llua -lsqlite3
LIBDIR=../libs
LOCALLIBS=$(LIBDIR)/out/libCodebase.a $(LIBDIR)/out/libCommon.a
LIB=$(LOCALLIBS) -lSDL_net -lwsock32 -liphlpapi -lmingw32 -lSDLmain -lSDL
INCLUDES=$(LIBDIR)/Codebase $(LIBDIR)/common
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
CSRC=$(wildcard *.c)
SRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
#output
OUTDIR=../out
@@ -19,8 +18,7 @@ OUT=$(addprefix $(OUTDIR)/,client)
#targets
all: $(OBJ) $(OUT)
$(MAKE) -C scenes
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
$(OBJ): | $(OBJDIR)
@@ -35,9 +33,6 @@ $(OUTDIR):
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
@@ -19,84 +19,59 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "options_menu.hpp"
#include "option_screen.hpp"
#include <iostream>
using namespace std;
//-------------------------
//Public access members
//-------------------------
OptionsMenu::OptionsMenu(ConfigUtility* const argConfig):
config(*argConfig)
{
//setup the utility objects
image.LoadSurface(config["dir.interface"] + "button_menu.bmp");
image.SetClipH(image.GetClipH()/3);
font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp");
//pass the utility objects
backButton.SetImage(&image);
backButton.SetFont(&font);
//set the button positions
backButton.SetX(50);
backButton.SetY(50 + image.GetClipH() * 0);
//set the button texts
backButton.SetText("Back");
OptionScreen::OptionScreen() {
#ifdef DEBUG
cout << "entering OptionScreen" << endl;
#endif
backButton.Setup(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Back");
}
OptionsMenu::~OptionsMenu() {
//
OptionScreen::~OptionScreen() {
#ifdef DEBUG
cout << "leaving OptionScreen" << endl;
#endif
}
//-------------------------
//Frame loop
//-------------------------
void OptionsMenu::FrameStart() {
//
}
void OptionsMenu::Update(double delta) {
//
}
void OptionsMenu::FrameEnd() {
//
}
void OptionsMenu::Render(SDL_Surface* const screen) {
void OptionScreen::Render(SDL_Surface* const screen) {
backButton.DrawTo(screen);
font.DrawStringTo("Oh, were you looking for the options screen?", screen, 50, 30);
}
//-------------------------
//Event handlers
//-------------------------
void OptionsMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
void OptionScreen::MouseMotion(SDL_MouseMotionEvent const& motion) {
backButton.MouseMotion(motion);
}
void OptionsMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
void OptionScreen::MouseButtonDown(SDL_MouseButtonEvent const& button) {
backButton.MouseButtonDown(button);
}
void OptionsMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
void OptionScreen::MouseButtonUp(SDL_MouseButtonEvent const& button) {
if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
SetNextScene(SceneList::MAINMENU);
}
}
void OptionsMenu::KeyDown(SDL_KeyboardEvent const& key) {
void OptionScreen::KeyDown(SDL_KeyboardEvent const& key) {
switch(key.keysym.sym) {
case SDLK_ESCAPE:
SetNextScene(SceneList::MAINMENU);
break;
break;
}
}
void OptionsMenu::KeyUp(SDL_KeyboardEvent const& key) {
//
}
@@ -19,42 +19,32 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef OPTIONSMENU_HPP_
#define OPTIONSMENU_HPP_
#ifndef OPTIONSCREEN_HPP_
#define OPTIONSCREEN_HPP_
#include "base_scene.hpp"
#include "service_locator.hpp"
#include "config_utility.hpp"
#include "image.hpp"
#include "raster_font.hpp"
#include "surface_manager.hpp"
#include "button.hpp"
class OptionsMenu : public BaseScene {
class OptionScreen : public BaseScene {
public:
//Public access members
OptionsMenu(ConfigUtility* const);
~OptionsMenu();
/* Public access members */
OptionScreen();
~OptionScreen();
protected:
//Frame loop
void FrameStart();
void Update(double delta);
void FrameEnd();
/* Frame loop */
void Render(SDL_Surface* const);
//Event handlers
/* 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
Image image;
RasterFont font;
SurfaceManager* surfaceMgr = ServiceLocator<SurfaceManager>::Get();
Button backButton;
};
-117
View File
@@ -1,117 +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 "player_character.hpp"
#define WALKING_SPEED 140
void PlayerCharacter::Update(double delta) {
if (diagonal) {
constexpr double d = 1.0/sqrt(2);
position += motion * delta * d;
}
else {
position += motion * delta;
}
sprite.Update(delta);
}
void PlayerCharacter::AdjustDirection(Direction direction) {
//shift the movement in this direction
switch(direction) {
case Direction::NORTH:
if (motion.y >= 0) {
motion.y -= WALKING_SPEED;
}
break;
case Direction::SOUTH:
if (motion.y <= 0) {
motion.y += WALKING_SPEED;
}
break;
case Direction::WEST:
if (motion.x >= 0) {
motion.x -= WALKING_SPEED;
}
break;
case Direction::EAST:
if (motion.x <= 0) {
motion.x += WALKING_SPEED;
}
break;
}
//face the correct direction
ResetDirection();
}
void PlayerCharacter::FaceDirection(Direction direction) {
//this function depends on the format of the sprite sheets
switch(direction) {
case Direction::NORTH:
sprite.SetYIndex(1);
break;
case Direction::SOUTH:
sprite.SetYIndex(0);
break;
case Direction::WEST:
sprite.SetYIndex(2);
break;
case Direction::EAST:
sprite.SetYIndex(3);
break;
}
}
void PlayerCharacter::ResetDirection() {
//base the direction on the character's movement
if (motion.y > 0) {
FaceDirection(Direction::SOUTH);
}
else if (motion.y < 0) {
FaceDirection(Direction::NORTH);
}
else if (motion.x > 0) {
FaceDirection(Direction::EAST);
}
else if (motion.x < 0) {
FaceDirection(Direction::WEST);
}
ResetSpeed();
}
void PlayerCharacter::ResetSpeed() {
//diagonal
if (motion.x != 0 && motion.y != 0) {
sprite.SetDelay(0.1);
diagonal = true;
}
//cardinal
else if (motion != 0) {
sprite.SetDelay(0.1);
diagonal = false;
}
//not moving
else {
sprite.SetDelay(0);
sprite.SetXIndex(0);
diagonal = false;
}
}
-66
View File
@@ -1,66 +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 PLAYERCHARACTER_HPP_
#define PLAYERCHARACTER_HPP_
#include "vector2.hpp"
#include "sprite_sheet.hpp"
class PlayerCharacter {
public:
enum class Direction {
NORTH, SOUTH, EAST, WEST
};
PlayerCharacter() = default;
~PlayerCharacter() = default;
void Update(double delta);
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
Vector2 SetPosition(Vector2 v) { return position = v; }
Vector2 ShiftPosition(Vector2 v) { return position += v; }
Vector2 GetPosition() { return position; }
Vector2 SetMotion(Vector2 v) { return motion = v; }
Vector2 ShiftMotion(Vector2 v) { return motion += v; }
Vector2 GetMotion() { return motion; }
SpriteSheet* GetSprite() { return &sprite; }
private:
Vector2 position;
Vector2 motion;
SpriteSheet sprite;
//for moving diagonally
bool diagonal = false;
};
#endif
+5 -5
View File
@@ -29,12 +29,12 @@ enum class SceneList {
FIRST,
//custom indexes
SPLASHSCREEN,
MAINMENU,
OPTIONSMENU,
LOBBYMENU,
INWORLD,
INCOMBAT,
INWORLD,
LOBBY,
MAINMENU,
OPTIONSCREEN,
SPLASHSCREEN,
};
#endif
@@ -5,7 +5,7 @@
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial ClientApplications, and to alter it and redistribute it
* 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
@@ -19,63 +19,90 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "client_application.hpp"
#include "scene_manager.hpp"
#include <stdexcept>
#include <chrono>
//-------------------------
//Static declarations
//-------------------------
ClientApplication ClientApplication::instance;
//-------------------------
//Scene headers
//-------------------------
//Add the custom scene headers here
#include "splash_screen.hpp"
#include "main_menu.hpp"
#include "options_menu.hpp"
#include "lobby_menu.hpp"
#include "in_world.hpp"
#include "in_combat.hpp"
#include "in_world.hpp"
#include "lobby.hpp"
#include "main_menu.hpp"
#include "option_screen.hpp"
#include "splash_screen.hpp"
//-------------------------
//Public access members
//-------------------------
ClientApplication::ClientApplication() {
SceneManager::SceneManager() {
//
}
ClientApplication::~ClientApplication() {
//
SceneManager::~SceneManager() {
UnloadScene();
}
void ClientApplication::Init() {
//load the prerequisites
config.Load("rsc\\config.cfg");
/* SceneManager::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 created 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.
*/
//initialize SDL
void SceneManager::Init() {
//load the config file
try {
configUtil = ServiceLocator<ConfigUtility>::Set(new ConfigUtility());
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
if (SDL_Init(SDL_INIT_VIDEO)) {
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()) {
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);
//instanciate the remaining services
surfaceMgr = ServiceLocator<SurfaceManager>::Set(new SurfaceManager());
netUtil = ServiceLocator<UDPNetworkUtility>::Set(new UDPNetworkUtility());
infoMgr = ServiceLocator<InformationManager>::Set(new InformationManager());
//initiate the remaining services
netUtil->Open(0, sizeof(Packet));
}
void ClientApplication::Proc() {
void SceneManager::Proc() {
LoadScene(SceneList::FIRST);
//prepare the time system
typedef std::chrono::steady_clock Clock;
typedef std::chrono::high_resolution_clock Clock;
Clock::duration delta(16 * Clock::duration::period::den / std::milli::den);
Clock::time_point simTime = Clock::now();
@@ -109,8 +136,21 @@ void ClientApplication::Proc() {
UnloadScene();
}
void ClientApplication::Quit() {
network.Close();
void SceneManager::Quit() {
//clean up the services
netUtil->Close();
surfaceMgr->FreeAll();
//delete the services
configUtil = ServiceLocator<ConfigUtility>::Set(nullptr);
surfaceMgr = ServiceLocator<SurfaceManager>::Set(nullptr);
netUtil = ServiceLocator<UDPNetworkUtility>::Set(nullptr);
infoMgr = ServiceLocator<InformationManager>::Set(nullptr);
//clean up the scene
UnloadScene();
//deinitialize the APIs
SDLNet_Quit();
SDL_Quit();
}
@@ -119,37 +159,37 @@ void ClientApplication::Quit() {
//Private access members
//-------------------------
void ClientApplication::LoadScene(SceneList sceneIndex) {
void SceneManager::LoadScene(SceneList sceneIndex) {
UnloadScene();
switch(sceneIndex) {
//add scene creation calls here
case SceneList::FIRST:
case SceneList::SPLASHSCREEN:
activeScene = new SplashScreen(&config);
break;
case SceneList::MAINMENU:
activeScene = new MainMenu(&config);
break;
case SceneList::OPTIONSMENU:
activeScene = new OptionsMenu(&config);
break;
case SceneList::LOBBYMENU:
activeScene = new LobbyMenu(&config, &network, &clientIndex);
break;
case SceneList::INWORLD:
activeScene = new InWorld(&config, &network, &clientIndex);
break;
case SceneList::INCOMBAT:
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::SPLASHSCREEN:
activeScene = new SplashScreen();
break;
default:
throw(std::logic_error("Failed to recognize the scene index"));
}
}
void ClientApplication::UnloadScene() {
void SceneManager::UnloadScene() {
delete activeScene;
activeScene = nullptr;
}
@@ -19,39 +19,42 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef CLIENTAPPLICATION_HPP_
#define CLIENTAPPLICATION_HPP_
#ifndef SCENEMANAGER_HPP_
#define SCENEMANAGER_HPP_
#include "scene_list.hpp"
#include "base_scene.hpp"
#include "service_locator.hpp"
#include "packet_type.hpp"
#include "information_manager.hpp"
#include "config_utility.hpp"
#include "network_packet.hpp"
#include "surface_manager.hpp"
#include "udp_network_utility.hpp"
class ClientApplication {
private:
ClientApplication();
~ClientApplication();
static ClientApplication instance;
#include "SDL/SDL.h"
class SceneManager {
public:
static ClientApplication* GetInstance() { return &instance; }
/* Public access members */
SceneManager();
~SceneManager();
void Init();
void Proc();
void Quit();
private:
//Private access members
/* Private access members */
void LoadScene(SceneList sceneIndex);
void UnloadScene();
BaseScene* activeScene = nullptr;
ConfigUtility config;
UDPNetworkUtility network;
int clientIndex = -1; //replace with a struct?
ConfigUtility* configUtil = nullptr;
SurfaceManager* surfaceMgr = nullptr;
UDPNetworkUtility* netUtil = nullptr;
InformationManager* infoMgr = nullptr;
};
#endif
-139
View File
@@ -1,139 +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 "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
@@ -1,74 +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 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
-315
View File
@@ -1,315 +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 "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));
}
-196
View File
@@ -1,196 +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_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;
}
}
-43
View File
@@ -1,43 +0,0 @@
#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
-51
View File
@@ -1,51 +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"
//-------------------------
//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);
}
+86
View File
@@ -0,0 +1,86 @@
/* 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 (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") + "/pokemon_dark_font.bmp");
surfaceMgr->Load("button", configUtil->String("interface") + "/button.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
}
@@ -23,29 +23,32 @@
#define SPLASHSCREEN_HPP_
#include "base_scene.hpp"
#include "defines.hpp"
#include "service_locator.hpp"
#include "config_utility.hpp"
#include "surface_manager.hpp"
#include "image.hpp"
#include <chrono>
class SplashScreen : public BaseScene {
public:
//Public access members
SplashScreen(ConfigUtility* const);
/* Public access members */
SplashScreen();
~SplashScreen();
protected:
//Frame loop
void Update(double delta);
void Render(SDL_Surface* const);
/* Frame loop */
void RunFrame(double delta);
void RenderFrame();
void LoadResources();
//globals
ConfigUtility& config;
//members
std::chrono::steady_clock::time_point startTick;
bool loaded = false;
ConfigUtility* configUtil = ServiceLocator<ConfigUtility>::Get();
SurfaceManager* surfaceMgr = ServiceLocator<SurfaceManager>::Get();
Image logo;
Clock::time_point start = Clock::now();
};
#endif
-145
View File
@@ -1,145 +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 "image.hpp"
#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) {
FreeSurface();
SDL_Surface* p = SDL_LoadBMP(fname.c_str());
if (!p) {
std::ostringstream os;
os << "Failed to load file: " << fname;
throw(std::runtime_error(os.str()));
}
surface = p;
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
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;
}
void Image::FreeSurface() {
if (local) {
SDL_FreeSurface(surface);
local = false;
}
surface = nullptr;
clip = {0, 0, 0, 0};
}
void Image::DrawTo(SDL_Surface* dest, Sint16 x, Sint16 y) {
if (!surface) {
throw(std::logic_error("No image surface to draw"));
}
SDL_Rect sclip = clip, dclip = {x,y};
SDL_BlitSurface(surface, &sclip, dest, &dclip);
}
void Image::SetTransparentColor(Uint8 r, Uint8 g, Uint8 b) {
if (!surface) {
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));
}
void Image::ClearTransparentColor() {
if (!surface) {
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);
}
-102
View File
@@ -1,102 +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 "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;
}
-66
View File
@@ -1,66 +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 SPRITESHEET_HPP_
#define SPRITESHEET_HPP_
#include "image.hpp"
class SpriteSheet {
public:
SpriteSheet() = default;
SpriteSheet(std::string fname, Uint16 xCellCount, Uint16 yCellCount) { LoadSurface(fname, xCellCount, yCellCount); }
SpriteSheet(SDL_Surface* surface, Uint16 xCellCount, Uint16 yCellCount) { SetSurface(surface, xCellCount, yCellCount); }
~SpriteSheet() { FreeSurface(); };
void Update(double delta);
SDL_Surface* LoadSurface(std::string fname, Uint16 xCellCount, Uint16 yCellCount);
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); }
//accessors and mutators
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; }
private:
Image image;
Uint16 xCount = 0, yCount = 0; //number of cells
Uint16 xIndex = 0, yIndex = 0; //current cell being drawn
double delay = 0.0, tick = 0.0;
};
#endif
-47
View File
@@ -1,47 +0,0 @@
#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)
$(MAKE) -C graphics
$(MAKE) -C map
$(MAKE) -C network
$(MAKE) -C ui
$(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
-43
View File
@@ -1,43 +0,0 @@
#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
@@ -1,123 +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 "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
@@ -1,112 +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 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
@@ -1,121 +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 "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
@@ -1,69 +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 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
-59
View File
@@ -1,59 +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 "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
@@ -1,70 +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 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
@@ -1,73 +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 "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"));
}
-106
View File
@@ -1,106 +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 NETWORKPACKET_HPP_
#define NETWORKPACKET_HPP_
#include "SDL/SDL_net.h"
#include "vector2.hpp"
#define PACKET_STRING_SIZE 100
#pragma pack(push, 0)
union NetworkPacket {
//types of packets
enum class Type {
//default: there is something wrong
NONE = 0,
//not used
PING = 1,
PONG = 2,
//Searching for a server to join
BROADCAST_REQUEST = 3,
BROADCAST_RESPONSE = 4,
//try to join the server
JOIN_REQUEST = 5,
JOIN_RESPONSE = 6,
//disconnect from the server
DISCONNECT = 7,
//mass update
SYNCHRONIZE = 8,
//shut down the server
SHUTDOWN = 9,
//Player movement, etc.
PLAYER_NEW = 10,
PLAYER_DELETE = 11,
PLAYER_UPDATE = 12,
};
//metadata on the packet itself
struct Metadata {
Type type;
IPaddress srcAddress;
}meta;
//information about the server
struct ServerInformation {
Metadata meta;
//TODO: version info
char name[PACKET_STRING_SIZE];
//TODO: player count
}serverInfo;
//information about the client
struct ClientInformation {
Metadata meta;
int index;
}clientInfo;
//information about a player
struct PlayerInformation {
Metadata meta;
int clientIndex;
int playerIndex;
char handle[PACKET_STRING_SIZE];
char avatar[PACKET_STRING_SIZE];
Vector2 position;
Vector2 motion;
}playerInfo;
//defaults
NetworkPacket() {
meta.type = Type::NONE;
meta.srcAddress = {0,0};
}
};
#pragma pack(pop)
#endif
-43
View File
@@ -1,43 +0,0 @@
#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
@@ -1,139 +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 "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
@@ -1,91 +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 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
-59
View File
@@ -1,59 +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 "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;
}
-130
View File
@@ -1,130 +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 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
@@ -1,53 +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 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
@@ -1,282 +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 "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
@@ -1,80 +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 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
-43
View File
@@ -1,43 +0,0 @@
#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
-107
View File
@@ -1,107 +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 "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
@@ -1,59 +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 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
@@ -23,8 +23,27 @@
#include <stdexcept>
Button::Button(Sint16 i, Sint16 j, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string s) {
Setup(i, j, imageSurface, fontSurface, s);
}
void Button::Setup(Sint16 i, Sint16 j, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string s) {
x = i;
y = j;
SetSurfaces(imageSurface, fontSurface);
SetText(s);
}
Button::State Button::MouseMotion(SDL_MouseMotionEvent const& motion) {
return CalcState(motion.x, motion.y, motion.state & SDL_BUTTON_LMASK);
if (motion.state & SDL_BUTTON_LMASK) {
return CalcState(motion.x, motion.y, true);
}
else {
return CalcState(motion.x, motion.y, false);
}
return state;
}
Button::State Button::MouseButtonDown(SDL_MouseButtonEvent const& button) {
@@ -42,40 +61,41 @@ Button::State Button::MouseButtonUp(SDL_MouseButtonEvent const& button) {
}
void Button::DrawTo(SDL_Surface* const dest) {
if (!image || !font) {
throw(std::runtime_error("Surface not set for Button"));
}
image->SetClipY(state * image->GetClipH());
image->DrawTo(dest, x, y);
font->DrawStringTo(text, dest, textX + x, textY + y);
image.DrawTo(dest, x, y);
font.DrawStringTo(text, dest, textX + x, textY + y);
}
std::string Button::SetText(std::string t) {
if (!image || !font) {
throw(std::runtime_error("Surface not set for Button"));
}
//one line, cache the position
text = t;
textX = (image->GetClipW() / 2) - (font->GetCharW() * text.size() / 2);
textY = (image->GetClipH() / 2) - (font->GetCharH() / 2);
void Button::SetSurfaces(SDL_Surface* imageSurface, SDL_Surface* fontSurface) {
//graphical stuff
image.SetSurface(imageSurface);
image.SetClipH(image.GetClipH() / 3); //3 phases
font.SetSurface(fontSurface);
//reset textX & textY
SetText(text);
}
std::string Button::SetText(std::string s) {
//one line
text = s;
textX = (image.GetClipW() / 2) - (font.GetCharW() * text.size() / 2);
textY = (image.GetClipH() / 2) - (font.GetCharH() / 2);
return text;
}
Button::State Button::CalcState(Sint16 i, Sint16 j, bool leftPressed) {
if (!image || !font) {
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())
if (i < x || i > (x + image.GetClipW()) ||
j < y || j > (y + image.GetClipH())
) {
image.SetClipY(0);
return state = State::NORMAL;
}
if (leftPressed) {
image.SetClipY(image.GetClipH()*2);
return state = State::PRESSED;
}
else {
image.SetClipY(image.GetClipH());
return state = State::HOVER;
}
}
@@ -27,66 +27,54 @@
#include <string>
/* 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.
*/
//3-phases, no toggle, centred text
class Button {
public:
enum State {
NORMAL = 0, HOVER = 1, PRESSED = 2
enum class State {
NORMAL, HOVER, PRESSED
};
Button() = default;
~Button() = default;
Button(Sint16 x, Sint16 y, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string text = "");
//handle input
void Setup(Sint16 x, Sint16 y, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string text = "");
//return the current state
State MouseMotion(SDL_MouseMotionEvent const&);
State MouseButtonDown(SDL_MouseButtonEvent const&);
State MouseButtonUp(SDL_MouseButtonEvent const&);
State GetState() const {
return state;
}
//yet another draw function
void DrawTo(SDL_Surface* const);
//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; }
//simple accessors and mutators
Sint16 SetX(Sint16 i) { return x = i; }
Sint16 SetY(Sint16 i) { return y = i; }
Sint16 GetX() const { return x; }
Sint16 GetY() const { return y; }
Sint16 SetTextX(Sint16 i) { return textX = i; }
Sint16 SetTextY(Sint16 i) { return textY = i; }
Sint16 GetTextX() const { return textX; }
Sint16 GetTextY() const { return textY; }
void SetSurfaces(SDL_Surface* image, SDL_Surface* font);
State SetState(State s) { return state = s; }
State GetState() const { return state; }
std::string SetText(std::string);
std::string SetText(std::string s);
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 GetTextY() const { return textY; }
private:
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 textX = 0, textY = 0;
//
Sint16 textX = 0, textY = 0; //prevent recalc every loop
Image image;
RasterFont font;
State state = State::NORMAL;
std::string text;
};
@@ -21,9 +21,8 @@
*/
#include "config_utility.hpp"
#include <cstdlib>
#include <fstream>
#include <stdexcept>
#include <fstream>
using namespace std;
@@ -75,31 +74,3 @@ void ConfigUtility::Load(string fname) {
is.close();
}
std::string& ConfigUtility::String(std::string s) {
return table[s];
}
int ConfigUtility::Integer(std::string s) {
std::map<std::string, std::string>::iterator it = table.find(s);
if (it == table.end()) {
return 0;
}
return atoi(it->second.c_str());
}
double ConfigUtility::Double(std::string s) {
std::map<std::string, std::string>::iterator it = table.find(s);
if (it == table.end()) {
return 0.0;
}
return atof(it->second.c_str());
}
bool ConfigUtility::Boolean(std::string s) {
std::map<std::string, std::string>::iterator it = table.find(s);
if (it == table.end()) {
return false;
}
return it->second == "true";
}
@@ -24,32 +24,40 @@
#include <map>
#include <string>
#include <cstdlib>
class ConfigUtility {
public:
ConfigUtility() = default;
ConfigUtility() {}
ConfigUtility(std::string s) { Load(s); }
void Load(std::string fname);
//convert to a type
std::string& String(std::string);
int Integer(std::string);
double Double(std::string);
bool Boolean(std::string);
std::string String(std::string s) {
return table[s];
}
const char* CString(std::string s) {
return table[s].c_str();
}
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) {
return String(s);
return table[s];
}
int Int(std::string s) {
return Integer(s);
}
bool Bool(std::string s) {
int Bool(std::string s) {
return Boolean(s);
}
//OO breaker
std::map<std::string, std::string>* GetMap() {
return &table;
}
+26
View File
@@ -0,0 +1,26 @@
/* 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 "frame_rate.hpp"
int FrameRate::frameCount = 0;
int FrameRate::lastFrameRate = 0;
FrameRate::Clock::time_point FrameRate::tick = FrameRate::Clock::now();
@@ -19,30 +19,30 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef UTILITY_HPP_
#define UTILITY_HPP_
#ifndef FRAMERATE_HPP_
#define FRAMERATE_HPP_
#include <string>
#include <chrono>
int snapToBase(int base, int x);
std::string truncatePath(std::string pathname);
class FrameRate {
public:
typedef std::chrono::high_resolution_clock Clock;
//fixing known bugs in g++
std::string to_string_custom(int i);
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;
FrameRate() = delete;
static int Calculate() {
frameCount++;
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
lastFrameRate = frameCount;
frameCount = 0;
tick = Clock::now();
}
return lastFrameRate;
}
static int GetFrameRate() { return lastFrameRate; }
private:
static int frameCount;
static int lastFrameRate;
static Clock::time_point tick;
};
#endif
+27 -23
View File
@@ -19,32 +19,36 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef TILE_HPP_
#define TILE_HPP_
#include "image.hpp"
//explicitly a POD
struct Tile {
//position relative to the Region
int x, y, depth;
Image::Image(SDL_Surface* p) {
SetSurface(p);
}
//graphics
int width, height;
int tileIndex;
Image::Image(SDL_Surface* p, SDL_Rect r) {
SetSurface(p, r);
}
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;
SDL_Surface* Image::SetSurface(SDL_Surface* p) {
if (!(surface = p)) {
clip = {0, 0, 0, 0};
}
};
else {
clip = {0, 0, (Uint16)surface->w, (Uint16)surface->h};
}
return surface;
}
bool operator<(Tile const& lhs, Tile const& rhs);
bool operator>(Tile const& lhs, Tile const& rhs);
bool operator==(Tile const& lhs, Tile const& rhs);
SDL_Surface* Image::SetSurface(SDL_Surface* const p, SDL_Rect r) {
surface = p;
clip = r;
return surface;
}
#endif
void Image::DrawTo(SDL_Surface* dest, Sint16 x, Sint16 y) {
if (!surface) {
return;
}
SDL_Rect sclip = clip, dclip = {x,y};
SDL_BlitSurface(surface, &sclip, dest, &dclip);
}
@@ -23,26 +23,17 @@
#define IMAGE_HPP_
#include "SDL/SDL.h"
#include <string>
class Image {
public:
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() { FreeSurface(); }
Image(SDL_Surface*);
Image(SDL_Surface*, SDL_Rect);
~Image() = default;
Image& operator=(Image const&);
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_Rect);
SDL_Surface* GetSurface() const { return surface; }
void FreeSurface();
void DrawTo(SDL_Surface* const, Sint16 x, Sint16 y);
@@ -59,15 +50,9 @@ public:
Sint16 GetClipY() const { return clip.y; }
Uint16 GetClipW() const { return clip.w; }
Uint16 GetClipH() const { return clip.h; }
bool GetLocal() const { return local; }
void SetTransparentColor(Uint8 r, Uint8 g, Uint8 b);
void ClearTransparentColor();
protected:
SDL_Surface* surface = nullptr;
SDL_Rect clip = {0, 0, 0, 0};
bool local = false;
};
#endif
@@ -1,21 +1,20 @@
#config
INCLUDES+=. ..
LIBS+=
LIBDIR=..
LOCALLIBS=
LIB=
INCLUDES=
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
CSRC=$(wildcard *.c)
SRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
OUTDIR=../out
OUT=$(addprefix $(OUTDIR)/,libCodebase.a)
#targets
all: $(OBJ) $(OUT)
@@ -34,9 +33,6 @@ $(OUTDIR):
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
@@ -23,9 +23,9 @@
#include <stdexcept>
/* It might be more efficient to render to a different surface (like an Image)
* rather than calling this function with all of it's '%' and '/'.
*/
RasterFont::RasterFont(SDL_Surface* p) {
SetSurface(p);
}
void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x, Sint16 y) {
if (!image.GetSurface()) {
@@ -34,27 +34,16 @@ void RasterFont::DrawStringTo(std::string s, SDL_Surface* const dest, Sint16 x,
const Uint16 w = image.GetClipW();
const Uint16 h = image.GetClipH();
for (int i = 0; i < s.size(); i++) {
image.SetClipX(s[i] % 16 * w);
image.SetClipY(s[i] / 16 * h);
image.SetClipX(s[i] % w * w);
image.SetClipY(s[i] / h * h);
image.DrawTo(dest, x + i * w, y);
}
}
/* Note: This class can only take a raster font with 16*16 characters, and the
* indevidual characters must have the same dimensions. Overall this class is too
* restrictive; I suggest using a 3rd party library.
*/
SDL_Surface* RasterFont::LoadSurface(std::string fname) {
image.LoadSurface(fname);
image.SetClipW(image.GetSurface()->w/16);
image.SetClipH(image.GetSurface()->h/16);
return image.GetSurface();
}
SDL_Surface* RasterFont::SetSurface(SDL_Surface* p) {
image.SetSurface(p);
image.SetClipW(image.GetSurface()->w/16);
image.SetClipH(image.GetSurface()->h/16);
if (image.SetSurface(p)) {
image.SetClipW(image.GetSurface()->w/16);
image.SetClipH(image.GetSurface()->h/16);
}
return image.GetSurface();
}
@@ -24,29 +24,21 @@
#include "image.hpp"
#include <string>
class RasterFont {
public:
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);
~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);
//Accessors and Mutators
SDL_Surface* LoadSurface(std::string);
SDL_Surface* SetSurface(SDL_Surface*);
SDL_Surface* GetSurface() const { return image.GetSurface(); }
void FreeSurface() { image.FreeSurface(); }
Uint16 GetCharW() const { return image.GetClipW(); }
Uint16 GetCharH() const { return image.GetClipH(); }
Uint16 GetCharW() { return image.GetClipW(); }
Uint16 GetCharH() { return image.GetClipH(); }
private:
Image image;
};
@@ -19,26 +19,26 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "tile.hpp"
#include "sprite_sheet.hpp"
bool operator<(Tile const& lhs, Tile const& rhs) {
//sort by depth -> y -> x
if (lhs.depth == rhs.depth) {
if (lhs.y == rhs.y) {
return lhs.x < rhs.x;
SpriteSheet::SpriteSheet(SDL_Surface* s, Uint16 w, Uint16 h) {
SetSurface(s, w, h);
}
void SpriteSheet::Update(double delta) {
if (interval && (ticks += delta) >= interval) {
if (++currentFrame >= maxFrames) {
currentFrame = 0;
}
return lhs.y < rhs.y;
ticks = 0;
}
return lhs.depth < rhs.depth;
image.SetClipX(currentFrame * image.GetClipW());
image.SetClipY(currentStrip * image.GetClipH());
}
inline bool operator>(Tile const& lhs, Tile const& rhs) {
//wrap the other operator
return rhs < lhs;
}
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);
SDL_Surface* SpriteSheet::SetSurface(SDL_Surface* const s, Uint16 w, Uint16 h) {
image.SetSurface(s, {0, 0, w, h});
currentFrame = 0; maxFrames = image.GetSurface()->w / image.GetClipW();
currentStrip = 0; maxStrips = image.GetSurface()->h / image.GetClipH();
interval = ticks = 0;
}
+66
View File
@@ -0,0 +1,66 @@
/* 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 SPRITESHEET_HPP_
#define SPRITESHEET_HPP_
#include "image.hpp"
#include "SDL/SDL.h"
class SpriteSheet {
public:
SpriteSheet() = default;
SpriteSheet(SDL_Surface*, Uint16 w, Uint16 h);
~SpriteSheet() = default;
void Update(double delta);
SDL_Surface* SetSurface(SDL_Surface* const, Uint16 w, Uint16 h);
SDL_Surface* GetSurface() const {
return image.GetSurface();
}
void DrawTo(SDL_Surface* const dest, Sint16 x, Sint16 y) {
image.DrawTo(dest, x, y);
}
//Accessors and Mutators
double SetInterval(double i) { return interval = i; }
double GetInterval() const { return interval; }
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:
Image image;
int currentFrame = 0, maxFrames = 0;
int currentStrip = 0, maxStrips = 0;
double interval = 0, ticks = 0;
};
#endif
+85
View File
@@ -0,0 +1,85 @@
/* 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>
SurfaceManager::~SurfaceManager() noexcept {
FreeAll();
}
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;
}
@@ -19,33 +19,31 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef TILESHEETMANAGER_HPP_
#define TILESHEETMANAGER_HPP_
#ifndef SURFACEMANAGER_HPP_
#define SURFACEMANAGER_HPP_
#include "tile_sheet.hpp"
#include "SDL/SDL.h"
#include <map>
#include <string>
class TileSheetManager {
class SurfaceManager {
public:
TileSheetManager() = default;
~TileSheetManager() = default;
SurfaceManager() = default;
~SurfaceManager() noexcept;
TileSheet* LoadSheet(std::string fname, Uint16 w, Uint16 h);
TileSheet* GetSheet(std::string name);
TileSheet* GetSheetByIndex(int tileIndex);
void UnloadSheet(std::string name);
SDL_Surface* Load(std::string key, std::string fname);
SDL_Surface* Reload(std::string key, std::string fname);
SDL_Surface* Get(std::string key);
SDL_Surface* Set(std::string key, SDL_Surface* ptr);
void Free(std::string key);
void FreeAll();
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; }
SDL_Surface* operator[](std::string key) { return Get(key); };
private:
std::map<std::string, TileSheet> sheetMap;
int rangeEnd = 0;
SDL_Surface* LoadSurface(std::string key, std::string fname);
typedef std::map<std::string, SDL_Surface*> MapType;
MapType surfaceMap;
};
#endif
@@ -22,7 +22,7 @@
#ifndef UDPNETWORKUTILITY_HPP_
#define UDPNETWORKUTILITY_HPP_
#include "SDL/SDL_net.h"
#include "SDL_net/SDL_net.h"
class UDPNetworkUtility {
public:
@@ -32,9 +32,17 @@ public:
void Open(int port, int packSize);
void Close();
//bind to a channel
int Bind(const char* ip, int port, int channel = -1);
int Bind(IPaddress* add, int channel = -1);
//bind to an available channel
int Bind(const char* ip, int port) {
Bind(ip, port, -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);
IPaddress* GetIPAddress(int channel) {
@@ -27,14 +27,11 @@
class Vector2 {
public:
double x, y;
//This is explicitly a POD
double x = 0, y = 0;
Vector2() = default;
Vector2(double i, double j): x(i), y(j) {};
~Vector2() = default;
Vector2& operator=(Vector2 const&) = default;
Vector2(double i, double j) {
x = i; y = j;
}
double Length() const {
return sqrt(x*x+y*y);
}
@@ -44,57 +41,31 @@ public:
double operator[](size_t i) {
if (i >= 2)
throw(std::domain_error("Out of range"));
throw(std::runtime_error("Out of range"));
return *(&x+i);
}
//Arithmetic operators
Vector2 operator+(Vector2 v) const {
Vector2 ret;
ret.x = x + v.x;
ret.y = y + v.y;
return ret;
}
Vector2 operator-(Vector2 v) const {
Vector2 ret;
ret.x = x - v.x;
ret.y = y - v.y;
return ret;
}
Vector2 operator*(Vector2 v) const {
Vector2 ret;
ret.x = x * v.x;
ret.y = y * v.y;
return ret;
}
Vector2 operator*(double d) const {
Vector2 ret;
ret.x = x * d;
ret.y = y * d;
return ret;
}
Vector2 operator+(Vector2 v) const { return Vector2(x + v.x, y + v.y); }
Vector2 operator-(Vector2 v) const { return Vector2(x - v.x, y - v.y); }
Vector2 operator*(Vector2 v) const { return Vector2(x * v.x, y * v.y); }
Vector2 operator*(double d) const { return Vector2(x * d, y * d); }
Vector2 operator/(Vector2 v) {
if (!v.x || !v.y)
throw(std::domain_error("Divide by zero"));
Vector2 ret;
ret.x = x / v.x;
ret.y = y / v.y;
return ret;
throw(std::runtime_error("Divide by zero"));
return Vector2(x / v.x, y / v.y);
}
Vector2 operator/(double d) {
if (!d)
throw(std::domain_error("Divide by zero"));
Vector2 ret;
ret.x = x / d;
ret.y = y / d;
return ret;
throw(std::runtime_error("Divide by zero"));
return Vector2(x / d, y / d);
}
bool operator==(Vector2 v) { return (x == v.x && y == v.y); }
bool operator!=(Vector2 v) { return (x != v.x || y != v.y); }
//member templates (curry the above operators)
//templates
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; }
@@ -103,13 +74,4 @@ public:
template<typename T> bool operator!=(T t) { return (x != t || y != t); }
};
//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> bool operator==(T t, Vector2 v) { return v == t; }
template<typename T> bool operator!=(T t, Vector2 v) { return v != t; }
#endif
+452
View File
@@ -0,0 +1,452 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
*/
/* $Id$ */
#ifndef _SDL_NET_H
#define _SDL_NET_H
#include "SDL/SDL.h"
#include "SDL/SDL_endian.h"
#include "SDL/SDL_version.h"
#include "SDL/begin_code.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
*/
#define SDL_NET_MAJOR_VERSION 1
#define SDL_NET_MINOR_VERSION 2
#define SDL_NET_PATCHLEVEL 8
/* This macro can be used to fill a version structure with the compile-time
* version of the SDL_net library.
*/
#define SDL_NET_VERSION(X) \
{ \
(X)->major = SDL_NET_MAJOR_VERSION; \
(X)->minor = SDL_NET_MINOR_VERSION; \
(X)->patch = SDL_NET_PATCHLEVEL; \
}
/* This function gets the version of the dynamically linked SDL_net library.
it should NOT be used to fill a version structure, instead you should
use the SDL_NET_VERSION() macro.
*/
extern DECLSPEC const SDL_version * SDLCALL SDLNet_Linked_Version(void);
/* Initialize/Cleanup the network API
SDL must be initialized before calls to functions in this library,
because this library uses utility functions from the SDL library.
*/
extern DECLSPEC int SDLCALL SDLNet_Init(void);
extern DECLSPEC void SDLCALL SDLNet_Quit(void);
/***********************************************************************/
/* IPv4 hostname resolution API */
/***********************************************************************/
typedef struct {
Uint32 host; /* 32-bit IPv4 host address */
Uint16 port; /* 16-bit protocol port */
} IPaddress;
/* Resolve a host name and port to an IP address in network form.
If the function succeeds, it will return 0.
If the host couldn't be resolved, the host portion of the returned
address will be INADDR_NONE, and the function will return -1.
If 'host' is NULL, the resolved host will be set to INADDR_ANY.
*/
#ifndef INADDR_ANY
#define INADDR_ANY 0x00000000
#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xFFFFFFFF
#endif
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif
#ifndef INADDR_BROADCAST
#define INADDR_BROADCAST 0xFFFFFFFF
#endif
extern DECLSPEC int SDLCALL SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port);
/* Resolve an ip address to a host name in canonical form.
If the ip couldn't be resolved, this function returns NULL,
otherwise a pointer to a static buffer containing the hostname
is returned. Note that this function is not thread-safe.
*/
extern DECLSPEC const char * SDLCALL SDLNet_ResolveIP(const IPaddress *ip);
/* Get the addresses of network interfaces on this system.
This returns the number of addresses saved in 'addresses'
*/
extern DECLSPEC int SDLCALL SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount);
/***********************************************************************/
/* TCP network API */
/***********************************************************************/
typedef struct _TCPsocket *TCPsocket;
/* Open a TCP network socket
If ip.host is INADDR_NONE or INADDR_ANY, this creates a local server
socket on the given port, otherwise a TCP connection to the remote
host and port is attempted. The address passed in should already be
swapped to network byte order (addresses returned from
SDLNet_ResolveHost() are already in the correct form).
The newly created socket is returned, or NULL if there was an error.
*/
extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Open(IPaddress *ip);
/* Accept an incoming connection on the given server socket.
The newly created socket is returned, or NULL if there was an error.
*/
extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Accept(TCPsocket server);
/* Get the IP address of the remote system associated with the socket.
If the socket is a server socket, this function returns NULL.
*/
extern DECLSPEC IPaddress * SDLCALL SDLNet_TCP_GetPeerAddress(TCPsocket sock);
/* Send 'len' bytes of 'data' over the non-server socket 'sock'
This function returns the actual amount of data sent. If the return value
is less than the amount of data sent, then either the remote connection was
closed, or an unknown socket error occurred.
*/
extern DECLSPEC int SDLCALL SDLNet_TCP_Send(TCPsocket sock, const void *data,
int len);
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
and store them in the buffer pointed to by 'data'.
This function returns the actual amount of data received. If the return
value is less than or equal to zero, then either the remote connection was
closed, or an unknown socket error occurred.
*/
extern DECLSPEC int SDLCALL SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen);
/* Close a TCP network socket */
extern DECLSPEC void SDLCALL SDLNet_TCP_Close(TCPsocket sock);
/***********************************************************************/
/* UDP network API */
/***********************************************************************/
/* The maximum channels on a a UDP socket */
#define SDLNET_MAX_UDPCHANNELS 150
/* The maximum addresses bound to a single UDP socket channel */
#define SDLNET_MAX_UDPADDRESSES 1
typedef struct _UDPsocket *UDPsocket;
typedef struct {
int channel; /* The src/dst channel of the packet */
Uint8 *data; /* The packet data */
int len; /* The length of the packet data */
int maxlen; /* The size of the data buffer */
int status; /* packet status after sending */
IPaddress address; /* The source/dest address of an incoming/outgoing packet */
} UDPpacket;
/* Allocate/resize/free a single UDP packet 'size' bytes long.
The new packet is returned, or NULL if the function ran out of memory.
*/
extern DECLSPEC UDPpacket * SDLCALL SDLNet_AllocPacket(int size);
extern DECLSPEC int SDLCALL SDLNet_ResizePacket(UDPpacket *packet, int newsize);
extern DECLSPEC void SDLCALL SDLNet_FreePacket(UDPpacket *packet);
/* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets,
each 'size' bytes long.
A pointer to the first packet in the array is returned, or NULL if the
function ran out of memory.
*/
extern DECLSPEC UDPpacket ** SDLCALL SDLNet_AllocPacketV(int howmany, int size);
extern DECLSPEC void SDLCALL SDLNet_FreePacketV(UDPpacket **packetV);
/* Open a UDP network socket
If 'port' is non-zero, the UDP socket is bound to a local port.
The 'port' should be given in native byte order, but is used
internally in network (big endian) byte order, in addresses, etc.
This allows other systems to send to this socket via a known port.
*/
extern DECLSPEC UDPsocket SDLCALL SDLNet_UDP_Open(Uint16 port);
/* Set the percentage of simulated packet loss for packets sent on the socket.
*/
extern DECLSPEC void SDLCALL SDLNet_UDP_SetPacketLoss(UDPsocket sock, int percent);
/* Bind the address 'address' to the requested channel on the UDP socket.
If the channel is -1, then the first unbound channel will be bound with
the given address as it's primary address.
If the channel is already bound, this new address will be added to the
list of valid source addresses for packets arriving on the channel.
If the channel is not already bound, then the address becomes the primary
address, to which all outbound packets on the channel are sent.
This function returns the channel which was bound, or -1 on error.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_Bind(UDPsocket sock, int channel, const IPaddress *address);
/* Unbind all addresses from the given channel */
extern DECLSPEC void SDLCALL SDLNet_UDP_Unbind(UDPsocket sock, int channel);
/* Get the primary IP address of the remote system associated with the
socket and channel. If the channel is -1, then the primary IP port
of the UDP socket is returned -- this is only meaningful for sockets
opened with a specific port.
If the channel is not bound and not -1, this function returns NULL.
*/
extern DECLSPEC IPaddress * SDLCALL SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel);
/* Send a vector of packets to the the channels specified within the packet.
If the channel specified in the packet is -1, the packet will be sent to
the address in the 'src' member of the packet.
Each packet will be updated with the status of the packet after it has
been sent, -1 if the packet send failed.
This function returns the number of packets sent.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets);
/* Send a single packet to the specified channel.
If the channel specified in the packet is -1, the packet will be sent to
the address in the 'src' member of the packet.
The packet will be updated with the status of the packet after it has
been sent.
This function returns 1 if the packet was sent, or 0 on error.
NOTE:
The maximum size of the packet is limited by the MTU (Maximum Transfer Unit)
of the transport medium. It can be as low as 250 bytes for some PPP links,
and as high as 1500 bytes for ethernet.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet);
/* Receive a vector of pending packets from the UDP socket.
The returned packets contain the source address and the channel they arrived
on. If they did not arrive on a bound channel, the the channel will be set
to -1.
The channels are checked in highest to lowest order, so if an address is
bound to multiple channels, the highest channel with the source address
bound will be returned.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets);
/* Receive a single packet from the UDP socket.
The returned packet contains the source address and the channel it arrived
on. If it did not arrive on a bound channel, the the channel will be set
to -1.
The channels are checked in highest to lowest order, so if an address is
bound to multiple channels, the highest channel with the source address
bound will be returned.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
extern DECLSPEC int SDLCALL SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet);
/* Close a UDP network socket */
extern DECLSPEC void SDLCALL SDLNet_UDP_Close(UDPsocket sock);
/***********************************************************************/
/* Hooks for checking sockets for available data */
/***********************************************************************/
typedef struct _SDLNet_SocketSet *SDLNet_SocketSet;
/* Any network socket can be safely cast to this socket type */
typedef struct _SDLNet_GenericSocket {
int ready;
} *SDLNet_GenericSocket;
/* Allocate a socket set for use with SDLNet_CheckSockets()
This returns a socket set for up to 'maxsockets' sockets, or NULL if
the function ran out of memory.
*/
extern DECLSPEC SDLNet_SocketSet SDLCALL SDLNet_AllocSocketSet(int maxsockets);
/* Add a socket to a set of sockets to be checked for available data */
#define SDLNet_TCP_AddSocket(set, sock) \
SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
#define SDLNet_UDP_AddSocket(set, sock) \
SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
extern DECLSPEC int SDLCALL SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock);
/* Remove a socket from a set of sockets to be checked for available data */
#define SDLNet_TCP_DelSocket(set, sock) \
SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
#define SDLNet_UDP_DelSocket(set, sock) \
SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
extern DECLSPEC int SDLCALL SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock);
/* This function checks to see if data is available for reading on the
given set of sockets. If 'timeout' is 0, it performs a quick poll,
otherwise the function returns when either data is available for
reading, or the timeout in milliseconds has elapsed, which ever occurs
first. This function returns the number of sockets ready for reading,
or -1 if there was an error with the select() system call.
*/
extern DECLSPEC int SDLCALL SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout);
/* After calling SDLNet_CheckSockets(), you can use this function on a
socket that was in the socket set, to find out if data is available
for reading.
*/
#define SDLNet_SocketReady(sock) \
((sock != NULL) && SDL_reinterpret_cast(SDLNet_GenericSocket, sock)->ready)
/* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
extern DECLSPEC void SDLCALL SDLNet_FreeSocketSet(SDLNet_SocketSet set);
/***********************************************************************/
/* Platform-independent data conversion functions */
/***********************************************************************/
/* Write a 16/32 bit value to network packet buffer */
extern DECLSPEC void SDLCALL SDLNet_Write16(Uint16 value, void *area);
extern DECLSPEC void SDLCALL SDLNet_Write32(Uint32 value, void *area);
/* Read a 16/32 bit value from network packet buffer */
extern DECLSPEC Uint16 SDLCALL SDLNet_Read16(void *area);
extern DECLSPEC Uint32 SDLCALL SDLNet_Read32(void *area);
/***********************************************************************/
/* Error reporting functions */
/***********************************************************************/
/* We'll use SDL's functions for error reporting */
#define SDLNet_SetError SDL_SetError
#define SDLNet_GetError SDL_GetError
/* I'm eventually going to try to disentangle SDL_net from SDL, thus making
SDL_net an independent X-platform networking toolkit. Not today though....
extern no_parse_DECLSPEC void SDLCALL SDLNet_SetError(const char *fmt, ...);
extern no_parse_DECLSPEC char * SDLCALL SDLNet_GetError(void);
*/
/* Inline macro functions to read/write network data */
/* Warning, some systems have data access alignment restrictions */
#if defined(sparc) || defined(mips)
#define SDL_DATA_ALIGNED 1
#endif
#ifndef SDL_DATA_ALIGNED
#define SDL_DATA_ALIGNED 0
#endif
/* Write a 16 bit value to network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Write16(value, areap) \
(*SDL_reinterpret_cast(Uint16 *, areap) = SDL_SwapBE16(value))
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Write16(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[0] = (value >> 8) & 0xFF; \
area[1] = value & 0xFF; \
} while ( 0 )
#else
#define SDLNet_Write16(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[1] = (value >> 8) & 0xFF; \
area[0] = value & 0xFF; \
} while ( 0 )
#endif
#endif /* !SDL_DATA_ALIGNED */
/* Write a 32 bit value to network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Write32(value, areap) \
*SDL_reinterpret_cast(Uint32 *, areap) = SDL_SwapBE32(value);
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Write32(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[0] = (value >> 24) & 0xFF; \
area[1] = (value >> 16) & 0xFF; \
area[2] = (value >> 8) & 0xFF; \
area[3] = value & 0xFF; \
} while ( 0 )
#else
#define SDLNet_Write32(value, areap) \
do \
{ \
Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap); \
area[3] = (value >> 24) & 0xFF; \
area[2] = (value >> 16) & 0xFF; \
area[1] = (value >> 8) & 0xFF; \
area[0] = value & 0xFF; \
} while ( 0 )
#endif
#endif /* !SDL_DATA_ALIGNED */
/* Read a 16 bit value from network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Read16(areap) \
(SDL_SwapBE16(*SDL_reinterpret_cast(Uint16 *, areap)))
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Read16(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[0] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[1] << 0)
#else
#define SDLNet_Read16(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0)
#endif
#endif /* !SDL_DATA_ALIGNED */
/* Read a 32 bit value from network packet buffer */
#if !SDL_DATA_ALIGNED
#define SDLNet_Read32(areap) \
(SDL_SwapBE32(*SDL_reinterpret_cast(Uint32 *, areap)))
#else
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define SDLNet_Read32(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[0] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 16) | \
((SDL_reinterpret_cast(Uint8 *, areap))[2] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[3] << 0)
#else
#define SDLNet_Read32(areap) \
(((SDL_reinterpret_cast(Uint8 *, areap))[3] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 16) | \
((SDL_reinterpret_cast(Uint8 *, areap))[1] << 8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] << 0)
#endif
#endif /* !SDL_DATA_ALIGNED */
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#include "SDL/close_code.h"
#endif /* _SDL_NET_H */
+269
View File
@@ -0,0 +1,269 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
*/
/* $Id$ */
#include <string.h>
#include "SDL/SDL_endian.h"
#include "SDLnetsys.h"
#include "SDL_net.h"
const SDL_version *SDLNet_Linked_Version(void)
{
static SDL_version linked_version;
SDL_NET_VERSION(&linked_version);
return(&linked_version);
}
/* Since the UNIX/Win32/BeOS code is so different from MacOS,
we'll just have two completely different sections here.
*/
static int SDLNet_started = 0;
#ifndef __USE_W32_SOCKETS
#include <signal.h>
#endif
#ifndef __USE_W32_SOCKETS
int SDLNet_GetLastError(void)
{
return errno;
}
void SDLNet_SetLastError(int err)
{
errno = err;
}
#endif
/* Initialize/Cleanup the network API */
int SDLNet_Init(void)
{
if ( !SDLNet_started ) {
#ifdef __USE_W32_SOCKETS
/* Start up the windows networking */
WORD version_wanted = MAKEWORD(1,1);
WSADATA wsaData;
if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
SDLNet_SetError("Couldn't initialize Winsock 1.1\n");
return(-1);
}
#else
/* SIGPIPE is generated when a remote socket is closed */
void (*handler)(int);
handler = signal(SIGPIPE, SIG_IGN);
if ( handler != SIG_DFL ) {
signal(SIGPIPE, handler);
}
#endif
}
++SDLNet_started;
return(0);
}
void SDLNet_Quit(void)
{
if ( SDLNet_started == 0 ) {
return;
}
if ( --SDLNet_started == 0 ) {
#ifdef __USE_W32_SOCKETS
/* Clean up windows networking */
if ( WSACleanup() == SOCKET_ERROR ) {
if ( WSAGetLastError() == WSAEINPROGRESS ) {
#ifndef _WIN32_WCE
WSACancelBlockingCall();
#endif
WSACleanup();
}
}
#else
/* Restore the SIGPIPE handler */
void (*handler)(int);
handler = signal(SIGPIPE, SIG_DFL);
if ( handler != SIG_IGN ) {
signal(SIGPIPE, handler);
}
#endif
}
}
/* Resolve a host name and port to an IP address in network form */
int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port)
{
int retval = 0;
/* Perform the actual host resolution */
if ( host == NULL ) {
address->host = INADDR_ANY;
} else {
address->host = inet_addr(host);
if ( address->host == INADDR_NONE ) {
struct hostent *hp;
hp = gethostbyname(host);
if ( hp ) {
memcpy(&address->host,hp->h_addr,hp->h_length);
} else {
retval = -1;
}
}
}
address->port = SDL_SwapBE16(port);
/* Return the status */
return(retval);
}
/* Resolve an ip address to a host name in canonical form.
If the ip couldn't be resolved, this function returns NULL,
otherwise a pointer to a static buffer containing the hostname
is returned. Note that this function is not thread-safe.
*/
/* Written by Miguel Angel Blanch.
* Main Programmer of Arianne RPG.
* http://come.to/arianne_rpg
*/
const char *SDLNet_ResolveIP(const IPaddress *ip)
{
struct hostent *hp;
struct in_addr in;
hp = gethostbyaddr((const char *)&ip->host, sizeof(ip->host), AF_INET);
if ( hp != NULL ) {
return hp->h_name;
}
in.s_addr = ip->host;
return inet_ntoa(in);
}
int SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount)
{
int count = 0;
#ifdef SIOCGIFCONF
/* Defined on Mac OS X */
#ifndef _SIZEOF_ADDR_IFREQ
#define _SIZEOF_ADDR_IFREQ sizeof
#endif
SOCKET sock;
struct ifconf conf;
char data[4096];
struct ifreq *ifr;
struct sockaddr_in *sock_addr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if ( sock == INVALID_SOCKET ) {
return 0;
}
conf.ifc_len = sizeof(data);
conf.ifc_buf = (caddr_t) data;
if ( ioctl(sock, SIOCGIFCONF, &conf) < 0 ) {
closesocket(sock);
return 0;
}
ifr = (struct ifreq*)data;
while ((char*)ifr < data+conf.ifc_len) {
if (ifr->ifr_addr.sa_family == AF_INET) {
if (count < maxcount) {
sock_addr = (struct sockaddr_in*)&ifr->ifr_addr;
addresses[count].host = sock_addr->sin_addr.s_addr;
addresses[count].port = sock_addr->sin_port;
}
++count;
}
ifr = (struct ifreq*)((char*)ifr + _SIZEOF_ADDR_IFREQ(*ifr));
}
closesocket(sock);
#elif defined(__WIN32__)
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter;
PIP_ADDR_STRING pAddress;
DWORD dwRetVal = 0;
ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);
pAdapterInfo = (IP_ADAPTER_INFO *) SDL_malloc(sizeof (IP_ADAPTER_INFO));
if (pAdapterInfo == NULL) {
return 0;
}
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == ERROR_BUFFER_OVERFLOW) {
pAdapterInfo = (IP_ADAPTER_INFO *) SDL_realloc(pAdapterInfo, ulOutBufLen);
if (pAdapterInfo == NULL) {
return 0;
}
dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
}
if (dwRetVal == NO_ERROR) {
for (pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next) {
for (pAddress = &pAdapterInfo->IpAddressList; pAddress; pAddress = pAddress->Next) {
if (count < maxcount) {
addresses[count].host = inet_addr(pAddress->IpAddress.String);
addresses[count].port = 0;
}
++count;
}
}
}
SDL_free(pAdapterInfo);
#endif
return count;
}
#if !SDL_DATA_ALIGNED /* function versions for binary compatibility */
/* Write a 16 bit value to network packet buffer */
#undef SDLNet_Write16
void SDLNet_Write16(Uint16 value, void *areap)
{
(*(Uint16 *)(areap) = SDL_SwapBE16(value));
}
/* Write a 32 bit value to network packet buffer */
#undef SDLNet_Write32
void SDLNet_Write32(Uint32 value, void *areap)
{
*(Uint32 *)(areap) = SDL_SwapBE32(value);
}
/* Read a 16 bit value from network packet buffer */
#undef SDLNet_Read16
Uint16 SDLNet_Read16(void *areap)
{
return (SDL_SwapBE16(*(Uint16 *)(areap)));
}
/* Read a 32 bit value from network packet buffer */
#undef SDLNet_Read32
Uint32 SDLNet_Read32(void *areap)
{
return (SDL_SwapBE32(*(Uint32 *)(areap)));
}
#endif /* !SDL_DATA_ALIGNED */
+295
View File
@@ -0,0 +1,295 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
*/
/* $Id$ */
#include "SDLnetsys.h"
#include "SDL_net.h"
/* The network API for TCP sockets */
/* Since the UNIX/Win32/BeOS code is so different from MacOS,
we'll just have two completely different sections here.
*/
struct _TCPsocket {
int ready;
SOCKET channel;
IPaddress remoteAddress;
IPaddress localAddress;
int sflag;
};
/* Open a TCP network socket
If 'remote' is NULL, this creates a local server socket on the given port,
otherwise a TCP connection to the remote host and port is attempted.
The newly created socket is returned, or NULL if there was an error.
*/
TCPsocket SDLNet_TCP_Open(IPaddress *ip)
{
TCPsocket sock;
struct sockaddr_in sock_addr;
/* Allocate a TCP socket structure */
sock = (TCPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
goto error_return;
}
/* Open the socket */
sock->channel = socket(AF_INET, SOCK_STREAM, 0);
if ( sock->channel == INVALID_SOCKET ) {
SDLNet_SetError("Couldn't create socket");
goto error_return;
}
/* Connect to remote, or bind locally, as appropriate */
if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) {
// ######### Connecting to remote
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = ip->host;
sock_addr.sin_port = ip->port;
/* Connect to the remote host */
if ( connect(sock->channel, (struct sockaddr *)&sock_addr,
sizeof(sock_addr)) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't connect to remote host");
goto error_return;
}
sock->sflag = 0;
} else {
// ########## Binding locally
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = INADDR_ANY;
sock_addr.sin_port = ip->port;
/*
* Windows gets bad mojo with SO_REUSEADDR:
* http://www.devolution.com/pipermail/sdl/2005-September/070491.html
* --ryan.
*/
#ifndef WIN32
/* allow local address reuse */
{ int yes = 1;
setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
}
#endif
/* Bind the socket for listening */
if ( bind(sock->channel, (struct sockaddr *)&sock_addr,
sizeof(sock_addr)) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't bind to local port");
goto error_return;
}
if ( listen(sock->channel, 5) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't listen to local port");
goto error_return;
}
/* Set the socket to non-blocking mode for accept() */
#if defined(__BEOS__) && defined(SO_NONBLOCK)
/* On BeOS r5 there is O_NONBLOCK but it's for files only */
{
long b = 1;
setsockopt(sock->channel, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
}
#elif defined(O_NONBLOCK)
{
fcntl(sock->channel, F_SETFL, O_NONBLOCK);
}
#elif defined(WIN32)
{
unsigned long mode = 1;
ioctlsocket (sock->channel, FIONBIO, &mode);
}
#elif defined(__OS2__)
{
int dontblock = 1;
ioctl(sock->channel, FIONBIO, &dontblock);
}
#else
#warning How do we set non-blocking mode on other operating systems?
#endif
sock->sflag = 1;
}
sock->ready = 0;
#ifdef TCP_NODELAY
/* Set the nodelay TCP option for real-time games */
{ int yes = 1;
setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes));
}
#endif /* TCP_NODELAY */
/* Fill in the channel host address */
sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
sock->remoteAddress.port = sock_addr.sin_port;
/* The socket is ready */
return(sock);
error_return:
SDLNet_TCP_Close(sock);
return(NULL);
}
/* Accept an incoming connection on the given server socket.
The newly created socket is returned, or NULL if there was an error.
*/
TCPsocket SDLNet_TCP_Accept(TCPsocket server)
{
TCPsocket sock;
struct sockaddr_in sock_addr;
socklen_t sock_alen;
/* Only server sockets can accept */
if ( ! server->sflag ) {
SDLNet_SetError("Only server sockets can accept()");
return(NULL);
}
server->ready = 0;
/* Allocate a TCP socket structure */
sock = (TCPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
goto error_return;
}
/* Accept a new TCP connection on a server socket */
sock_alen = sizeof(sock_addr);
sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr,
&sock_alen);
if ( sock->channel == INVALID_SOCKET ) {
SDLNet_SetError("accept() failed");
goto error_return;
}
#ifdef WIN32
{
/* passing a zero value, socket mode set to block on */
unsigned long mode = 0;
ioctlsocket (sock->channel, FIONBIO, &mode);
}
#elif defined(O_NONBLOCK)
{
int flags = fcntl(sock->channel, F_GETFL, 0);
fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK);
}
#endif /* WIN32 */
sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
sock->remoteAddress.port = sock_addr.sin_port;
sock->sflag = 0;
sock->ready = 0;
/* The socket is ready */
return(sock);
error_return:
SDLNet_TCP_Close(sock);
return(NULL);
}
/* Get the IP address of the remote system associated with the socket.
If the socket is a server socket, this function returns NULL.
*/
IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock)
{
if ( sock->sflag ) {
return(NULL);
}
return(&sock->remoteAddress);
}
/* Send 'len' bytes of 'data' over the non-server socket 'sock'
This function returns the actual amount of data sent. If the return value
is less than the amount of data sent, then either the remote connection was
closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
{
const Uint8 *data = (const Uint8 *)datap; /* For pointer arithmetic */
int sent, left;
/* Server sockets are for accepting connections only */
if ( sock->sflag ) {
SDLNet_SetError("Server sockets cannot send");
return(-1);
}
/* Keep sending data until it's sent or an error occurs */
left = len;
sent = 0;
SDLNet_SetLastError(0);
do {
len = send(sock->channel, (const char *) data, left, 0);
if ( len > 0 ) {
sent += len;
left -= len;
data += len;
}
} while ( (left > 0) && ((len > 0) || (SDLNet_GetLastError() == EINTR)) );
return(sent);
}
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
and store them in the buffer pointed to by 'data'.
This function returns the actual amount of data received. If the return
value is less than or equal to zero, then either the remote connection was
closed, or an unknown socket error occurred.
*/
int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
{
int len;
/* Server sockets are for accepting connections only */
if ( sock->sflag ) {
SDLNet_SetError("Server sockets cannot receive");
return(-1);
}
SDLNet_SetLastError(0);
do {
len = recv(sock->channel, (char *) data, maxlen, 0);
} while ( SDLNet_GetLastError() == EINTR );
sock->ready = 0;
return(len);
}
/* Close a TCP network socket */
void SDLNet_TCP_Close(TCPsocket sock)
{
if ( sock != NULL ) {
if ( sock->channel != INVALID_SOCKET ) {
closesocket(sock->channel);
}
free(sock);
}
}
+528
View File
@@ -0,0 +1,528 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
*/
/* $Id$ */
#include "SDLnetsys.h"
#include "SDL_net.h"
#ifdef __WIN32__
#define srandom srand
#define random rand
#endif
struct UDP_channel {
int numbound;
IPaddress address[SDLNET_MAX_UDPADDRESSES];
};
struct _UDPsocket {
int ready;
SOCKET channel;
IPaddress address;
struct UDP_channel binding[SDLNET_MAX_UDPCHANNELS];
/* For debugging purposes */
int packetloss;
};
/* Allocate/free a single UDP packet 'size' bytes long.
The new packet is returned, or NULL if the function ran out of memory.
*/
extern UDPpacket *SDLNet_AllocPacket(int size)
{
UDPpacket *packet;
int error;
error = 1;
packet = (UDPpacket *)malloc(sizeof(*packet));
if ( packet != NULL ) {
packet->maxlen = size;
packet->data = (Uint8 *)malloc(size);
if ( packet->data != NULL ) {
error = 0;
}
}
if ( error ) {
SDLNet_SetError("Out of memory");
SDLNet_FreePacket(packet);
packet = NULL;
}
return(packet);
}
int SDLNet_ResizePacket(UDPpacket *packet, int newsize)
{
Uint8 *newdata;
newdata = (Uint8 *)malloc(newsize);
if ( newdata != NULL ) {
free(packet->data);
packet->data = newdata;
packet->maxlen = newsize;
}
return(packet->maxlen);
}
extern void SDLNet_FreePacket(UDPpacket *packet)
{
if ( packet ) {
if ( packet->data )
free(packet->data);
free(packet);
}
}
/* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets,
each 'size' bytes long.
A pointer to the packet array is returned, or NULL if the function ran out
of memory.
*/
UDPpacket **SDLNet_AllocPacketV(int howmany, int size)
{
UDPpacket **packetV;
packetV = (UDPpacket **)malloc((howmany+1)*sizeof(*packetV));
if ( packetV != NULL ) {
int i;
for ( i=0; i<howmany; ++i ) {
packetV[i] = SDLNet_AllocPacket(size);
if ( packetV[i] == NULL ) {
break;
}
}
packetV[i] = NULL;
if ( i != howmany ) {
SDLNet_SetError("Out of memory");
SDLNet_FreePacketV(packetV);
packetV = NULL;
}
}
return(packetV);
}
void SDLNet_FreePacketV(UDPpacket **packetV)
{
if ( packetV ) {
int i;
for ( i=0; packetV[i]; ++i ) {
SDLNet_FreePacket(packetV[i]);
}
free(packetV);
}
}
/* Since the UNIX/Win32/BeOS code is so different from MacOS,
we'll just have two completely different sections here.
*/
/* Open a UDP network socket
If 'port' is non-zero, the UDP socket is bound to a fixed local port.
*/
UDPsocket SDLNet_UDP_Open(Uint16 port)
{
UDPsocket sock;
struct sockaddr_in sock_addr;
socklen_t sock_len;
/* Allocate a UDP socket structure */
sock = (UDPsocket)malloc(sizeof(*sock));
if ( sock == NULL ) {
SDLNet_SetError("Out of memory");
goto error_return;
}
memset(sock, 0, sizeof(*sock));
memset(&sock_addr, 0, sizeof(sock_addr));
/* Open the socket */
sock->channel = socket(AF_INET, SOCK_DGRAM, 0);
if ( sock->channel == INVALID_SOCKET )
{
SDLNet_SetError("Couldn't create socket");
goto error_return;
}
/* Bind locally, if appropriate */
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = INADDR_ANY;
sock_addr.sin_port = SDL_SwapBE16(port);
/* Bind the socket for listening */
if ( bind(sock->channel, (struct sockaddr *)&sock_addr,
sizeof(sock_addr)) == SOCKET_ERROR ) {
SDLNet_SetError("Couldn't bind to local port");
goto error_return;
}
/* Get the bound address and port */
sock_len = sizeof(sock_addr);
if ( getsockname(sock->channel, (struct sockaddr *)&sock_addr, &sock_len) < 0 ) {
perror("getsockname");
SDLNet_SetError("Couldn't get socket address");
goto error_return;
}
/* Fill in the channel host address */
sock->address.host = sock_addr.sin_addr.s_addr;
sock->address.port = sock_addr.sin_port;
#ifdef SO_BROADCAST
/* Allow LAN broadcasts with the socket */
{ int yes = 1;
setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes));
}
#endif
#ifdef IP_ADD_MEMBERSHIP
/* Receive LAN multicast packets on 224.0.0.1
This automatically works on Mac OS X, Linux and BSD, but needs
this code on Windows.
*/
/* A good description of multicast can be found here:
http://www.docs.hp.com/en/B2355-90136/ch05s05.html
*/
/* FIXME: Add support for joining arbitrary groups to the API */
{
struct ip_mreq g;
g.imr_multiaddr.s_addr = inet_addr("224.0.0.1");
g.imr_interface.s_addr = INADDR_ANY;
setsockopt(sock->channel, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char*)&g, sizeof(g));
}
#endif
/* The socket is ready */
return(sock);
error_return:
SDLNet_UDP_Close(sock);
return(NULL);
}
void SDLNet_UDP_SetPacketLoss(UDPsocket sock, int percent)
{
/* FIXME: We may want this behavior to be reproducible
but there isn't a portable reentrant random
number generator with good randomness.
*/
srandom(SDL_GetTicks());
if (percent < 0) {
percent = 0;
} else if (percent > 100) {
percent = 100;
}
sock->packetloss = percent;
}
/* Verify that the channel is in the valid range */
static int ValidChannel(int channel)
{
if ( (channel < 0) || (channel >= SDLNET_MAX_UDPCHANNELS) ) {
SDLNet_SetError("Invalid channel");
return(0);
}
return(1);
}
/* Bind the address 'address' to the requested channel on the UDP socket.
If the channel is -1, then the first unbound channel will be bound with
the given address as it's primary address.
If the channel is already bound, this new address will be added to the
list of valid source addresses for packets arriving on the channel.
If the channel is not already bound, then the address becomes the primary
address, to which all outbound packets on the channel are sent.
This function returns the channel which was bound, or -1 on error.
*/
int SDLNet_UDP_Bind(UDPsocket sock, int channel, const IPaddress *address)
{
struct UDP_channel *binding;
if ( sock == NULL ) {
SDLNet_SetError("Passed a NULL socket");
return(-1);
}
if ( channel == -1 ) {
for ( channel=0; channel < SDLNET_MAX_UDPCHANNELS; ++channel ) {
binding = &sock->binding[channel];
if ( binding->numbound < SDLNET_MAX_UDPADDRESSES ) {
break;
}
}
} else {
if ( ! ValidChannel(channel) ) {
return(-1);
}
binding = &sock->binding[channel];
}
if ( binding->numbound == SDLNET_MAX_UDPADDRESSES ) {
SDLNet_SetError("No room for new addresses");
return(-1);
}
binding->address[binding->numbound++] = *address;
return(channel);
}
/* Unbind all addresses from the given channel */
void SDLNet_UDP_Unbind(UDPsocket sock, int channel)
{
if ( (channel >= 0) && (channel < SDLNET_MAX_UDPCHANNELS) ) {
sock->binding[channel].numbound = 0;
}
}
/* Get the primary IP address of the remote system associated with the
socket and channel.
If the channel is not bound, this function returns NULL.
*/
IPaddress *SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel)
{
IPaddress *address;
address = NULL;
switch (channel) {
case -1:
/* Return the actual address of the socket */
address = &sock->address;
break;
default:
/* Return the address of the bound channel */
if ( ValidChannel(channel) &&
(sock->binding[channel].numbound > 0) ) {
address = &sock->binding[channel].address[0];
}
break;
}
return(address);
}
/* Send a vector of packets to the the channels specified within the packet.
If the channel specified in the packet is -1, the packet will be sent to
the address in the 'src' member of the packet.
Each packet will be updated with the status of the packet after it has
been sent, -1 if the packet send failed.
This function returns the number of packets sent.
*/
int SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets)
{
int numsent, i, j;
struct UDP_channel *binding;
int status;
int sock_len;
struct sockaddr_in sock_addr;
if ( sock == NULL ) {
SDLNet_SetError("Passed a NULL socket");
return(0);
}
/* Set up the variables to send packets */
sock_len = sizeof(sock_addr);
numsent = 0;
for ( i=0; i<npackets; ++i )
{
/* Simulate packet loss, if desired */
if (sock->packetloss) {
if ((random()%100) <= sock->packetloss) {
packets[i]->status = packets[i]->len;
++numsent;
continue;
}
}
/* if channel is < 0, then use channel specified in sock */
if ( packets[i]->channel < 0 )
{
sock_addr.sin_addr.s_addr = packets[i]->address.host;
sock_addr.sin_port = packets[i]->address.port;
sock_addr.sin_family = AF_INET;
status = sendto(sock->channel,
packets[i]->data, packets[i]->len, 0,
(struct sockaddr *)&sock_addr,sock_len);
if ( status >= 0 )
{
packets[i]->status = status;
++numsent;
}
}
else
{
/* Send to each of the bound addresses on the channel */
#ifdef DEBUG_NET
printf("SDLNet_UDP_SendV sending packet to channel = %d\n", packets[i]->channel );
#endif
binding = &sock->binding[packets[i]->channel];
for ( j=binding->numbound-1; j>=0; --j )
{
sock_addr.sin_addr.s_addr = binding->address[j].host;
sock_addr.sin_port = binding->address[j].port;
sock_addr.sin_family = AF_INET;
status = sendto(sock->channel,
packets[i]->data, packets[i]->len, 0,
(struct sockaddr *)&sock_addr,sock_len);
if ( status >= 0 )
{
packets[i]->status = status;
++numsent;
}
}
}
}
return(numsent);
}
int SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet)
{
/* This is silly, but... */
packet->channel = channel;
return(SDLNet_UDP_SendV(sock, &packet, 1));
}
/* Returns true if a socket is has data available for reading right now */
static int SocketReady(SOCKET sock)
{
int retval = 0;
struct timeval tv;
fd_set mask;
/* Check the file descriptors for available data */
do {
SDLNet_SetLastError(0);
/* Set up the mask of file descriptors */
FD_ZERO(&mask);
FD_SET(sock, &mask);
/* Set up the timeout */
tv.tv_sec = 0;
tv.tv_usec = 0;
/* Look! */
retval = select(sock+1, &mask, NULL, NULL, &tv);
} while ( SDLNet_GetLastError() == EINTR );
return(retval == 1);
}
/* Receive a vector of pending packets from the UDP socket.
The returned packets contain the source address and the channel they arrived
on. If they did not arrive on a bound channel, the the channel will be set
to -1.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
extern int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets)
{
int numrecv, i, j;
struct UDP_channel *binding;
socklen_t sock_len;
struct sockaddr_in sock_addr;
if ( sock == NULL ) {
return(0);
}
numrecv = 0;
while ( packets[numrecv] && SocketReady(sock->channel) )
{
UDPpacket *packet;
packet = packets[numrecv];
sock_len = sizeof(sock_addr);
packet->status = recvfrom(sock->channel,
packet->data, packet->maxlen, 0,
(struct sockaddr *)&sock_addr,
&sock_len);
if ( packet->status >= 0 ) {
packet->len = packet->status;
packet->address.host = sock_addr.sin_addr.s_addr;
packet->address.port = sock_addr.sin_port;
packet->channel = -1;
for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i )
{
binding = &sock->binding[i];
for ( j=binding->numbound-1; j>=0; --j )
{
if ( (packet->address.host == binding->address[j].host) &&
(packet->address.port == binding->address[j].port) )
{
packet->channel = i;
goto foundit; /* break twice */
}
}
}
foundit:
++numrecv;
}
else
{
packet->len = 0;
}
}
sock->ready = 0;
return(numrecv);
}
/* Receive a single packet from the UDP socket.
The returned packet contains the source address and the channel it arrived
on. If it did not arrive on a bound channel, the the channel will be set
to -1.
This function returns the number of packets read from the network, or -1
on error. This function does not block, so can return 0 packets pending.
*/
int SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet)
{
UDPpacket *packets[2];
/* Receive a packet array of 1 */
packets[0] = packet;
packets[1] = NULL;
return(SDLNet_UDP_RecvV(sock, packets));
}
/* Close a UDP network socket */
extern void SDLNet_UDP_Close(UDPsocket sock)
{
if ( sock != NULL )
{
if ( sock->channel != INVALID_SOCKET )
{
closesocket(sock->channel);
}
free(sock);
}
}
+163
View File
@@ -0,0 +1,163 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
*/
/* $Id$ */
#include "SDLnetsys.h"
#include "SDL_net.h"
/* The select() API for network sockets */
struct SDLNet_Socket {
int ready;
SOCKET channel;
};
struct _SDLNet_SocketSet {
int numsockets;
int maxsockets;
struct SDLNet_Socket **sockets;
};
/* Allocate a socket set for use with SDLNet_CheckSockets()
This returns a socket set for up to 'maxsockets' sockets, or NULL if
the function ran out of memory.
*/
SDLNet_SocketSet SDLNet_AllocSocketSet(int maxsockets)
{
struct _SDLNet_SocketSet *set;
int i;
set = (struct _SDLNet_SocketSet *)malloc(sizeof(*set));
if ( set != NULL ) {
set->numsockets = 0;
set->maxsockets = maxsockets;
set->sockets = (struct SDLNet_Socket **)malloc
(maxsockets*sizeof(*set->sockets));
if ( set->sockets != NULL ) {
for ( i=0; i<maxsockets; ++i ) {
set->sockets[i] = NULL;
}
} else {
free(set);
set = NULL;
}
}
return(set);
}
/* Add a socket to a set of sockets to be checked for available data */
int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
{
if ( sock != NULL ) {
if ( set->numsockets == set->maxsockets ) {
SDLNet_SetError("socketset is full");
return(-1);
}
set->sockets[set->numsockets++] = (struct SDLNet_Socket *)sock;
}
return(set->numsockets);
}
/* Remove a socket from a set of sockets to be checked for available data */
int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
{
int i;
if ( sock != NULL ) {
for ( i=0; i<set->numsockets; ++i ) {
if ( set->sockets[i] == (struct SDLNet_Socket *)sock ) {
break;
}
}
if ( i == set->numsockets ) {
SDLNet_SetError("socket not found in socketset");
return(-1);
}
--set->numsockets;
for ( ; i<set->numsockets; ++i ) {
set->sockets[i] = set->sockets[i+1];
}
}
return(set->numsockets);
}
/* This function checks to see if data is available for reading on the
given set of sockets. If 'timeout' is 0, it performs a quick poll,
otherwise the function returns when either data is available for
reading, or the timeout in milliseconds has elapsed, which ever occurs
first. This function returns the number of sockets ready for reading,
or -1 if there was an error with the select() system call.
*/
int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
{
int i;
SOCKET maxfd;
int retval;
struct timeval tv;
fd_set mask;
/* Find the largest file descriptor */
maxfd = 0;
for ( i=set->numsockets-1; i>=0; --i ) {
if ( set->sockets[i]->channel > maxfd ) {
maxfd = set->sockets[i]->channel;
}
}
/* Check the file descriptors for available data */
do {
SDLNet_SetLastError(0);
/* Set up the mask of file descriptors */
FD_ZERO(&mask);
for ( i=set->numsockets-1; i>=0; --i ) {
FD_SET(set->sockets[i]->channel, &mask);
}
/* Set up the timeout */
tv.tv_sec = timeout/1000;
tv.tv_usec = (timeout%1000)*1000;
/* Look! */
retval = select(maxfd+1, &mask, NULL, NULL, &tv);
} while ( SDLNet_GetLastError() == EINTR );
/* Mark all file descriptors ready that have data available */
if ( retval > 0 ) {
for ( i=set->numsockets-1; i>=0; --i ) {
if ( FD_ISSET(set->sockets[i]->channel, &mask) ) {
set->sockets[i]->ready = 1;
}
}
}
return(retval);
}
/* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
extern void SDLNet_FreeSocketSet(SDLNet_SocketSet set)
{
if ( set ) {
free(set->sockets);
free(set);
}
}
+94
View File
@@ -0,0 +1,94 @@
/*
SDL_net: An example cross-platform network library for use with SDL
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
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.
*/
/* $Id$ */
/* Include normal system headers */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32_WCE
#include <errno.h>
#endif
/* Include system network headers */
#if defined(__WIN32__) || defined(WIN32)
#define __USE_W32_SOCKETS
#ifdef _WIN64
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <winsock.h>
/* NOTE: windows socklen_t is signed
* and is defined only for winsock2. */
typedef int socklen_t;
#endif /* W64 */
#include <iphlpapi.h>
#else /* UNIX */
#include <sys/types.h>
#ifdef __FreeBSD__
#include <sys/socket.h>
#endif
#include <sys/ioctl.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#ifndef __BEOS__
#include <arpa/inet.h>
#endif
#ifdef linux /* FIXME: what other platforms have this? */
#include <netinet/tcp.h>
#endif
#include <sys/socket.h>
#include <net/if.h>
#include <netdb.h>
#endif /* WIN32 */
/* FIXME: What platforms need this? */
#if 0
typedef Uint32 socklen_t;
#endif
/* System-dependent definitions */
#ifndef __USE_W32_SOCKETS
#ifdef __OS2__
#define closesocket soclose
#else /* !__OS2__ */
#define closesocket close
#endif /* __OS2__ */
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#endif /* __USE_W32_SOCKETS */
#ifdef __USE_W32_SOCKETS
#define SDLNet_GetLastError WSAGetLastError
#define SDLNet_SetLastError WSASetLastError
#ifndef EINTR
#define EINTR WSAEINTR
#endif
#else
int SDLNet_GetLastError(void);
void SDLNet_SetLastError(int err);
#endif
+39
View File
@@ -0,0 +1,39 @@
#config
LIBDIR=..
LOCALLIBS=
LIB=
INCLUDES=
CFLAGS+=$(addprefix -I,$(INCLUDES))
#source
SRC=$(wildcard *.c)
#objects
OBJDIR=obj
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.c=.o))
#output
OUTDIR=../out
OUT=$(addprefix $(OUTDIR)/,libSDL_net.a)
#targets
all: $(OBJ) $(OUT)
ar -crs $(OUT) $(OBJ)
$(OBJ): | $(OBJDIR)
$(OUT): | $(OUTDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OUTDIR):
mkdir $(OUTDIR)
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
@@ -19,18 +19,12 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef SCENELIST_HPP_
#define SCENELIST_HPP_
#include "defines.hpp"
enum class SceneList {
//these are reserved
QUIT,
CONTINUE,
FIRST,
#include <cstdio>
//custom indexes
TESTIFICATESCENE,
EDITORSCENE,
};
#endif
std::string itos(int i) {
char buffer[20];
snprintf(buffer, 20, "%d", i);
return std::string(buffer);
}
+8 -11
View File
@@ -19,20 +19,17 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#ifndef CLIENT_HPP_
#define CLIENT_HPP_
#ifndef DEFINES_HPP_
#define DEFINES_HPP
#include "SDL/SDL_net.h"
#include <chrono>
#include <string>
#include <map>
#define GAME_CHANNEL 0
#define CHAT_CHANNEL 1
/* Hold the client info.
*/
typedef std::chrono::high_resolution_clock Clock;
struct Client {
IPaddress address;
};
typedef std::map<int, Client> ClientMap;
std::string itos(int i);
#endif
@@ -1,21 +1,20 @@
#config
INCLUDES+=. ..
LIBS+=
LIBDIR=..
LOCALLIBS=$(LIBDIR)/out/libCodebase.a
LIB=
INCLUDES=$(LIBDIR)/Codebase
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
CFLAGS+=-DDEBUG $(addprefix -I,$(INCLUDES))
#source
CXXSRC=$(wildcard *.cpp)
CSRC=$(wildcard *.c)
SRC=$(wildcard *.cpp)
#objects
OBJDIR=obj
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
OBJ+=$(addprefix $(OBJDIR)/,$(CSRC:.c=.o))
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
#output
OUTDIR=../..
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
OUTDIR=../out
OUT=$(addprefix $(OUTDIR)/,libCommon.a)
#targets
all: $(OBJ) $(OUT)
@@ -34,9 +33,6 @@ $(OUTDIR):
$(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
$(RM) *.o *.a *.exe
+110
View File
@@ -0,0 +1,110 @@
/* 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 "service_locator.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 = ServiceLocator<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 = ServiceLocator<UDPNetworkUtility>::Get();
SDL_SemWait(lock);
while(netUtil->Receive());
queue.clear();
SDL_SemPost(lock);
}
+34
View File
@@ -0,0 +1,34 @@
/* 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_type.hpp"
void beginQueueThread();
void endQueueThread();
void killQueueThread();
Packet peekNetworkPacket();
Packet popNetworkPacket();
void flushNetworkQueue();
#endif
+138
View File
@@ -0,0 +1,138 @@
/* 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 PACKETTYPE_HPP_
#define PACKETTYPE_HPP_
#include "vector2.hpp"
#include "SDL_net/SDL_net.h"
#define PACKET_STRING_SIZE 100
#pragma pack(push, 0)
enum class PacketType {
NONE = 0,
PING = 1,
PONG = 2,
BROADCAST_REQUEST = 3,
BROADCAST_RESPONSE = 4,
JOIN_REQUEST = 5,
JOIN_RESPONSE = 6,
DISCONNECT = 7,
SYNCHRONIZE = 8,
PLAYER_NEW = 9,
PLAYER_DELETE = 10,
PLAYER_MOVE = 11,
};
struct Metadata {
PacketType type;
IPaddress address;
};
struct Ping {
Metadata meta;
};
struct Pong {
Metadata meta;
};
struct BroadcastRequest {
Metadata meta;
};
struct BroadcastResponse {
Metadata meta;
char name[PACKET_STRING_SIZE];
//TODO: version
};
struct JoinRequest {
Metadata meta;
};
struct JoinResponse {
Metadata meta;
int clientIndex;
//resource list
};
struct Disconnect {
Metadata meta;
int clientIndex;
};
struct Synchronize {
Metadata meta;
};
struct PlayerNew {
Metadata meta;
int playerIndex;
//TODO Playerdata
};
struct PlayerDelete {
Metadata meta;
int playerIndex;
};
struct PlayerMove {
Metadata meta;
int playerIndex;
Vector2 position;
Vector2 motion;
};
union Packet {
Packet() {
meta.type = PacketType::NONE;
meta.address.host = 0;
meta.address.port = 0;
};
Metadata meta;
Ping ping;
Pong pong;
BroadcastRequest broadcastRequest;
BroadcastResponse broadcastResponse;
JoinRequest joinRequest;
JoinResponse joinResponse;
Disconnect disconnect;
PlayerNew playerNew;
PlayerDelete playerDelete;
PlayerMove playerMove;
#ifdef DEBUG
char buffer[1024];
#endif
};
#pragma pack(pop)
#endif
@@ -19,24 +19,24 @@
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "editor_application.hpp"
#ifndef SERVICELOCATOR_HPP_
#define SERVICELOCATOR_HPP_
#include <stdexcept>
#include <iostream>
using namespace std;
int main(int, char**) {
cout << "Beginning editor" << endl;
try {
EditorApplication::GetInstance()->Init();
EditorApplication::GetInstance()->Proc();
EditorApplication::GetInstance()->Quit();
template<typename T>
class ServiceLocator {
public:
static T* Set(T* t) {
delete service;
return service = t;
}
catch(exception& e) {
cerr << "Fatal exception thrown: " << e.what() << endl;
return 1;
static T* Get() {
return service;
}
cout << "Clean exit" << endl;
return 0;
}
private:
static T* service;
};
template<typename T>
T* ServiceLocator<T>::service = nullptr;
#endif
+14
View File
@@ -0,0 +1,14 @@
OUTDIR=out
all: $(OUTDIR)
$(MAKE) -C SDL_net
$(MAKE) -C codebase
$(MAKE) -C common
$(OUTDIR):
mkdir $(OUTDIR)
clean:
$(RM) *.o *.a *.exe
rebuild: clean all
+2 -12
View File
@@ -1,20 +1,10 @@
#for use on Windows:
#MKDIR=mkdir
#RM=del /y
CXXFLAGS+=-static-libgcc -static-libstdc++
CFLAGS+=-static-libgcc
export
OUTDIR=out
all: $(OUTDIR)
$(MAKE) -C common
$(MAKE) -C libs
$(MAKE) -C server
$(MAKE) -C client
$(MAKE) -C editor
$(MAKE) -C test
$(OUTDIR):
mkdir $(OUTDIR)
+11 -15
View File
@@ -1,24 +1,20 @@
#configuration of the programs
server.host = 255.255.255.255
server.port = 21795
server.name = local
server.dbname = database.db
server.host = 127.0.0.1
server.port = 1991
server.name = foobar
screen.w = 800
screen.h = 600
screen.f = false
#directories
dir.fonts = rsc/graphics/fonts/
dir.logos = rsc/graphics/logos/
dir.sprites = rsc/graphics/sprites/
dir.tilesets = rsc/graphics/tilesets/
dir.interface = rsc/graphics/interface/
dir.scripts = rsc/scripts/
#player options
player.handle = username
player.avatar = elliot2.bmp
fonts = rsc/graphics/fonts
logos = rsc/graphics/logos
sprites = rsc/graphics/sprites
tilesets = rsc/graphics/tilesets
interface = rsc/graphics/interface
#debugging
debug = true
avatar = elliot2.bmp
handle = UserName
Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Some files were not shown because too many files have changed in this diff Show More