Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c60709d047 | |||
| 6b677e5de8 | |||
| d347545c20 | |||
| dfac9c1518 | |||
| 0cfb47e641 | |||
| a260f29d4f | |||
| a8b798ddff | |||
| 231db701e4 | |||
| 783e8928d6 | |||
| 6a16e341ec | |||
| 4c670c3a22 | |||
| 488283be50 | |||
| 4c228e0e36 | |||
| 0d3a69106f | |||
| e2fed23659 | |||
| 1ab963099d | |||
| 0b2af1d80f | |||
| cce1a874bf | |||
| 66f54dca0b | |||
| bf73b542f1 | |||
| d76cbe13da | |||
| d5409d2006 | |||
| 7866f46ed5 | |||
| b587759203 | |||
| f8c174741d | |||
| 000e3707ed | |||
| b3691a341c | |||
| d2087be9ac | |||
| 5ade2cc98e | |||
| 24e48dec53 | |||
| 738320e88e | |||
| f04c7fa161 | |||
| 30d163ec80 | |||
| 613d9cec08 | |||
| 9f76b19a3c | |||
| cc00129542 | |||
| 6a19d0a312 | |||
| 4671afe900 | |||
| a667fae21a | |||
| f0d4ef0675 | |||
| 2dedfa9505 | |||
| f0e7550b7d | |||
| 96f0821d9b | |||
| f349e59fd3 | |||
| b935fcf1d1 | |||
| 95f2d212ef | |||
| 80004ca8d4 | |||
| fe04561b26 | |||
| 63aa248056 | |||
| cf82679109 | |||
| ecdf658463 | |||
| c9447fcf3b | |||
| 7dafb372b1 | |||
| 392ef1ef32 | |||
| d72a3f4fb5 | |||
| 1226fa08ca | |||
| 79304f24b8 | |||
| 31d5b3f618 |
@@ -0,0 +1,18 @@
|
||||
#Editor generated files
|
||||
#*.sln
|
||||
#*.vcproj
|
||||
*.suo
|
||||
*.ncb
|
||||
*.user
|
||||
|
||||
#Directories
|
||||
Release/
|
||||
Debug/
|
||||
Out/
|
||||
|
||||
#Project generated files
|
||||
*.db
|
||||
|
||||
#Shell files
|
||||
*.bat
|
||||
*.sh
|
||||
@@ -0,0 +1,30 @@
|
||||
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.
|
||||
|
||||
## Libraries
|
||||
|
||||
* [SDL](http://www.libsdl.org/) - Simple DirectMedia Layer API
|
||||
* [SDL_net](http://www.libsdl.org/projects/SDL_net/) - SDL's networking extension; modified source included under libs/SDL_net
|
||||
* [Codebase](https://github.com/Ratstail91/Codebase) - files included locally; modifications will be included upstream further into this project.
|
||||
|
||||
## Instructions
|
||||
|
||||
* 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.
|
||||
* You need to build the library in the common/ directroy before any others.
|
||||
* 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
|
||||
|
||||
Tortuga is released under the [zlib license](http://en.wikipedia.org/wiki/Zlib_License).
|
||||
|
||||
Copyright (c) 2013 Kayne Ruse
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
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,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -34,7 +34,7 @@ SDL_Surface* BaseScene::screen = nullptr;
|
||||
//-------------------------
|
||||
|
||||
BaseScene::BaseScene() {
|
||||
//
|
||||
nextScene = SceneList::CONTINUE;
|
||||
}
|
||||
|
||||
BaseScene::~BaseScene() {
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -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
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "combat.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
Combat::Combat() {
|
||||
#ifdef DEBUG
|
||||
cout << "entering Combat" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
Combat::~Combat() {
|
||||
#ifdef DEBUG
|
||||
cout << "leaving Combat" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void Combat::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void Combat::Update(double delta) {
|
||||
//
|
||||
}
|
||||
|
||||
void Combat::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void Combat::Render(SDL_Surface* const screen) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void Combat::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
//
|
||||
}
|
||||
|
||||
void Combat::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void Combat::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void Combat::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Combat::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef COMBAT_HPP_
|
||||
#define COMBAT_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
class Combat : public BaseScene {
|
||||
public:
|
||||
/* Public access members */
|
||||
Combat();
|
||||
~Combat();
|
||||
|
||||
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&);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef DEFINES_HPP_
|
||||
#define DEFINES_HPP_
|
||||
|
||||
enum class Direction {
|
||||
NORTH = 1, SOUTH = 2,
|
||||
EAST = 3, WEST = 4
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "in_game.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InGame::InGame(ConfigUtility* cUtil, SurfaceManager* sMgr, UDPNetworkUtility* nUtil, int* ID) {
|
||||
#ifdef DEBUG
|
||||
cout << "entering InGame" << endl;
|
||||
#endif
|
||||
configUtil = cUtil;
|
||||
surfaceMgr = sMgr;
|
||||
netUtil = nUtil;
|
||||
playerID = ID;
|
||||
cout << "playerID: " << *playerID << endl;
|
||||
}
|
||||
|
||||
InGame::~InGame() {
|
||||
//placeholder disconnect
|
||||
PacketData p;
|
||||
p.type = PacketList::DISCONNECT;
|
||||
p.disconnect.playerID = *playerID;
|
||||
*playerID = -1;
|
||||
netUtil->Send(0, &p, sizeof(PacketData));
|
||||
netUtil->Unbind(0);
|
||||
#ifdef DEBUG
|
||||
cout << "leaving InGame" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void InGame::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void InGame::Update(double delta) {
|
||||
Receive();
|
||||
}
|
||||
|
||||
void InGame::Receive() {
|
||||
PacketData packet;
|
||||
while(netUtil->Receive()) {
|
||||
memcpy(&packet, netUtil->GetInData(), sizeof(PacketData));
|
||||
switch(packet.type) {
|
||||
// case PacketList::NONE:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::PING:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::PONG:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::JOINREQUEST:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::JOINCONFIRM:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::DISCONNECT:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::SYNCHRONIZE:
|
||||
// //
|
||||
// break;
|
||||
case PacketList::NEWPLAYER:
|
||||
cout << "NEWPLAYER triggered" << endl;
|
||||
break;
|
||||
case PacketList::DELETEPLAYER:
|
||||
cout << "DELETEPLAYER triggered" << endl;
|
||||
break;
|
||||
// case PacketList::MOVEMENT:
|
||||
// //
|
||||
// break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InGame::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void InGame::Render(SDL_Surface* const screen) {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InGame::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
//
|
||||
}
|
||||
|
||||
void InGame::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void InGame::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void InGame::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InGame::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef INGAME_HPP_
|
||||
#define INGAME_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "surface_manager.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "packet_list.hpp"
|
||||
|
||||
class InGame : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
InGame(ConfigUtility*, SurfaceManager*, UDPNetworkUtility*, int* playerID);
|
||||
~InGame();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void Receive();
|
||||
void FrameEnd();
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//Event handlers
|
||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
//members
|
||||
ConfigUtility* configUtil = nullptr;
|
||||
SurfaceManager* surfaceMgr = nullptr;
|
||||
UDPNetworkUtility* netUtil = nullptr;
|
||||
int* playerID = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,210 @@
|
||||
#include "lobby.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
Lobby::Lobby(ConfigUtility* cUtil, SurfaceManager* sMgr, UDPNetworkUtility* nUtil, int* ID) {
|
||||
#ifdef DEBUG
|
||||
cout << "entering Lobby" << endl;
|
||||
#endif
|
||||
//globals
|
||||
configUtil = cUtil;
|
||||
surfaceMgr = sMgr;
|
||||
netUtil = nUtil;
|
||||
playerID = ID;
|
||||
|
||||
//members
|
||||
font.SetSurface(surfaceMgr->Get("font"));
|
||||
|
||||
//the buttons
|
||||
buttonMap["ping"] = new Button(50, 50 , surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Refresh");
|
||||
buttonMap["join"] = new Button(50, 100, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Join");
|
||||
buttonMap["back"] = new Button(50, 150, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Back");
|
||||
|
||||
//drawing information for the server list
|
||||
listBox.x = 250;
|
||||
listBox.y = 50;
|
||||
listBox.w = GetScreen()->w - listBox.x;
|
||||
listBox.h = font.GetCharH();
|
||||
|
||||
//ping the network
|
||||
PingNetwork();
|
||||
}
|
||||
|
||||
Lobby::~Lobby() {
|
||||
for (auto it : buttonMap) {
|
||||
delete it.second;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
cout << "leaving Lobby" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void Lobby::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void Lobby::Update(double delta) {
|
||||
Receive();
|
||||
}
|
||||
|
||||
void Lobby::Receive() {
|
||||
PacketData packet;
|
||||
while(netUtil->Receive()) {
|
||||
memcpy(&packet, netUtil->GetInData(), sizeof(PacketData));
|
||||
switch(packet.type) {
|
||||
// case PacketList::NONE:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::PING:
|
||||
// //
|
||||
// break;
|
||||
case PacketList::PONG:
|
||||
PushServer(&packet);
|
||||
break;
|
||||
// case PacketList::JOINREQUEST:
|
||||
// //
|
||||
// break;
|
||||
case PacketList::JOINCONFIRM: {
|
||||
PacketData p;
|
||||
memcpy(&p, netUtil->GetInData(), sizeof(PacketData));
|
||||
*playerID = p.joinConfirm.playerID;
|
||||
netUtil->Bind(&netUtil->GetInPacket()->address, 0);
|
||||
SetNextScene(SceneList::INGAME);
|
||||
}
|
||||
break;
|
||||
// case PacketList::DISCONNECT:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::SYNCHRONIZE:
|
||||
// //
|
||||
// break;
|
||||
#ifdef DEBUG
|
||||
//this might not be the end of the world; it only happens when the game ping is too low
|
||||
case PacketList::NEWPLAYER:
|
||||
cout << "WARNING: new player triggered unexpectedly" << endl;
|
||||
break;
|
||||
#endif
|
||||
// case PacketList::DELETEPLAYER:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::MOVEMENT:
|
||||
// //
|
||||
// break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void Lobby::Render(SDL_Surface* const screen) {
|
||||
for (auto it : buttonMap) {
|
||||
it.second->DrawTo(screen);
|
||||
}
|
||||
|
||||
//draw the server list, highlighting the selected server
|
||||
SDL_Rect clip;
|
||||
for (int i = 0; i < serverVector.size(); i++) {
|
||||
clip = listBox;
|
||||
clip.y += i * font.GetCharH();
|
||||
|
||||
//if a server has been selected, and this is the selected server
|
||||
if (selectedServer && selectedServer == &serverVector[i]) {
|
||||
//draw the orange box
|
||||
SDL_FillRect(screen, &clip, SDL_MapRGB(screen->format, 255, 127, 39));
|
||||
}
|
||||
font.DrawStringTo(serverVector[i].name, screen, clip.x, clip.y);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void Lobby::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
for (auto it : buttonMap) {
|
||||
it.second->MouseMotion(motion);
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
for (auto it : buttonMap) {
|
||||
it.second->MouseButtonDown(button);
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (buttonMap["ping"]->MouseButtonUp(button) == Button::State::HOVER) {
|
||||
PingNetwork();
|
||||
}
|
||||
else if (buttonMap["join"]->MouseButtonUp(button) == Button::State::HOVER) {
|
||||
JoinRequest(selectedServer);
|
||||
}
|
||||
else if (buttonMap["back"]->MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
//select a server (clicked within the bounds of the server box)
|
||||
else if (button.x > listBox.x && button.y > listBox.y && button.y < serverVector.size() * font.GetCharH() + listBox.y) {
|
||||
selectedServer = &serverVector[(button.y-listBox.y)/font.GetCharH()];
|
||||
}
|
||||
else {
|
||||
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
|
||||
//-------------------------
|
||||
|
||||
void Lobby::PingNetwork() {
|
||||
//ping the network
|
||||
PacketData p;
|
||||
p.type = PacketList::PING;
|
||||
netUtil->Send("255.255.255.255", configUtil->Integer("server.port"), reinterpret_cast<void*>(&p), sizeof(PacketData));
|
||||
//reset the server list
|
||||
//TODO: enable this
|
||||
// serverVector.clear();
|
||||
}
|
||||
|
||||
void Lobby::PushServer(PacketData* packet) {
|
||||
ServerData s;
|
||||
s.name = packet->pong.metadata;
|
||||
s.address = netUtil->GetInPacket()->address;
|
||||
serverVector.push_back(s);
|
||||
}
|
||||
|
||||
void Lobby::JoinRequest(ServerData* server) {
|
||||
if (!server) {
|
||||
//CAN receive null
|
||||
return;
|
||||
}
|
||||
PacketData p;
|
||||
p.type = PacketList::JOINREQUEST;
|
||||
snprintf(p.joinRequest.handle, PACKET_STRING_SIZE, "%s", configUtil->CString("handle"));
|
||||
snprintf(p.joinRequest.avatar, PACKET_STRING_SIZE, "%s", configUtil->CString("avatar"));
|
||||
netUtil->Send(&server->address, reinterpret_cast<void*>(&p), sizeof(PacketData));
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef LOBBY_HPP_
|
||||
#define LOBBY_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "surface_manager.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "packet_list.hpp"
|
||||
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class Lobby : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
Lobby(ConfigUtility*, SurfaceManager*, UDPNetworkUtility*, int* playerID);
|
||||
~Lobby();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void Receive();
|
||||
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&);
|
||||
|
||||
//utilities
|
||||
struct ServerData {
|
||||
std::string name;
|
||||
IPaddress address;
|
||||
};
|
||||
|
||||
void PingNetwork();
|
||||
void PushServer(PacketData*);
|
||||
void JoinRequest(ServerData*);
|
||||
|
||||
//globals
|
||||
ConfigUtility* configUtil = nullptr;
|
||||
SurfaceManager* surfaceMgr = nullptr;
|
||||
UDPNetworkUtility* netUtil = nullptr;
|
||||
int* playerID;
|
||||
|
||||
//members
|
||||
RasterFont font;
|
||||
std::map<std::string, Button*> buttonMap;
|
||||
|
||||
//the list of servers on the screen
|
||||
std::vector<ServerData> serverVector;
|
||||
ServerData* selectedServer = nullptr;
|
||||
SDL_Rect listBox;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "scene_manager.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int, char**) {
|
||||
#ifdef DEBUG
|
||||
cout << "Beginning program" << endl;
|
||||
#endif
|
||||
try {
|
||||
SceneManager app;
|
||||
app.Init();
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
}
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal error: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
cout << "Clean exit" << endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "main_menu.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
MainMenu::MainMenu(ConfigUtility* cUtil, SurfaceManager* sMgr) {
|
||||
#ifdef DEBUG
|
||||
cout << "entering MainMenu" << endl;
|
||||
#endif
|
||||
configUtil = cUtil;
|
||||
surfaceMgr = sMgr;
|
||||
|
||||
buttonMap["start"] = new Button(50, 50, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Start");
|
||||
buttonMap["options"] = new Button(50, 100, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Options");
|
||||
buttonMap["quit"] = new Button(50, 150, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "Quit");
|
||||
|
||||
buttonMap["testsystems"] = new Button(50, 250, surfaceMgr->Get("button"), surfaceMgr->Get("font"), "TestSystems");
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu() {
|
||||
for (auto it : buttonMap) {
|
||||
delete it.second;
|
||||
}
|
||||
buttonMap.clear();
|
||||
#ifdef DEBUG
|
||||
cout << "leaving MainMenu" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void MainMenu::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::Update(double delta) {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::Render(SDL_Surface* const screen) {
|
||||
for (auto it : buttonMap) {
|
||||
it.second->DrawTo(screen);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void MainMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
for (auto it : buttonMap) {
|
||||
it.second->MouseMotion(motion);
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
for (auto it : buttonMap) {
|
||||
it.second->MouseButtonDown(button);
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (buttonMap["start"]->MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::LOBBY);
|
||||
}
|
||||
if (buttonMap["options"]->MouseButtonUp(button) == Button::State::HOVER) {
|
||||
//TODO
|
||||
}
|
||||
if (buttonMap["quit"]->MouseButtonUp(button) == Button::State::HOVER) {
|
||||
QuitEvent();
|
||||
}
|
||||
if (buttonMap["testsystems"]->MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::TESTSYSTEMS);
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
QuitEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef MAINMENU_HPP_
|
||||
#define MAINMENU_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "surface_manager.hpp"
|
||||
|
||||
#include "button.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class MainMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
MainMenu(ConfigUtility*, SurfaceManager*);
|
||||
~MainMenu();
|
||||
|
||||
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* configUtil;
|
||||
SurfaceManager* surfaceMgr;
|
||||
|
||||
//members
|
||||
std::map<std::string, Button*> buttonMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#config
|
||||
INCLUDES=../common
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
LIB=../common/out/common.a -lmingw32 -lSDL_net -lSDLmain -lSDL -lwsock32 -liphlpapi
|
||||
|
||||
#source
|
||||
SRC=$(filter-out unit.cpp, $(wildcard *.cpp))
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=out
|
||||
OUT=$(addprefix $(OUTDIR)/,client)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIB)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "player.hpp"
|
||||
|
||||
#define ANIMATION_SPEED 0.1
|
||||
#define WALKING_SPEED 140
|
||||
|
||||
Player::Player(SDL_Surface* s, int w, int h)
|
||||
: sprite(s, w, h)
|
||||
{
|
||||
}
|
||||
|
||||
void Player::Update(double delta) {
|
||||
if (motion.y > 0) {
|
||||
FaceDirection(Direction::SOUTH);
|
||||
}
|
||||
else if (motion.y < 0) {
|
||||
FaceDirection(Direction::NORTH);
|
||||
}
|
||||
else if (motion.x < 0) {
|
||||
FaceDirection(Direction::WEST);
|
||||
}
|
||||
else if (motion.x > 0) {
|
||||
FaceDirection(Direction::EAST);
|
||||
}
|
||||
|
||||
if (motion.x != 0 && motion.y != 0) {
|
||||
sprite.SetInterval(ANIMATION_SPEED);
|
||||
constexpr double d = 1/sqrt(2);
|
||||
position += motion * d * delta;
|
||||
}
|
||||
else if (motion != 0) {
|
||||
sprite.SetInterval(ANIMATION_SPEED);
|
||||
position += motion * delta;
|
||||
}
|
||||
else {
|
||||
sprite.SetCurrentFrame(0);
|
||||
sprite.SetInterval(0);
|
||||
}
|
||||
sprite.Update(delta);
|
||||
}
|
||||
|
||||
void Player::WalkInDirection(Direction d) {
|
||||
switch(d) {
|
||||
case Direction::NORTH:
|
||||
if (motion.y >= 0) {
|
||||
motion.y -= WALKING_SPEED;
|
||||
}
|
||||
else {
|
||||
motion.y = -WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
case Direction::SOUTH:
|
||||
if (motion.y <= 0) {
|
||||
motion.y += WALKING_SPEED;
|
||||
}
|
||||
else {
|
||||
motion.y = WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
case Direction::WEST:
|
||||
if (motion.x >= 0) {
|
||||
motion.x -= WALKING_SPEED;
|
||||
}
|
||||
else {
|
||||
motion.x = -WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
case Direction::EAST:
|
||||
if (motion.x <= 0) {
|
||||
motion.x += WALKING_SPEED;
|
||||
}
|
||||
else {
|
||||
motion.x = WALKING_SPEED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::FaceDirection(Direction dir) {
|
||||
switch(dir) {
|
||||
case Direction::SOUTH:
|
||||
sprite.SetCurrentStrip(0);
|
||||
break;
|
||||
case Direction::NORTH:
|
||||
sprite.SetCurrentStrip(1);
|
||||
break;
|
||||
case Direction::WEST:
|
||||
sprite.SetCurrentStrip(2);
|
||||
break;
|
||||
case Direction::EAST:
|
||||
sprite.SetCurrentStrip(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef PLAYER_HPP_
|
||||
#define PLAYER_HPP_
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "vector2.hpp"
|
||||
#include "sprite_sheet.hpp"
|
||||
|
||||
#include "SDL/SDL.h"
|
||||
|
||||
class Player {
|
||||
public:
|
||||
Player(SDL_Surface*, int w, int h);
|
||||
|
||||
void Update(double delta);
|
||||
|
||||
void WalkInDirection(Direction);
|
||||
|
||||
Vector2 SetPosition(Vector2 v) { return position = v; }
|
||||
Vector2 ShiftPosition(Vector2 v) { return position += v; }
|
||||
Vector2 GetPosition() const { return position; };
|
||||
|
||||
Vector2 SetMotion(Vector2 v) { return motion = v; }
|
||||
Vector2 ShiftMotion(Vector2 v) { return motion += v; }
|
||||
Vector2 GetMotion() const { return motion; }
|
||||
|
||||
void DrawTo(SDL_Surface* const s) { sprite.DrawTo(s, position.x, position.y); }
|
||||
void FaceDirection(Direction);
|
||||
|
||||
SpriteSheet* GetSpriteSheet() { return &sprite; };
|
||||
private:
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
SpriteSheet sprite;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "player_manager.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
PlayerManager::PlayerManager() {
|
||||
//
|
||||
}
|
||||
|
||||
PlayerManager::~PlayerManager() {
|
||||
DeleteAll();
|
||||
}
|
||||
|
||||
Player* PlayerManager::New(int index, SDL_Surface* avatarSheet) {
|
||||
if (playerMap.find(index) != playerMap.end()) {
|
||||
throw(std::runtime_error("This player's index is already taken"));
|
||||
}
|
||||
|
||||
return playerMap[index] = new Player(avatarSheet, avatarSheet->w/4, avatarSheet->h/4);
|
||||
}
|
||||
|
||||
Player* PlayerManager::Get(int index) {
|
||||
std::map<int, Player*>::iterator it = playerMap.find(index);
|
||||
if(it == playerMap.end()) {
|
||||
throw(std::runtime_error("Failed to find a player with that index"));
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void PlayerManager::Delete(int index) {
|
||||
std::map<int, Player*>::iterator it = playerMap.find(index);
|
||||
delete it->second;
|
||||
playerMap.erase(it);
|
||||
}
|
||||
|
||||
void PlayerManager::UpdateAll(double delta) {
|
||||
for (auto it : playerMap) {
|
||||
it.second->Update(delta);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::DrawAllTo(SDL_Surface* dest) {
|
||||
for (auto it : playerMap) {
|
||||
it.second->DrawTo(dest);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::DeleteAll() {
|
||||
for (auto it : playerMap) {
|
||||
delete it.second;
|
||||
}
|
||||
playerMap.clear();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef PLAYERMANAGER_HPP_
|
||||
#define PLAYERMANAGER_HPP_
|
||||
|
||||
#include "player.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
class PlayerManager {
|
||||
public:
|
||||
PlayerManager();
|
||||
~PlayerManager();
|
||||
|
||||
Player* New(int index, SDL_Surface* avatarSheet);
|
||||
Player* Get(int index);
|
||||
void Delete(int index);
|
||||
|
||||
void UpdateAll(double delta);
|
||||
void DrawAllTo(SDL_Surface* dest);
|
||||
void DeleteAll();
|
||||
|
||||
Player* operator[](int i) { return Get(i); }
|
||||
private:
|
||||
std::map<int, Player*> playerMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef SCENELIST_HPP_
|
||||
#define SCENELIST_HPP_
|
||||
|
||||
enum class SceneList {
|
||||
//these are reserved
|
||||
QUIT, //doubles as "up one scene" in nested scenes
|
||||
CONTINUE,
|
||||
FIRST,
|
||||
|
||||
//custom indexes
|
||||
TESTSYSTEMS,
|
||||
SPLASH,
|
||||
MAINMENU,
|
||||
INGAME,
|
||||
|
||||
//subscenes
|
||||
LOBBY,
|
||||
COMBAT,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
#include "scene_manager.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
|
||||
//-------------------------
|
||||
//Scene headers
|
||||
//-------------------------
|
||||
|
||||
//Add the custom scene headers here
|
||||
#include "test_systems.hpp"
|
||||
|
||||
#include "splash.hpp"
|
||||
#include "main_menu.hpp"
|
||||
#include "lobby.hpp"
|
||||
#include "in_game.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
SceneManager::SceneManager() {
|
||||
//
|
||||
}
|
||||
|
||||
SceneManager::~SceneManager() {
|
||||
UnloadScene();
|
||||
}
|
||||
|
||||
void SceneManager::Init() {
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
throw(std::runtime_error("Failed to initialize SDL"));
|
||||
}
|
||||
if (SDLNet_Init()) {
|
||||
throw(std::runtime_error("Failed to initialize SDL_net"));
|
||||
}
|
||||
|
||||
configUtil.Load("rsc/config.cfg");
|
||||
netUtil.Open(0, sizeof(PacketData));
|
||||
|
||||
//set the screen from the config file
|
||||
int flags = SDL_HWSURFACE|SDL_DOUBLEBUF;
|
||||
if (configUtil.Boolean("screen.f")) {
|
||||
flags |= SDL_FULLSCREEN;
|
||||
}
|
||||
BaseScene::SetScreen(configUtil.Integer("screen.w"),configUtil.Integer("screen.h"),0,flags);
|
||||
}
|
||||
|
||||
void SceneManager::Proc() {
|
||||
LoadScene(SceneList::FIRST);
|
||||
|
||||
//prepare the time system
|
||||
typedef std::chrono::high_resolution_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 SceneManager::Quit() {
|
||||
UnloadScene();
|
||||
SDLNet_Quit();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Private access members
|
||||
//-------------------------
|
||||
|
||||
void SceneManager::LoadScene(SceneList sceneIndex) {
|
||||
UnloadScene();
|
||||
|
||||
switch(sceneIndex) {
|
||||
//add scene creation calls here
|
||||
case SceneList::TESTSYSTEMS:
|
||||
activeScene = new TestSystems(&configUtil, &surfaceMgr, &netUtil);
|
||||
break;
|
||||
|
||||
case SceneList::FIRST:
|
||||
case SceneList::SPLASH:
|
||||
activeScene = new Splash(&configUtil, &surfaceMgr);
|
||||
break;
|
||||
case SceneList::MAINMENU:
|
||||
activeScene = new MainMenu(&configUtil, &surfaceMgr);
|
||||
break;
|
||||
case SceneList::LOBBY:
|
||||
activeScene = new Lobby(&configUtil, &surfaceMgr, &netUtil, &playerID);
|
||||
break;
|
||||
case SceneList::INGAME:
|
||||
activeScene = new InGame(&configUtil, &surfaceMgr, &netUtil, &playerID);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw(std::logic_error("Failed to recognize the scene index"));
|
||||
}
|
||||
}
|
||||
|
||||
void SceneManager::UnloadScene() {
|
||||
delete activeScene;
|
||||
activeScene = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef SCENEMANAGER_HPP_
|
||||
#define SCENEMANAGER_HPP_
|
||||
|
||||
#include "scene_list.hpp"
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "surface_manager.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "packet_list.hpp"
|
||||
|
||||
#include "SDL/SDL.h"
|
||||
|
||||
class SceneManager {
|
||||
public:
|
||||
//Public access members
|
||||
SceneManager();
|
||||
~SceneManager();
|
||||
|
||||
void Init();
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
//Private access members
|
||||
void LoadScene(SceneList sceneIndex);
|
||||
void UnloadScene();
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
|
||||
//globals
|
||||
ConfigUtility configUtil;
|
||||
SurfaceManager surfaceMgr;
|
||||
UDPNetworkUtility netUtil;
|
||||
int playerID = -1;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "splash.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
Splash::Splash(ConfigUtility* cUtil, SurfaceManager* sMgr) {
|
||||
#ifdef DEBUG
|
||||
cout << "entering Splash" << endl;
|
||||
#endif
|
||||
configUtil = cUtil;
|
||||
surfaceMgr = sMgr;
|
||||
|
||||
logo = new Image(surfaceMgr->Load("splash-logo", configUtil->String("logos") + "/krstudios.bmp"));
|
||||
}
|
||||
|
||||
Splash::~Splash() {
|
||||
delete logo;
|
||||
surfaceMgr->Free("splash-logo");
|
||||
#ifdef DEBUG
|
||||
cout << "leaving Splash" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Splash::RunFrame(double delta) {
|
||||
//skip any event handling here
|
||||
SDL_Event event;
|
||||
while(SDL_PollEvent(&event));
|
||||
|
||||
//draw the logo in the middle of the screen
|
||||
int x = (GetScreen()->w - logo->GetClipW()) / 2;
|
||||
int y = (GetScreen()->h - logo->GetClipH()) / 2;
|
||||
|
||||
logo->DrawTo(GetScreen(),x,y);
|
||||
SDL_Flip(GetScreen());
|
||||
|
||||
//load the resources ONCE
|
||||
if (!loaded) {
|
||||
loaded = true;
|
||||
LoadResources();
|
||||
}
|
||||
|
||||
//wait X seconds
|
||||
if (Clock::now() - start > std::chrono::duration<int>(1)) {
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
}
|
||||
|
||||
void Splash::LoadResources() {
|
||||
//load the global resources here
|
||||
surfaceMgr->Load("font", configUtil->String("fonts") + "/pokemon_dark_font.bmp");
|
||||
surfaceMgr->Load("button", configUtil->String("interface") + "/button.bmp");
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef SPLASH_HPP_
|
||||
#define SPLASH_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "surface_manager.hpp"
|
||||
#include "image.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
class Splash : public BaseScene {
|
||||
public:
|
||||
Splash(ConfigUtility*, SurfaceManager*);
|
||||
~Splash();
|
||||
|
||||
protected:
|
||||
typedef std::chrono::high_resolution_clock Clock;
|
||||
void RunFrame(double delta);
|
||||
void RenderFrame() {};
|
||||
|
||||
void LoadResources();
|
||||
|
||||
//globals
|
||||
ConfigUtility* configUtil;
|
||||
SurfaceManager* surfaceMgr;
|
||||
|
||||
//members
|
||||
bool loaded = false;
|
||||
Clock::time_point start = Clock::now();
|
||||
Image* logo = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,170 @@
|
||||
#include "test_systems.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "splash.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
TestSystems::TestSystems(ConfigUtility* cUtil, SurfaceManager* sMgr, UDPNetworkUtility* nUtil) {
|
||||
#ifdef DEBUG
|
||||
cout << "entering TestSystems" << endl;
|
||||
#endif
|
||||
configUtil = cUtil;
|
||||
surfaceMgr = sMgr;
|
||||
netUtil = nUtil;
|
||||
|
||||
playerCounter = currentPlayer = 0;
|
||||
|
||||
playerMgr.New(playerCounter++, surfaceMgr->Get("elliot"));
|
||||
playerMgr.New(playerCounter++, surfaceMgr->Get("elliot"));
|
||||
playerMgr.New(playerCounter++, surfaceMgr->Get("coa"));
|
||||
playerMgr.New(playerCounter++, surfaceMgr->Get("coa"));
|
||||
|
||||
font.SetSurface(surfaceMgr->Get("font"));
|
||||
}
|
||||
|
||||
TestSystems::~TestSystems() {
|
||||
playerMgr.DeleteAll();
|
||||
#ifdef DEBUG
|
||||
cout << "leaving TestSystems" << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void TestSystems::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void TestSystems::Update(double delta) {
|
||||
playerMgr.UpdateAll(delta);
|
||||
}
|
||||
|
||||
void TestSystems::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
string IToS(int i) {
|
||||
char buffer[20];
|
||||
memset(buffer, 0, 20);
|
||||
sprintf(buffer, "%d", i);
|
||||
return string(buffer);
|
||||
}
|
||||
|
||||
void TestSystems::Render(SDL_Surface* const screen) {
|
||||
FrameRate::Calculate();
|
||||
playerMgr.DrawAllTo(screen);
|
||||
font.DrawStringTo("FPS: " + IToS(FrameRate::GetFrameRate()), screen, 16, 16);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void TestSystems::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
//
|
||||
}
|
||||
|
||||
void TestSystems::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void TestSystems::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
//
|
||||
}
|
||||
|
||||
void TestSystems::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
break;
|
||||
|
||||
case SDLK_w:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::NORTH);
|
||||
SendMessage("move up");
|
||||
break;
|
||||
case SDLK_s:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::SOUTH);
|
||||
SendMessage("move down");
|
||||
break;
|
||||
case SDLK_a:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::WEST);
|
||||
SendMessage("move left");
|
||||
break;
|
||||
case SDLK_d:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::EAST);
|
||||
SendMessage("move right");
|
||||
break;
|
||||
|
||||
case SDLK_1:
|
||||
SwitchToPlayer(0);
|
||||
break;
|
||||
case SDLK_2:
|
||||
SwitchToPlayer(1);
|
||||
break;
|
||||
case SDLK_3:
|
||||
SwitchToPlayer(2);
|
||||
break;
|
||||
case SDLK_4:
|
||||
SwitchToPlayer(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TestSystems::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_w:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::SOUTH);
|
||||
break;
|
||||
case SDLK_s:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::NORTH);
|
||||
break;
|
||||
case SDLK_a:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::EAST);
|
||||
break;
|
||||
case SDLK_d:
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::WEST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Utilities
|
||||
//-------------------------
|
||||
|
||||
void TestSystems::NewPlayer(int index, std::string avatarName, int x, int y) {
|
||||
Player* p = playerMgr.New(index, surfaceMgr->Get(avatarName));
|
||||
p->SetPosition(Vector2(x, y));
|
||||
}
|
||||
|
||||
void TestSystems::SwitchToPlayer(int index) {
|
||||
//dirty hacks for smooth movement
|
||||
playerMgr[currentPlayer]->SetMotion(Vector2(0,0));
|
||||
currentPlayer = index;
|
||||
|
||||
Uint8* key = SDL_GetKeyState(nullptr);
|
||||
|
||||
if (key[SDLK_w]) {
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::NORTH);
|
||||
}
|
||||
if (key[SDLK_s]) {
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::SOUTH);
|
||||
}
|
||||
if (key[SDLK_a]) {
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::WEST);
|
||||
}
|
||||
if (key[SDLK_d]) {
|
||||
playerMgr[currentPlayer]->WalkInDirection(Direction::EAST);
|
||||
}
|
||||
}
|
||||
|
||||
void TestSystems::SendMessage(std::string s) {
|
||||
cout << s << endl;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef TESTSYSTEMS_HPP_
|
||||
#define TESTSYSTEMS_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "config_utility.hpp"
|
||||
#include "surface_manager.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
#include "packet_list.hpp"
|
||||
|
||||
#include "player_manager.hpp"
|
||||
#include "frame_rate.hpp"
|
||||
#include "raster_font.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
class TestSystems : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
TestSystems(ConfigUtility*, SurfaceManager*, UDPNetworkUtility*);
|
||||
~TestSystems();
|
||||
|
||||
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&);
|
||||
|
||||
//utilities
|
||||
void NewPlayer(int index, std::string avatarName, int x, int y);
|
||||
void SwitchToPlayer(int index);
|
||||
void SendMessage(std::string);
|
||||
|
||||
//members
|
||||
ConfigUtility* configUtil = nullptr;
|
||||
SurfaceManager* surfaceMgr = nullptr;
|
||||
UDPNetworkUtility* netUtil = nullptr;
|
||||
|
||||
PlayerManager playerMgr;
|
||||
RasterFont font;
|
||||
|
||||
int playerCounter;
|
||||
int currentPlayer;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int SDL_main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -23,8 +23,29 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
Button::Button():
|
||||
Button(0,0, nullptr, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Button::Button(Sint16 i, Sint16 j, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string s) {
|
||||
x = i;
|
||||
y = j;
|
||||
state = State::NORMAL;
|
||||
|
||||
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 +63,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;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -27,67 +27,53 @@
|
||||
|
||||
#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();
|
||||
Button(Sint16 x, Sint16 y, SDL_Surface* imageSurface, SDL_Surface* fontSurface, std::string text = "");
|
||||
|
||||
//handle input
|
||||
//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 ℑ }
|
||||
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;
|
||||
|
||||
//
|
||||
State state = State::NORMAL;
|
||||
Sint16 x, y;
|
||||
Sint16 textX, textY; //prevent recalc every loop
|
||||
Image image;
|
||||
RasterFont font;
|
||||
State state;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* 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 "config_utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ConfigUtility::Load(string fname) {
|
||||
ifstream is(fname);
|
||||
|
||||
if (!is.is_open()) {
|
||||
throw(runtime_error("Failed to open config file"));
|
||||
}
|
||||
|
||||
string key, val;
|
||||
|
||||
for (;;) { //forever
|
||||
//eat whitespace
|
||||
while(isspace(is.peek()))
|
||||
is.ignore();
|
||||
|
||||
//end of file
|
||||
if (is.eof())
|
||||
break;
|
||||
|
||||
//skip comment lines
|
||||
if (is.peek() == '#') {
|
||||
while(is.peek() != '\n' && !is.eof()) {
|
||||
is.ignore();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//read in the pair
|
||||
getline(is, key,'=');
|
||||
getline(is, val);
|
||||
|
||||
//trim the strings at the start & end
|
||||
while(key.size() && isspace(*key.begin())) key.erase(0, 1);
|
||||
while(val.size() && isspace(*val.begin())) val.erase(0, 1);
|
||||
|
||||
while(key.size() && isspace(*(key.end()-1))) key.erase(key.end() - 1);
|
||||
while(val.size() && isspace(*(val.end()-1))) val.erase(val.end() - 1);
|
||||
|
||||
//allow empty/wiped values
|
||||
if (key.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//save the pair
|
||||
table[key] = val;
|
||||
}
|
||||
|
||||
is.close();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* 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
|
||||
@@ -19,36 +19,50 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef TILESHEET_HPP_
|
||||
#define TILESHEET_HPP_
|
||||
|
||||
#include "region.hpp"
|
||||
|
||||
#include "image.hpp"
|
||||
#ifndef CONFIGUTILITY_HPP_
|
||||
#define CONFIGUTILITY_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
class TileSheet {
|
||||
class ConfigUtility {
|
||||
public:
|
||||
TileSheet() = default;
|
||||
TileSheet(std::string f, int w, int h) { Load(f, w, h); }
|
||||
~TileSheet() = default;
|
||||
ConfigUtility() {}
|
||||
ConfigUtility(std::string s) { Load(s); }
|
||||
|
||||
void Load(std::string fname, int tileWidth, int tileHeight);
|
||||
void Unload();
|
||||
void Load(std::string fname);
|
||||
|
||||
void DrawTileTo(SDL_Surface* const dest, int x, int y, Region::type_t tile);
|
||||
void DrawRegionTo(SDL_Surface* const dest, Region* const region, int camX, int camY);
|
||||
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";
|
||||
}
|
||||
|
||||
//accessors
|
||||
Image* GetImage() { return ℑ }
|
||||
int GetXCount() { return xCount; }
|
||||
int GetYCount() { return yCount; }
|
||||
int GetTileW() { return image.GetClipW(); }
|
||||
int GetTileH() { return image.GetClipH(); }
|
||||
std::string& operator[](std::string s) {
|
||||
return table[s];
|
||||
}
|
||||
int Int(std::string s) {
|
||||
return Integer(s);
|
||||
}
|
||||
int Bool(std::string s) {
|
||||
return Boolean(s);
|
||||
}
|
||||
std::map<std::string, std::string>* GetMap() {
|
||||
return &table;
|
||||
}
|
||||
private:
|
||||
Image image;
|
||||
int xCount = 0, yCount = 0;
|
||||
std::map<std::string, std::string> table;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* 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
|
||||
@@ -19,12 +19,8 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGIONAPI_HPP_
|
||||
#define REGIONAPI_HPP_
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#define TORTUGA_REGION_NAME "Region"
|
||||
LUAMOD_API int openRegionAPI(lua_State* L);
|
||||
|
||||
#endif
|
||||
int FrameRate::frameCount = 0;
|
||||
int FrameRate::lastFrameRate = 0;
|
||||
FrameRate::Clock::time_point FrameRate::tick = FrameRate::Clock::now();
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* 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
|
||||
@@ -28,8 +28,8 @@ class FrameRate {
|
||||
public:
|
||||
typedef std::chrono::high_resolution_clock Clock;
|
||||
|
||||
FrameRate() = default;
|
||||
int Calculate() {
|
||||
FrameRate() = delete;
|
||||
static int Calculate() {
|
||||
frameCount++;
|
||||
if (Clock::now() - tick >= std::chrono::duration<int>(1)) {
|
||||
lastFrameRate = frameCount;
|
||||
@@ -38,11 +38,11 @@ public:
|
||||
}
|
||||
return lastFrameRate;
|
||||
}
|
||||
int GetFrameRate() { return lastFrameRate; }
|
||||
static int GetFrameRate() { return lastFrameRate; }
|
||||
private:
|
||||
int frameCount = 0;
|
||||
int lastFrameRate = 0;
|
||||
Clock::time_point tick = Clock::now();
|
||||
static int frameCount;
|
||||
static int lastFrameRate;
|
||||
static Clock::time_point tick;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -19,34 +19,36 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef SPLASHSCREEN_HPP_
|
||||
#define SPLASHSCREEN_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "image.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
Image::Image(SDL_Surface* p) {
|
||||
SetSurface(p);
|
||||
}
|
||||
|
||||
#include <chrono>
|
||||
Image::Image(SDL_Surface* p, SDL_Rect r) {
|
||||
SetSurface(p, r);
|
||||
}
|
||||
|
||||
class SplashScreen : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
SplashScreen(lua_State* L);
|
||||
~SplashScreen();
|
||||
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;
|
||||
}
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void Update(double delta);
|
||||
void Render(SDL_Surface* const);
|
||||
SDL_Surface* Image::SetSurface(SDL_Surface* const p, SDL_Rect r) {
|
||||
surface = p;
|
||||
clip = r;
|
||||
return surface;
|
||||
}
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
|
||||
//members
|
||||
std::chrono::steady_clock::time_point startTick;
|
||||
Image logo;
|
||||
};
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -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,18 +1,18 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
INCLUDES=
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
LIB=
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
SRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
OUTDIR=out
|
||||
OUT=$(addprefix $(OUTDIR)/,common.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
@@ -0,0 +1,109 @@
|
||||
#ifndef PACKETLIST_HPP_
|
||||
#define PACKETLIST_HPP_
|
||||
|
||||
#include "vector2.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#define PACKET_STRING_SIZE 100
|
||||
|
||||
enum class PacketList {
|
||||
NONE = 0,
|
||||
|
||||
//connections
|
||||
PING = 1,
|
||||
PONG = 2,
|
||||
JOINREQUEST = 3,
|
||||
JOINCONFIRM = 4,
|
||||
DISCONNECT = 5,
|
||||
|
||||
//information control
|
||||
SYNCHRONIZE = 6,
|
||||
NEWPLAYER = 7,
|
||||
DELETEPLAYER = 8,
|
||||
MOVEMENT = 9,
|
||||
};
|
||||
|
||||
//-------------------------
|
||||
//connections
|
||||
//-------------------------
|
||||
|
||||
struct Ping {
|
||||
PacketList type = PacketList::PING;
|
||||
char metadata[PACKET_STRING_SIZE];
|
||||
};
|
||||
|
||||
struct Pong {
|
||||
PacketList type = PacketList::PONG;
|
||||
char metadata[PACKET_STRING_SIZE];
|
||||
};
|
||||
|
||||
struct JoinRequest {
|
||||
PacketList type = PacketList::JOINREQUEST;
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
};
|
||||
|
||||
struct JoinConfirm {
|
||||
PacketList type = PacketList::JOINCONFIRM;
|
||||
int playerID;
|
||||
};
|
||||
|
||||
struct Disconnect {
|
||||
PacketList type = PacketList::DISCONNECT;
|
||||
int playerID;
|
||||
};
|
||||
|
||||
//-------------------------
|
||||
//information control
|
||||
//-------------------------
|
||||
|
||||
struct Synchronize {
|
||||
PacketList type = PacketList::SYNCHRONIZE;
|
||||
int playerID;
|
||||
};
|
||||
|
||||
struct NewPlayer {
|
||||
PacketList type = PacketList::NEWPLAYER;
|
||||
int playerID;
|
||||
char handle[PACKET_STRING_SIZE];
|
||||
char avatar[PACKET_STRING_SIZE];
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
};
|
||||
|
||||
struct DeletePlayer {
|
||||
PacketList type = PacketList::DELETEPLAYER;
|
||||
int playerID;
|
||||
};
|
||||
|
||||
struct Movement {
|
||||
PacketList type = PacketList::MOVEMENT;
|
||||
int playerID;
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
};
|
||||
|
||||
//-------------------------
|
||||
//the packet itself
|
||||
//-------------------------
|
||||
|
||||
union PacketData {
|
||||
PacketData() {};
|
||||
PacketList type = PacketList::NONE;
|
||||
|
||||
//connections
|
||||
Ping ping;
|
||||
Pong pong;
|
||||
JoinRequest joinRequest;
|
||||
JoinConfirm joinConfirm;
|
||||
Disconnect disconnect;
|
||||
|
||||
//information control
|
||||
Synchronize synchronize;
|
||||
NewPlayer newPlayer;
|
||||
DeletePlayer deletePlayer;
|
||||
Movement movement;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -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;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -19,23 +19,26 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "application.hpp"
|
||||
#include "sprite_sheet.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
try {
|
||||
Application app;
|
||||
app.Init(argc, argv);
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
}
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal exception thrown: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
ticks = 0;
|
||||
}
|
||||
image.SetClipX(currentFrame * image.GetClipW());
|
||||
image.SetClipY(currentStrip * image.GetClipH());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
/* 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
|
||||
@@ -19,36 +19,31 @@
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef TIMER_HPP_
|
||||
#define TIMER_HPP_
|
||||
#ifndef SURFACEMANAGER_HPP_
|
||||
#define SURFACEMANAGER_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include "SDL/SDL.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
class Timer {
|
||||
class SurfaceManager {
|
||||
public:
|
||||
typedef std::chrono::high_resolution_clock Clock;
|
||||
SurfaceManager() = default;
|
||||
~SurfaceManager() noexcept;
|
||||
|
||||
Timer() = default;
|
||||
Timer(std::string s) : name(s), start(Clock::now()) {};
|
||||
~Timer() = default;
|
||||
|
||||
inline void Start() { start = Clock::now(); }
|
||||
inline void Stop() { time = Clock::now() - start; }
|
||||
|
||||
//accessors and mutators
|
||||
Clock::duration GetTime() { return time; }
|
||||
|
||||
std::string SetName(std::string s) { return name = s; }
|
||||
std::string GetName() { return 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();
|
||||
|
||||
SDL_Surface* operator[](std::string key) { return Get(key); };
|
||||
private:
|
||||
std::string name;
|
||||
Clock::time_point start;
|
||||
Clock::duration time;
|
||||
SDL_Surface* LoadSurface(std::string key, std::string fname);
|
||||
typedef std::map<std::string, SDL_Surface*> MapType;
|
||||
MapType surfaceMap;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Timer& t);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,148 @@
|
||||
/* 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 "udp_network_utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
void UDPNetworkUtility::Open(int port, int packSize) {
|
||||
if (!(socket = SDLNet_UDP_Open(port))) {
|
||||
Close();
|
||||
throw(std::runtime_error("Failed to open a UDP socket"));
|
||||
}
|
||||
|
||||
if (!(packOut = SDLNet_AllocPacket(packSize))) {
|
||||
Close();
|
||||
throw(std::runtime_error("Failed to allocate the out packet"));
|
||||
}
|
||||
|
||||
if (!(packIn = SDLNet_AllocPacket(packSize))) {
|
||||
Close();
|
||||
throw(std::runtime_error("Failed to allocate the in packet"));
|
||||
}
|
||||
}
|
||||
|
||||
void UDPNetworkUtility::Close() {
|
||||
SDLNet_UDP_Close(socket);
|
||||
SDLNet_FreePacket(packOut);
|
||||
SDLNet_FreePacket(packIn);
|
||||
socket = nullptr;
|
||||
packOut = nullptr;
|
||||
packIn = nullptr;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Bind(const char* ip, int port, int channel) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
throw(std::runtime_error("Failed to resolve a host"));
|
||||
}
|
||||
|
||||
return Bind(&add, channel);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Bind(IPaddress* add, int channel) {
|
||||
int ret = SDLNet_UDP_Bind(socket, channel, add);
|
||||
|
||||
if (ret == -1) {
|
||||
throw(std::runtime_error("Failed to bind to a channel"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UDPNetworkUtility::Unbind(int channel) {
|
||||
SDLNet_UDP_Unbind(socket, channel);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Send(const char* ip, int port, void* data, int len) {
|
||||
IPaddress add;
|
||||
if (SDLNet_ResolveHost(&add, ip, port) == -1) {
|
||||
throw(std::runtime_error("Failed to resolve a host"));
|
||||
}
|
||||
|
||||
Send(&add, data, len);
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Send(IPaddress* add, void* data, int len) {
|
||||
if (len > packOut->maxlen) {
|
||||
throw(std::runtime_error("Failed to copy the data into the packet"));
|
||||
}
|
||||
memset(packOut->data, 0, packOut->maxlen);
|
||||
memcpy(packOut->data, data, len);
|
||||
packOut->len = len;
|
||||
packOut->address = *add;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, -1, packOut);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Send(int channel, void* data, int len) {
|
||||
if (len > packOut->maxlen) {
|
||||
throw(std::runtime_error("Failed to copy the data into the packet"));
|
||||
}
|
||||
memset(packOut->data, 0, packOut->maxlen);
|
||||
memcpy(packOut->data, data, len);
|
||||
packOut->len = len;
|
||||
|
||||
int ret = SDLNet_UDP_Send(socket, channel, packOut);
|
||||
|
||||
if (ret <= 0) {
|
||||
throw(std::runtime_error("Failed to send a packet"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::SendAll(void* data, int len) {
|
||||
if (len > packOut->maxlen) {
|
||||
throw(std::runtime_error("Failed to copy the data into the packet"));
|
||||
}
|
||||
memset(packOut->data, 0, packOut->maxlen);
|
||||
memcpy(packOut->data, data, len);
|
||||
packOut->len = len;
|
||||
|
||||
int sent = 0;
|
||||
|
||||
//send to all bound channels
|
||||
for (int i = 0; i < SDLNET_MAX_UDPCHANNELS; i++) {
|
||||
if (SDLNet_UDP_GetPeerAddress(socket, i)) {
|
||||
sent += SDLNet_UDP_Send(socket, i, packOut);
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
int UDPNetworkUtility::Receive() {
|
||||
memset(packIn->data, 0, packIn->maxlen);
|
||||
int ret = SDLNet_UDP_Recv(socket, packIn);
|
||||
|
||||
if (ret < 0) {
|
||||
throw(std::runtime_error("Unknown network error occured"));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* 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 UDPNETWORKUTILITY_HPP_
|
||||
#define UDPNETWORKUTILITY_HPP_
|
||||
|
||||
#include "SDL_net/SDL_net.h"
|
||||
|
||||
class UDPNetworkUtility {
|
||||
public:
|
||||
UDPNetworkUtility() = default;
|
||||
~UDPNetworkUtility() = default;
|
||||
|
||||
void Open(int port, int packSize);
|
||||
void Close();
|
||||
|
||||
//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) {
|
||||
return SDLNet_UDP_GetPeerAddress(socket, channel);
|
||||
}
|
||||
|
||||
int Send(const char* ip, int port, void* data, int len);
|
||||
int Send(IPaddress* add, void* data, int len);
|
||||
int Send(int channel, void* data, int len);
|
||||
int SendAll(void* data, int len);
|
||||
int Receive();
|
||||
|
||||
void* GetOutData() const {
|
||||
return reinterpret_cast<void*>(packOut->data);
|
||||
};
|
||||
void* GetInData() const {
|
||||
return reinterpret_cast<void*>(packIn->data);
|
||||
};
|
||||
UDPpacket* GetOutPacket() const {
|
||||
return packOut;
|
||||
}
|
||||
UDPpacket* GetInPacket() const {
|
||||
return packIn;
|
||||
}
|
||||
UDPsocket GetSocket() const {
|
||||
return socket;
|
||||
}
|
||||
private:
|
||||
UDPsocket socket = nullptr;
|
||||
UDPpacket* packOut = nullptr;
|
||||
UDPpacket* packIn = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
/* 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
|
||||
@@ -22,80 +22,50 @@
|
||||
#ifndef VECTOR2_HPP_
|
||||
#define VECTOR2_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
class Vector2 {
|
||||
public:
|
||||
double x, y;
|
||||
|
||||
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);
|
||||
}
|
||||
double SquaredLength() const {
|
||||
return x*x+y*y;
|
||||
}
|
||||
void Normalize() {
|
||||
double l = Length();
|
||||
if (l == 0)
|
||||
throw(std::domain_error("Divide by zero"));
|
||||
x /= l;
|
||||
y /= l;
|
||||
|
||||
double operator[](size_t i) {
|
||||
if (i >= 2)
|
||||
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; }
|
||||
@@ -104,7 +74,4 @@ public:
|
||||
template<typename T> bool operator!=(T t) { return (x != t || y != t); }
|
||||
};
|
||||
|
||||
//This is explicitly a POD
|
||||
static_assert(std::is_pod<Vector2>::value, "Vector2 is not a POD");
|
||||
|
||||
#endif
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
INCLUDES=
|
||||
CFLAGS+=$(addprefix -I,$(INCLUDES))
|
||||
LIB=
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
SRC=$(wildcard *.c)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.c=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=..
|
||||
OUT=$(addprefix $(OUTDIR)/,libcommon.a)
|
||||
OUTDIR=out
|
||||
OUT=$(addprefix $(OUTDIR)/,libSDL_net.a)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
@@ -28,8 +28,8 @@ $(OBJDIR):
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
@@ -1,22 +0,0 @@
|
||||
#for use on Windows:
|
||||
|
||||
#MKDIR=mkdir
|
||||
#RM=del /y
|
||||
|
||||
#CXXFLAGS+=-static-libgcc -static-libstdc++ -g -fno-inline-functions -Wall
|
||||
#CXXFLAGS+=-static-libgcc -static-libstdc++
|
||||
|
||||
#export
|
||||
|
||||
OUTDIR=out
|
||||
|
||||
all: $(OUTDIR)
|
||||
$(MAKE) -C src
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -1,3 +0,0 @@
|
||||
--reroute the program while in development
|
||||
config = {debug = true}
|
||||
dofile("../rsc/setup.lua")
|
||||
@@ -0,0 +1,19 @@
|
||||
#configuration of the program
|
||||
server.host = 127.0.0.1
|
||||
server.port = 2000
|
||||
screen.w = 800
|
||||
screen.h = 600
|
||||
screen.f = false
|
||||
|
||||
#directories
|
||||
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
|
||||
servername = foobar
|
||||
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 768 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 108 KiB |
@@ -1,9 +0,0 @@
|
||||
--overwriting the existing hard coded methods
|
||||
function Region.Load(region)
|
||||
--the return value signals if this succeeded or failed
|
||||
return false
|
||||
end
|
||||
|
||||
function Region.Save(region)
|
||||
--
|
||||
end
|
||||
@@ -1,16 +0,0 @@
|
||||
--uber lazy declarations
|
||||
function math.sqr(x) return x*x end
|
||||
function math.dist(x, y, i, j) return math.sqrt(math.sqr(x-i) + math.sqr(y-j)) end
|
||||
|
||||
--define these
|
||||
function Region.Create(region)
|
||||
for i = 1, Region.GetWidth() do
|
||||
for j = 1, Region.GetHeight() do
|
||||
Region.SetTile(region, i, j, 1, 1) --to show the basics are working
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Region.Unload(region)
|
||||
--
|
||||
end
|
||||
@@ -1,33 +0,0 @@
|
||||
local sheet = TileSheet.GetTileSheet()
|
||||
local pager = RegionPager.GetRegionPager()
|
||||
|
||||
--the selected tilesheet
|
||||
TileSheet.Load(sheet, config.dir.tilesets .. "terrain.bmp", 32, 32)
|
||||
|
||||
--tile macros, mapped to this tilesheet
|
||||
local base = 14
|
||||
local shift = 36
|
||||
tiles = {
|
||||
plains = base + shift * 0,
|
||||
grass = base + shift * 1,
|
||||
dirt = base + shift * 2,
|
||||
sand = base + shift * 3,
|
||||
water = base + shift * 4
|
||||
}
|
||||
|
||||
--could set custom generation systems here, that differ from the global generators, etc.
|
||||
function Region.Create(region)
|
||||
for i = 1, Region.GetWidth() do
|
||||
for j = 1, Region.GetHeight() do
|
||||
local dist = math.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1)
|
||||
if dist < 10 then
|
||||
Region.SetTile(region, i, j, 1, tiles.plains)
|
||||
elseif dist < 12 then
|
||||
Region.SetTile(region, i, j, 1, tiles.sand)
|
||||
else
|
||||
Region.SetTile(region, i, j, 1, tiles.water)
|
||||
Region.SetSolid(region, i, j, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,42 +0,0 @@
|
||||
--[[
|
||||
--reroute the program while in development
|
||||
config = {debug = true}
|
||||
dofile("../rsc/setup.lua")
|
||||
--]]
|
||||
|
||||
--catch the debug signal if the program was rerouted
|
||||
local debug = false
|
||||
if config ~= nil then
|
||||
debug = config.debug
|
||||
end
|
||||
|
||||
--the program's configuration
|
||||
config = {
|
||||
debug = debug,
|
||||
screen = {
|
||||
width = 800,
|
||||
height = 600,
|
||||
fullscreen = false
|
||||
},
|
||||
dir = {
|
||||
fonts = "rsc/graphics/fonts/",
|
||||
logos = "rsc/graphics/logos/",
|
||||
sprites = "rsc/graphics/sprites/",
|
||||
tilesets = "rsc/graphics/tilesets/",
|
||||
interface = "rsc/graphics/interface/",
|
||||
scripts = "rsc/scripts/",
|
||||
maps = "rsc/maps/"
|
||||
},
|
||||
mapname = "mapname"
|
||||
}
|
||||
|
||||
--development environment
|
||||
if config.debug then
|
||||
for k, v in pairs(config.dir) do
|
||||
config.dir[k] = string.format("../%s", v)
|
||||
end
|
||||
end
|
||||
|
||||
--"load" the scripted systems
|
||||
dofile(config.dir.scripts .. "file_format.lua")
|
||||
dofile(config.dir.scripts .. "generator.lua")
|
||||
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,32 @@
|
||||
#ifndef CLIENTDATA_HPP_
|
||||
#define CLIENTDATA_HPP_
|
||||
|
||||
#include "vector2.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct ClientData {
|
||||
ClientData() = default;
|
||||
ClientData(int ID, int ch, std::string h, std::string a) {
|
||||
playerID = ID;
|
||||
channel = ch;
|
||||
handle = h;
|
||||
avatar = a;
|
||||
}
|
||||
void Update(double delta) {
|
||||
position += motion * delta;
|
||||
}
|
||||
|
||||
int playerID = -1;
|
||||
int channel = -1;
|
||||
Vector2 position;
|
||||
Vector2 motion;
|
||||
std::string handle;
|
||||
std::string avatar;
|
||||
enum class Command {
|
||||
NORMAL,
|
||||
CHANGED,
|
||||
}command = Command::NORMAL;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "server_application.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int, char**) {
|
||||
#ifdef DEBUG
|
||||
cout << "Beginning server" << endl;
|
||||
#endif
|
||||
try {
|
||||
ServerApplication app;
|
||||
app.Init();
|
||||
app.Proc();
|
||||
app.Quit();
|
||||
}
|
||||
catch(exception& e) {
|
||||
cerr << "Fatal error: " << e.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
cout << "Clean exit" << endl;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#config
|
||||
INCLUDES=../common
|
||||
CXXFLAGS+=-std=c++11 -DDEBUG $(addprefix -I,$(INCLUDES))
|
||||
LIB=../common/out/common.a -lmingw32 -lSDL_net -lSDLmain -lSDL -lwsock32 -liphlpapi
|
||||
|
||||
#source
|
||||
SRC=$(filter-out unit.cpp main.cpp, $(wildcard *.cpp))
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ=$(addprefix $(OBJDIR)/,$(SRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=out
|
||||
|
||||
#targets
|
||||
all: server unit
|
||||
|
||||
server: $(OBJ) $(OUT)
|
||||
$(CXX) $(CXXFLAGS) -o $(OUTDIR)/$@ main.cpp $(OBJ) $(LIB)
|
||||
|
||||
unit: $(OBJ) $(OUT)
|
||||
$(CXX) $(CXXFLAGS) -o $(OUTDIR)/$@ unit.cpp $(OBJ) $(LIB)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -0,0 +1,185 @@
|
||||
#include "server_application.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ServerApplication::Init() {
|
||||
if (SDLNet_Init()) {
|
||||
throw(runtime_error("Failed to initialize SDL_net"));
|
||||
}
|
||||
configUtil.Load("config.cfg");
|
||||
netUtil.Open(configUtil.Integer("server.port"), sizeof(PacketData));
|
||||
running = true;
|
||||
}
|
||||
|
||||
void ServerApplication::Proc() {
|
||||
while(running) {
|
||||
//handle input
|
||||
while(netUtil.Receive()) {
|
||||
PacketData packet;
|
||||
memcpy(reinterpret_cast<void*>(&packet), netUtil.GetInData(), sizeof(PacketData));
|
||||
switch(packet.type) {
|
||||
// case PacketList::NONE:
|
||||
// //
|
||||
// break;
|
||||
case PacketList::PING:
|
||||
Ping(&packet);
|
||||
break;
|
||||
// case PacketList::PONG:
|
||||
// //
|
||||
// break;
|
||||
case PacketList::JOINREQUEST:
|
||||
JoinRequest(&packet);
|
||||
break;
|
||||
// case PacketList::JOINCONFIRM:
|
||||
// //
|
||||
// break;
|
||||
case PacketList::DISCONNECT:
|
||||
Disconnect(packet.disconnect.playerID);
|
||||
break;
|
||||
// case PacketList::SYNCHRONIZE:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::NEWPLAYER:
|
||||
// //
|
||||
// break;
|
||||
// case PacketList::DELETEPLAYER:
|
||||
// //
|
||||
// break;
|
||||
case PacketList::MOVEMENT:
|
||||
Movement(&packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//update the world
|
||||
//TODO Delta::Calculate();
|
||||
// for (auto it : clientMap) {
|
||||
// it.second.Update(Delta::GetTime());
|
||||
// }
|
||||
|
||||
//handle output...
|
||||
//TODO...
|
||||
|
||||
SDL_Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::Quit() {
|
||||
netUtil.Close();
|
||||
SDLNet_Quit();
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//network commands
|
||||
//-------------------------
|
||||
|
||||
void ServerApplication::Ping(PacketData* packet) {
|
||||
//respond to pings with the server name
|
||||
if (!packet) {
|
||||
throw(runtime_error("Ping() received null"));
|
||||
}
|
||||
packet->type = PacketList::PONG;
|
||||
snprintf(packet->pong.metadata,PACKET_STRING_SIZE, "%s",configUtil.CString("servername"));
|
||||
netUtil.Send(&netUtil.GetInPacket()->address, reinterpret_cast<void*>(packet), sizeof(PacketData));
|
||||
}
|
||||
|
||||
void ServerApplication::JoinRequest(PacketData* packet) {
|
||||
if (!packet || clientMap.size() >= maxClients) {
|
||||
//rejection
|
||||
return;
|
||||
}
|
||||
//add the player
|
||||
int playerID = uniqueIndex++;
|
||||
clientMap[playerID].playerID = playerID;
|
||||
clientMap[playerID].channel = netUtil.Bind(&netUtil.GetInPacket()->address, -1);
|
||||
clientMap[playerID].handle = packet->joinRequest.handle;
|
||||
clientMap[playerID].avatar = packet->joinRequest.avatar;
|
||||
|
||||
//debug
|
||||
#ifdef DEBUG
|
||||
cout << "New player:" << endl;
|
||||
cout << "\tplayerID: " << clientMap[playerID].playerID << endl;
|
||||
cout << "\tchannel: " << clientMap[playerID].channel << endl;
|
||||
cout << "\thandle: " << clientMap[playerID].handle << endl;
|
||||
cout << "\tavatar: " << clientMap[playerID].avatar << endl;
|
||||
#else
|
||||
cout << "New player: " << playerID << endl;
|
||||
#endif
|
||||
|
||||
//join confirm
|
||||
PacketData p;
|
||||
p.type = PacketList::JOINCONFIRM;
|
||||
p.joinConfirm.playerID = clientMap[playerID].playerID;
|
||||
netUtil.Send(clientMap[playerID].channel, &p, sizeof(PacketData));
|
||||
|
||||
//send it out to the clients
|
||||
NewClientData(playerID);
|
||||
|
||||
#ifdef DEBUG
|
||||
cout << "current players: " << clientMap.size() << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ServerApplication::Disconnect(int playerID) {
|
||||
if (clientMap.find(playerID) == clientMap.end()) {
|
||||
return;
|
||||
}
|
||||
cout << "disconnecting: " << playerID << endl;
|
||||
|
||||
//delete the player from all clients
|
||||
PacketData p;
|
||||
p.type = PacketList::DELETEPLAYER;
|
||||
p.deletePlayer.playerID = playerID;
|
||||
|
||||
netUtil.SendAll(&p, sizeof(PacketData));
|
||||
|
||||
//remove the player from the server
|
||||
netUtil.Unbind(clientMap[playerID].channel);
|
||||
clientMap.erase(playerID);
|
||||
|
||||
#ifdef DEBUG
|
||||
cout << "current players: " << clientMap.size() << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ServerApplication::Movement(PacketData* packet) {
|
||||
if (!packet) {
|
||||
throw(runtime_error("Movement() received null"));
|
||||
}
|
||||
clientMap[packet->movement.playerID].position = packet->movement.position;
|
||||
clientMap[packet->movement.playerID].motion = packet->movement.motion;
|
||||
//simple relay
|
||||
//TODO: SendClientData(packet->movement.playerID);
|
||||
for (auto it : clientMap) {
|
||||
netUtil.Send(it.second.channel, packet, sizeof(PacketData));
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::NewClientData(int playerID) {
|
||||
if (clientMap.find(playerID) == clientMap.end()) {
|
||||
throw(runtime_error("NewClientData() Failed to find the client"));
|
||||
}
|
||||
//create the packet to send
|
||||
PacketData p;
|
||||
p.type = PacketList::NEWPLAYER;
|
||||
p.newPlayer.playerID = clientMap[playerID].playerID;
|
||||
snprintf(p.newPlayer.handle, PACKET_STRING_SIZE, "%s", clientMap[playerID].handle.c_str());
|
||||
snprintf(p.newPlayer.avatar, PACKET_STRING_SIZE, "%s", clientMap[playerID].avatar.c_str());
|
||||
p.newPlayer.position = clientMap[playerID].position;
|
||||
p.newPlayer.motion = clientMap[playerID].motion;
|
||||
|
||||
//send the packet
|
||||
for (auto it : clientMap) {
|
||||
netUtil.Send(it.second.channel, &p, sizeof(PacketData));
|
||||
}
|
||||
}
|
||||
|
||||
void ServerApplication::SendClientData(int playerID) {
|
||||
//relay a client's data
|
||||
}
|
||||
|
||||
void ServerApplication::SynchronizeClient(int playerID) {
|
||||
//send all server data to a specific client
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef SERVERAPPLICATION_HPP_
|
||||
#define SERVERAPPLICATION_HPP_
|
||||
|
||||
#include "client_data.hpp"
|
||||
|
||||
#include "packet_list.hpp"
|
||||
#include "config_utility.hpp"
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class ServerApplication {
|
||||
public:
|
||||
ServerApplication() = default;
|
||||
~ServerApplication() = default;
|
||||
|
||||
void Init();
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
//network commands
|
||||
void Ping(PacketData*);
|
||||
void JoinRequest(PacketData*);
|
||||
void Disconnect(int playerID);
|
||||
void Movement(PacketData*);
|
||||
|
||||
void NewClientData(int playerID);
|
||||
void SendClientData(int playerID);
|
||||
void SynchronizeClient(int playerID);
|
||||
|
||||
//globals
|
||||
ConfigUtility configUtil;
|
||||
UDPNetworkUtility netUtil;
|
||||
|
||||
//members
|
||||
bool running = false;
|
||||
std::map<int, ClientData> clientMap;
|
||||
int maxClients = SDLNET_MAX_UDPCHANNELS;
|
||||
int uniqueIndex = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "udp_network_utility.hpp"
|
||||
|
||||
#include "SDL_net/SDL_net.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int, char**) {
|
||||
if (SDLNet_Init()) {
|
||||
cerr << "Failed to init SDL_net" << endl;
|
||||
return -1;
|
||||
}
|
||||
UDPNetworkUtility netUtil;
|
||||
|
||||
netUtil.Open(0, 512);
|
||||
|
||||
string s = "Hello world";
|
||||
netUtil.Send("127.0.0.1", 2000, (void*)s.c_str(), s.length());
|
||||
|
||||
netUtil.Close();
|
||||
|
||||
SDLNet_Quit();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial Applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "application.hpp"
|
||||
|
||||
#include "timer.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
//-------------------------
|
||||
//Scene headers
|
||||
//-------------------------
|
||||
|
||||
//Add the custom scene headers here
|
||||
#include "splash_screen.hpp"
|
||||
#include "main_menu.hpp"
|
||||
#include "options_menu.hpp"
|
||||
#include "in_world.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
void Application::Init(int argc, char** argv) {
|
||||
std::cout << "Beginning " << argv[0] << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Initialize the APIs
|
||||
//-------------------------
|
||||
|
||||
//initialize SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
throw(std::runtime_error("Failed to initialize SDL"));
|
||||
}
|
||||
std::cout << "Initialized SDL" << std::endl;
|
||||
|
||||
//initialize lua
|
||||
lua = luaL_newstate();
|
||||
if (!lua) {
|
||||
throw(std::runtime_error("Failed to initialize lua"));
|
||||
}
|
||||
luaL_openlibs(lua);
|
||||
std::cout << "Initialized lua" << std::endl;
|
||||
|
||||
if (luaL_dofile(lua, "rsc\\setup.lua")) {
|
||||
throw(std::runtime_error("Failed to initialize lua's startup script"));
|
||||
}
|
||||
std::cout << "Initialized lua's setup script" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//Setup the screen
|
||||
//-------------------------
|
||||
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, 1, "screen");
|
||||
lua_getfield(lua, 2, "width");
|
||||
lua_getfield(lua, 2, "height");
|
||||
lua_getfield(lua, 2, "fullscreen");
|
||||
|
||||
int w = lua_tointeger(lua, 3);
|
||||
int h = lua_tointeger(lua, 4);
|
||||
int f = lua_toboolean(lua, 5);
|
||||
|
||||
lua_pop(lua, 5);
|
||||
|
||||
BaseScene::SetScreen(w ? w : 800, h ? h : 600, 0, f ? SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN : SDL_HWSURFACE|SDL_DOUBLEBUF);
|
||||
std::cout << "Initialized the screen" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//finalize the startup
|
||||
//-------------------------
|
||||
|
||||
std::cout << "Startup completed successfully" << std::endl;
|
||||
|
||||
//-------------------------
|
||||
//debugging
|
||||
//-------------------------
|
||||
|
||||
//...
|
||||
}
|
||||
|
||||
void Application::Proc() {
|
||||
LoadScene(SceneList::FIRST);
|
||||
|
||||
//prepare the time system
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
|
||||
std::chrono::duration<int, std::milli> delta(16);
|
||||
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();
|
||||
|
||||
Timer runTimer("run");
|
||||
|
||||
//simulate game time
|
||||
while (simTime < realTime) {
|
||||
//call each user defined function
|
||||
activeScene->RunFrame(double(delta.count()) / std::chrono::duration<int, std::milli>::period::den);
|
||||
simTime += delta;
|
||||
}
|
||||
|
||||
runTimer.Stop();
|
||||
|
||||
Timer renderTimer("render");
|
||||
|
||||
//draw the game to the screen
|
||||
activeScene->RenderFrame();
|
||||
|
||||
renderTimer.Stop();
|
||||
|
||||
//debugging output
|
||||
// std::cout << runTimer << std::endl;
|
||||
// std::cout << renderTimer << std::endl;
|
||||
}
|
||||
|
||||
UnloadScene();
|
||||
}
|
||||
|
||||
void Application::Quit() {
|
||||
std::cout << "Shutting down" << std::endl;
|
||||
lua_close(lua);
|
||||
SDL_Quit();
|
||||
std::cout << "Clean exit" << std::endl;
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Private access members
|
||||
//-------------------------
|
||||
|
||||
void Application::LoadScene(SceneList sceneIndex) {
|
||||
UnloadScene();
|
||||
switch(sceneIndex) {
|
||||
//add scene creation calls here
|
||||
case SceneList::FIRST:
|
||||
case SceneList::SPLASHSCREEN:
|
||||
activeScene = new SplashScreen(lua);
|
||||
break;
|
||||
case SceneList::MAINMENU:
|
||||
activeScene = new MainMenu(lua);
|
||||
break;
|
||||
case SceneList::OPTIONSMENU:
|
||||
activeScene = new OptionsMenu(lua);
|
||||
break;
|
||||
case SceneList::INWORLD:
|
||||
activeScene = new InWorld(lua);
|
||||
break;
|
||||
default:
|
||||
throw(std::logic_error("Failed to recognize the scene index"));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::UnloadScene() {
|
||||
delete activeScene;
|
||||
activeScene = nullptr;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef APPLICATION_HPP_
|
||||
#define APPLICATION_HPP_
|
||||
|
||||
#include "scene_list.hpp"
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application() = default;
|
||||
~Application() = default;
|
||||
|
||||
void Init(int argc, char** argv);
|
||||
void Proc();
|
||||
void Quit();
|
||||
|
||||
private:
|
||||
//Private access members
|
||||
void LoadScene(SceneList sceneIndex);
|
||||
void UnloadScene();
|
||||
|
||||
BaseScene* activeScene = nullptr;
|
||||
|
||||
lua_State* lua = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "character.hpp"
|
||||
|
||||
void Character::Update(double delta) {
|
||||
if (motion.x && motion.y) {
|
||||
origin += motion * delta * CHARACTER_WALKING_MOD;
|
||||
}
|
||||
else if (motion != 0) {
|
||||
origin += motion * delta;
|
||||
}
|
||||
sprite.Update(delta);
|
||||
}
|
||||
|
||||
void Character::DrawTo(SDL_Surface* const dest, int camX, int camY) {
|
||||
sprite.DrawTo(dest, origin.x - camX, origin.y - camY);
|
||||
}
|
||||
|
||||
void Character::CorrectSprite() {
|
||||
//NOTE: These must correspond to the sprite sheet in use
|
||||
if (motion.y > 0) {
|
||||
sprite.SetYIndex(0);
|
||||
}
|
||||
else if (motion.y < 0) {
|
||||
sprite.SetYIndex(1);
|
||||
}
|
||||
else if (motion.x > 0) {
|
||||
sprite.SetYIndex(3);
|
||||
}
|
||||
else if (motion.x < 0) {
|
||||
sprite.SetYIndex(2);
|
||||
}
|
||||
|
||||
//animation
|
||||
if (motion != 0) {
|
||||
sprite.SetDelay(0.1);
|
||||
}
|
||||
else {
|
||||
sprite.SetDelay(0);
|
||||
sprite.SetXIndex(0);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef CHARACTER_HPP_
|
||||
#define CHARACTER_HPP_
|
||||
|
||||
//components
|
||||
#include "vector2.hpp"
|
||||
#include "bounding_box.hpp"
|
||||
|
||||
//graphics
|
||||
#include "sprite_sheet.hpp"
|
||||
|
||||
//std namespace
|
||||
#include <cmath>
|
||||
|
||||
//the speeds that the characters move
|
||||
constexpr double CHARACTER_WALKING_SPEED = 140.0;
|
||||
constexpr double CHARACTER_WALKING_MOD = 1.0/sqrt(2.0);
|
||||
|
||||
class Character {
|
||||
public:
|
||||
Character() = default;
|
||||
~Character() = default;
|
||||
|
||||
void Update(double delta);
|
||||
|
||||
//graphics
|
||||
void DrawTo(SDL_Surface* const, int camX, int camY);
|
||||
void CorrectSprite();
|
||||
SpriteSheet* GetSprite() { return &sprite; }
|
||||
|
||||
//accessors and mutators
|
||||
Vector2 SetOrigin(Vector2 v) { return origin = v; }
|
||||
Vector2 GetOrigin() const { return origin; }
|
||||
Vector2 SetMotion(Vector2 v) { return motion = v; }
|
||||
Vector2 GetMotion() const { return motion; }
|
||||
BoundingBox SetBoundingBox(BoundingBox b) { return bounds = b; }
|
||||
BoundingBox GetBoundingBox() const { return bounds; }
|
||||
|
||||
private:
|
||||
//graphics
|
||||
SpriteSheet sprite;
|
||||
|
||||
//position
|
||||
Vector2 origin = {0.0,0.0};
|
||||
Vector2 motion = {0.0,0.0};
|
||||
BoundingBox bounds;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,37 +0,0 @@
|
||||
#config
|
||||
INCLUDES+=.
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.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 $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -1,29 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "timer.hpp"
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Timer& t) {
|
||||
os << t.GetName() << ": ";
|
||||
os << std::chrono::duration_cast<std::chrono::nanoseconds>(t.GetTime()).count();
|
||||
os << "ns";
|
||||
return os;
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "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);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "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;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef 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 ℑ } //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
|
||||
@@ -1,257 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "in_world.hpp"
|
||||
|
||||
#include "timer.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "region_pager_api.hpp"
|
||||
#include "tile_sheet_api.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
InWorld::InWorld(lua_State* L): lua(L) {
|
||||
//register the pager
|
||||
lua_pushstring(lua, TORTUGA_REGION_PAGER_PSEUDO_INDEX);
|
||||
lua_pushlightuserdata(lua, &pager);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//register the tilesheet
|
||||
lua_pushstring(lua, TORTUGA_TILE_SHEET_PSEUDO_INDEX);
|
||||
lua_pushlightuserdata(lua, &tileSheet);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
|
||||
//setup the component objecrs
|
||||
pager.SetLuaState(lua);
|
||||
|
||||
//get the config info
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, -1, "dir");
|
||||
lua_getfield(lua, -1, "fonts");
|
||||
std::string fonts = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -2, "interface");
|
||||
std::string interface = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -3, "sprites");
|
||||
std::string sprites = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -4, "scripts");
|
||||
std::string scripts = lua_tostring(lua, -1);
|
||||
lua_pop(lua, 6);
|
||||
|
||||
//run the additional scripts
|
||||
if (luaL_dofile(lua, (scripts + "in_world.lua").c_str())) {
|
||||
throw(std::runtime_error(std::string() + "Failed to run in_world.lua: " + lua_tostring(lua, -1) ));
|
||||
}
|
||||
|
||||
//setup the utility objects
|
||||
buttonImage.LoadSurface(interface + "button_menu.bmp");
|
||||
buttonImage.SetClipH(buttonImage.GetClipH()/3);
|
||||
font.LoadSurface(fonts + "pk_white_8.bmp");
|
||||
|
||||
//pass the utility objects
|
||||
backButton.SetImage(&buttonImage);
|
||||
backButton.SetFont(&font);
|
||||
|
||||
//set the button positions
|
||||
backButton.SetX(50);
|
||||
backButton.SetY(50 + buttonImage.GetClipH() * 0);
|
||||
|
||||
//set the button texts
|
||||
backButton.SetText("Back");
|
||||
|
||||
//entities
|
||||
character.GetSprite()->LoadSurface(sprites + "elliot2.bmp", 4, 4);
|
||||
character.SetBoundingBox({0, 0,
|
||||
character.GetSprite()->GetImage()->GetClipW(),
|
||||
character.GetSprite()->GetImage()->GetClipH()
|
||||
});
|
||||
|
||||
//setup the camera
|
||||
camera.margin.x = GetScreen()->w / 2 - character.GetSprite()->GetImage()->GetClipW() / 2;
|
||||
camera.margin.y = GetScreen()->h / 2 - character.GetSprite()->GetImage()->GetClipH() / 2;
|
||||
|
||||
//debug
|
||||
//
|
||||
}
|
||||
|
||||
InWorld::~InWorld() {
|
||||
//unregister the map components
|
||||
lua_pushstring(lua, TORTUGA_REGION_PAGER_PSEUDO_INDEX);
|
||||
lua_pushstring(lua, TORTUGA_TILE_SHEET_PSEUDO_INDEX);
|
||||
lua_pushnil(lua);
|
||||
lua_settable(lua, LUA_REGISTRYINDEX);
|
||||
lua_pushnil(lua);
|
||||
lua_settable(lua, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void InWorld::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::Update(double delta) {
|
||||
//update the entities
|
||||
character.Update(delta);
|
||||
|
||||
//check for collisions with the map
|
||||
BoundingBox wallBounds = {0, 0, tileSheet.GetTileW(), tileSheet.GetTileH()};
|
||||
const int xCount = character.GetBoundingBox().w / wallBounds.w + 1;
|
||||
const int yCount = character.GetBoundingBox().h / wallBounds.h + 1;
|
||||
|
||||
for (int i = -1; i <= xCount; ++i) {
|
||||
for (int j = -1; j <= yCount; ++j) {
|
||||
//set the wall's position
|
||||
wallBounds.x = wallBounds.w * i + snapToBase((double)wallBounds.w, character.GetOrigin().x);
|
||||
wallBounds.y = wallBounds.h * j + snapToBase((double)wallBounds.h, character.GetOrigin().y);
|
||||
|
||||
if (!pager.GetSolid(wallBounds.x / wallBounds.w, wallBounds.y / wallBounds.h)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((character.GetOrigin() + character.GetBoundingBox()).CheckOverlap(wallBounds)) {
|
||||
character.SetOrigin(character.GetOrigin() - (character.GetMotion() * delta));
|
||||
character.SetMotion({0,0});
|
||||
character.CorrectSprite();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//update the camera
|
||||
camera.origin.x = character.GetOrigin().x - camera.margin.x;
|
||||
camera.origin.y = character.GetOrigin().y - camera.margin.y;
|
||||
|
||||
//TODO: prune distant regions
|
||||
|
||||
//summon nearby unloaded regions
|
||||
const int left = snapToBase(REGION_WIDTH, camera.origin.x / tileSheet.GetTileW());
|
||||
const int top = snapToBase(REGION_HEIGHT, camera.origin.y / tileSheet.GetTileH());
|
||||
const int right = snapToBase(REGION_WIDTH, (camera.origin.x + GetScreen()->w) / tileSheet.GetTileW());
|
||||
const int bottom = snapToBase(REGION_HEIGHT, (camera.origin.y + GetScreen()->h) / tileSheet.GetTileH());
|
||||
|
||||
for (int i = left - REGION_WIDTH; i <= right + REGION_WIDTH; i += REGION_WIDTH) {
|
||||
for (int j = top - REGION_HEIGHT; j <= bottom + REGION_HEIGHT; j += REGION_HEIGHT) {
|
||||
pager.GetRegion(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void InWorld::RenderFrame() {
|
||||
// SDL_FillRect(GetScreen(), 0, 0);
|
||||
Render(GetScreen());
|
||||
SDL_Flip(GetScreen());
|
||||
fps.Calculate();
|
||||
}
|
||||
|
||||
void InWorld::Render(SDL_Surface* const screen) {
|
||||
//draw all regions
|
||||
for (std::list<Region>::iterator it = pager.GetContainer()->begin(); it != pager.GetContainer()->end(); it++) {
|
||||
tileSheet.DrawRegionTo(screen, &(*it), camera.origin.x, camera.origin.y);
|
||||
}
|
||||
|
||||
//draw the characters
|
||||
character.DrawTo(screen, camera.origin.x, camera.origin.y);
|
||||
|
||||
//draw the UI
|
||||
backButton.DrawTo(screen);
|
||||
font.DrawStringTo(to_string_custom(fps.GetFrameRate()), screen, 0, 0);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void InWorld::QuitEvent() {
|
||||
//exit the game
|
||||
SetNextScene(SceneList::QUIT);
|
||||
}
|
||||
|
||||
void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
backButton.MouseMotion(motion);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
backButton.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (backButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::MAINMENU);
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
//player movement
|
||||
Vector2 motion = character.GetMotion();
|
||||
switch(key.keysym.sym) {
|
||||
case SDLK_LEFT:
|
||||
motion.x -= CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
motion.x += CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_UP:
|
||||
motion.y -= CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
motion.y += CHARACTER_WALKING_SPEED;
|
||||
break;
|
||||
}
|
||||
if (character.GetMotion() != motion) {
|
||||
character.SetMotion(motion);
|
||||
character.CorrectSprite();
|
||||
}
|
||||
}
|
||||
|
||||
void InWorld::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//player movement
|
||||
Vector2 motion = character.GetMotion();
|
||||
switch(key.keysym.sym) {
|
||||
//NOTE: The use of min/max here are to prevent awkward movements
|
||||
case SDLK_LEFT:
|
||||
motion.x = std::min(motion.x + CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
motion.x = std::max(motion.x - CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
case SDLK_UP:
|
||||
motion.y = std::min(motion.y + CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
motion.y = std::max(motion.y - CHARACTER_WALKING_SPEED, 0.0);
|
||||
break;
|
||||
}
|
||||
if (character.GetMotion() != motion) {
|
||||
character.SetMotion(motion);
|
||||
character.CorrectSprite();
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef INWORLD_HPP_
|
||||
#define INWORLD_HPP_
|
||||
|
||||
//graphics & ui
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
//map stuff
|
||||
#include "tile_sheet.hpp"
|
||||
#include "region_pager_lua.hpp"
|
||||
|
||||
//entities
|
||||
#include "character.hpp"
|
||||
|
||||
//utilities
|
||||
#include "frame_rate.hpp"
|
||||
|
||||
//framework
|
||||
#include "base_scene.hpp"
|
||||
|
||||
//APIs
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
class InWorld : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
InWorld(lua_State* L);
|
||||
~InWorld();
|
||||
|
||||
protected:
|
||||
//Frame loop
|
||||
void FrameStart();
|
||||
void Update(double delta);
|
||||
void FrameEnd();
|
||||
void RenderFrame();
|
||||
void Render(SDL_Surface* const);
|
||||
|
||||
//Event handlers
|
||||
void QuitEvent();
|
||||
void MouseMotion(SDL_MouseMotionEvent const&);
|
||||
void MouseButtonDown(SDL_MouseButtonEvent const&);
|
||||
void MouseButtonUp(SDL_MouseButtonEvent const&);
|
||||
void KeyDown(SDL_KeyboardEvent const&);
|
||||
void KeyUp(SDL_KeyboardEvent const&);
|
||||
|
||||
struct {
|
||||
struct {
|
||||
int x, y;
|
||||
}origin, margin;
|
||||
}camera;
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
|
||||
//graphics
|
||||
Image buttonImage;
|
||||
RasterFont font;
|
||||
|
||||
//map stuff
|
||||
TileSheet tileSheet;
|
||||
RegionPagerLua pager;
|
||||
|
||||
//entities
|
||||
Character character;
|
||||
|
||||
//UI
|
||||
Button backButton;
|
||||
FrameRate fps;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,85 +0,0 @@
|
||||
/* $Id: linit.c,v 1.32, modified
|
||||
* Initialization of libraries for lua.c and other clients
|
||||
* See Copyright Notice in lua.h
|
||||
*
|
||||
* If you embed Lua in your program and need to open the standard
|
||||
* libraries, call luaL_openlibs in your program. If you need a
|
||||
* different set of libraries, copy this file to your project and edit
|
||||
* it to suit your needs.
|
||||
*
|
||||
* Modified for use in Tortuga, renamed to linit.cpp
|
||||
* Modifications are released under the zlib license:
|
||||
*
|
||||
* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#define linit_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
#include "region_api.hpp"
|
||||
#include "region_pager_api.hpp"
|
||||
#include "tile_sheet_api.hpp"
|
||||
|
||||
//these libs are loaded by lua.c and are readily available to any Lua program
|
||||
static const luaL_Reg loadedlibs[] = {
|
||||
//Standard libs
|
||||
{"_G", luaopen_base},
|
||||
{LUA_LOADLIBNAME, luaopen_package},
|
||||
{LUA_COLIBNAME, luaopen_coroutine},
|
||||
{LUA_TABLIBNAME, luaopen_table},
|
||||
{LUA_IOLIBNAME, luaopen_io},
|
||||
{LUA_OSLIBNAME, luaopen_os},
|
||||
{LUA_STRLIBNAME, luaopen_string},
|
||||
{LUA_BITLIBNAME, luaopen_bit32},
|
||||
{LUA_MATHLIBNAME, luaopen_math},
|
||||
{LUA_DBLIBNAME, luaopen_debug},
|
||||
|
||||
//Tortuga's API
|
||||
{TORTUGA_REGION_NAME, openRegionAPI},
|
||||
{TORTUGA_REGION_PAGER_NAME, openRegionPagerAPI},
|
||||
{TORTUGA_TILE_SHEET_NAME, openTileSheetAPI},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
//these libs are preloaded and must be required before used
|
||||
static const luaL_Reg preloadedlibs[] = {
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
LUALIB_API void luaL_openlibs (lua_State *L) {
|
||||
const luaL_Reg *lib;
|
||||
//call open functions from 'loadedlibs' and set results to global table
|
||||
for (lib = loadedlibs; lib->func; lib++) {
|
||||
luaL_requiref(L, lib->name, lib->func, 1);
|
||||
lua_pop(L, 1); //remove lib
|
||||
}
|
||||
//add open functions from 'preloadedlibs' into 'package.preload' table
|
||||
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
|
||||
for (lib = preloadedlibs; lib->func; lib++) {
|
||||
lua_pushcfunction(L, lib->func);
|
||||
lua_setfield(L, -2, lib->name);
|
||||
}
|
||||
lua_pop(L, 1); //remove _PRELOAD table
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "main_menu.hpp"
|
||||
|
||||
//-------------------------
|
||||
//Public access members
|
||||
//-------------------------
|
||||
|
||||
MainMenu::MainMenu(lua_State* L): lua(L) {
|
||||
//get the config info
|
||||
lua_getglobal(lua, "config");
|
||||
lua_getfield(lua, -1, "dir");
|
||||
lua_getfield(lua, -1, "interface");
|
||||
std::string interface = lua_tostring(lua, -1);
|
||||
lua_getfield(lua, -2, "fonts");
|
||||
std::string fonts = lua_tostring(lua, -1);
|
||||
lua_pop(lua, 4);
|
||||
|
||||
//setup the utility objects
|
||||
image.LoadSurface(interface + "button_menu.bmp");
|
||||
image.SetClipH(image.GetClipH()/3);
|
||||
font.LoadSurface(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");
|
||||
|
||||
//debug
|
||||
//
|
||||
}
|
||||
|
||||
MainMenu::~MainMenu() {
|
||||
//
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Frame loop
|
||||
//-------------------------
|
||||
|
||||
void MainMenu::FrameStart() {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::Update(double delta) {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::FrameEnd() {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::Render(SDL_Surface* const screen) {
|
||||
startButton.DrawTo(screen);
|
||||
optionsButton.DrawTo(screen);
|
||||
quitButton.DrawTo(screen);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//Event handlers
|
||||
//-------------------------
|
||||
|
||||
void MainMenu::MouseMotion(SDL_MouseMotionEvent const& motion) {
|
||||
startButton.MouseMotion(motion);
|
||||
optionsButton.MouseMotion(motion);
|
||||
quitButton.MouseMotion(motion);
|
||||
}
|
||||
|
||||
void MainMenu::MouseButtonDown(SDL_MouseButtonEvent const& button) {
|
||||
startButton.MouseButtonDown(button);
|
||||
optionsButton.MouseButtonDown(button);
|
||||
quitButton.MouseButtonDown(button);
|
||||
}
|
||||
|
||||
void MainMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) {
|
||||
if (startButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::INWORLD);
|
||||
}
|
||||
if (optionsButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
SetNextScene(SceneList::OPTIONSMENU);
|
||||
}
|
||||
if (quitButton.MouseButtonUp(button) == Button::State::HOVER) {
|
||||
QuitEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenu::KeyDown(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
|
||||
void MainMenu::KeyUp(SDL_KeyboardEvent const& key) {
|
||||
//
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2013, 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef MAINMENU_HPP_
|
||||
#define MAINMENU_HPP_
|
||||
|
||||
#include "base_scene.hpp"
|
||||
|
||||
#include "image.hpp"
|
||||
#include "raster_font.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
#include "lua/lua.hpp"
|
||||
|
||||
class MainMenu : public BaseScene {
|
||||
public:
|
||||
//Public access members
|
||||
MainMenu(lua_State* L);
|
||||
~MainMenu();
|
||||
|
||||
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&);
|
||||
|
||||
//shared parameters
|
||||
lua_State* lua = nullptr;
|
||||
|
||||
//members
|
||||
Image image;
|
||||
RasterFont font;
|
||||
Button startButton;
|
||||
Button optionsButton;
|
||||
Button quitButton;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
#config
|
||||
INCLUDES+=. debugging graphics map ui utilities
|
||||
LIBS+=libcommon.a -lmingw32 -lSDLmain -lSDL -llua
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o))
|
||||
|
||||
#output
|
||||
OUTDIR=../out
|
||||
OUT=$(addprefix $(OUTDIR)/,jam)
|
||||
|
||||
#targets
|
||||
all: $(OBJ) $(OUT)
|
||||
$(MAKE) -C debugging
|
||||
$(MAKE) -C graphics
|
||||
$(MAKE) -C map
|
||||
$(MAKE) -C ui
|
||||
$(MAKE) -C utilities
|
||||
$(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS)
|
||||
|
||||
$(OBJ): | $(OBJDIR)
|
||||
|
||||
$(OUT): | $(OUTDIR)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(OUTDIR):
|
||||
mkdir $(OUTDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -1,37 +0,0 @@
|
||||
#config
|
||||
INCLUDES+=. ../graphics ../utilities
|
||||
LIBS+=
|
||||
CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES))
|
||||
|
||||
#source
|
||||
CXXSRC=$(wildcard *.cpp)
|
||||
|
||||
#objects
|
||||
OBJDIR=obj
|
||||
OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.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 $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.a *.exe
|
||||
|
||||
rebuild: clean all
|
||||
@@ -1,55 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
Region::Region(int argX, int argY): x(argX), y(argY) {
|
||||
if (x != snapToBase(REGION_WIDTH, x) || y != snapToBase(REGION_HEIGHT, y)) {
|
||||
throw(std::invalid_argument("Region location is off grid"));
|
||||
}
|
||||
memset(tiles, 0, REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH*sizeof(type_t));
|
||||
}
|
||||
|
||||
Region::Region(Region const& rhs): x(rhs.x), y(rhs.y) {
|
||||
memcpy(tiles, rhs.tiles, REGION_WIDTH*REGION_HEIGHT*REGION_DEPTH*sizeof(type_t));
|
||||
solid = rhs.solid;
|
||||
}
|
||||
|
||||
Region::type_t Region::SetTile(int x, int y, int z, type_t v) {
|
||||
return tiles[x][y][z] = v;
|
||||
}
|
||||
|
||||
Region::type_t Region::GetTile(int x, int y, int z) {
|
||||
return tiles[x][y][z];
|
||||
}
|
||||
|
||||
bool Region::SetSolid(int x, int y, bool b) {
|
||||
return solid[x * REGION_WIDTH + y] = b;
|
||||
}
|
||||
|
||||
bool Region::GetSolid(int x, int y) {
|
||||
return solid[x * REGION_WIDTH + y];
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#ifndef REGION_HPP_
|
||||
#define REGION_HPP_
|
||||
|
||||
#include <bitset>
|
||||
#include <cmath>
|
||||
|
||||
//the region's storage format
|
||||
constexpr int REGION_WIDTH = 20;
|
||||
constexpr int REGION_HEIGHT = 20;
|
||||
constexpr int REGION_DEPTH = 3;
|
||||
|
||||
//the size of the solid map
|
||||
constexpr int REGION_SOLID_FOOTPRINT = ceil(REGION_WIDTH * REGION_HEIGHT / 8.0);
|
||||
|
||||
class Region {
|
||||
public:
|
||||
typedef unsigned char type_t;
|
||||
|
||||
Region() = delete;
|
||||
Region(int x, int y);
|
||||
Region(Region const&);
|
||||
~Region() = default;
|
||||
|
||||
type_t SetTile(int x, int y, int z, type_t v);
|
||||
type_t GetTile(int x, int y, int z);
|
||||
|
||||
bool SetSolid(int x, int y, bool b);
|
||||
bool GetSolid(int x, int y);
|
||||
|
||||
//accessors
|
||||
int GetX() const { return x; }
|
||||
int GetY() const { return y; }
|
||||
|
||||
std::bitset<REGION_WIDTH*REGION_HEIGHT>* GetSolidBitset() { return &solid; }
|
||||
private:
|
||||
const int x;
|
||||
const int y;
|
||||
|
||||
type_t tiles[REGION_WIDTH][REGION_HEIGHT][REGION_DEPTH];
|
||||
std::bitset<REGION_WIDTH*REGION_HEIGHT> solid;
|
||||
};
|
||||
|
||||
//the memory footprint of the tile and solid data; not including any metadata
|
||||
constexpr int REGION_FOOTPRINT = REGION_WIDTH * REGION_HEIGHT * REGION_DEPTH * sizeof(Region::type_t) + REGION_SOLID_FOOTPRINT;
|
||||
|
||||
#endif
|
||||
@@ -1,122 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region_api.hpp"
|
||||
|
||||
#include "region.hpp"
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
int ret = region->SetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1, lua_tointeger(L, 5));
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getTile(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
int ret = region->GetTile(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_tointeger(L, 4)-1);
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setSolid(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
bool ret = region->SetSolid(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1, lua_toboolean(L, 4));
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getSolid(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
bool ret = region->GetSolid(lua_tointeger(L, 2)-1, lua_tointeger(L, 3)-1);
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getX(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, region->GetX());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getY(lua_State* L) {
|
||||
Region* region = reinterpret_cast<Region*>(lua_touserdata(L, 1));
|
||||
lua_pushinteger(L, region->GetY());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getWidth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_WIDTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getHeight(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_HEIGHT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getDepth(lua_State* L) {
|
||||
lua_pushinteger(L, REGION_DEPTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int load(lua_State* L) {
|
||||
//EMPTY
|
||||
lua_pushboolean(L, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int save(lua_State* L) {
|
||||
//EMPTY
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create(lua_State* L) {
|
||||
//EMPTY
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload(lua_State* L) {
|
||||
//EMPTY
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg regionLib[] = {
|
||||
{"SetTile",setTile},
|
||||
{"GetTile",getTile},
|
||||
{"SetSolid",setSolid},
|
||||
{"GetSolid",getSolid},
|
||||
{"GetX",getX},
|
||||
{"GetY",getY},
|
||||
{"GetWidth",getWidth},
|
||||
{"GetHeight",getHeight},
|
||||
{"GetDepth",getDepth},
|
||||
{"Load",load},
|
||||
{"Save",save},
|
||||
{"Create",create},
|
||||
{"Unload",unload},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openRegionAPI(lua_State* L) {
|
||||
luaL_newlib(L, regionLib);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/* Copyright: (c) Kayne Ruse 2014
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
#include "region_pager_api.hpp"
|
||||
|
||||
#include "region_pager_lua.hpp"
|
||||
#include "region.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
static int getRegionPager(lua_State* L) {
|
||||
lua_pushstring(L, TORTUGA_REGION_PAGER_PSEUDO_INDEX);
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
//DOCS: These glue functions simply wrap RegionPagerLua's methods
|
||||
|
||||
static int setTile(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
int ret = pager->SetTile(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4), lua_tointeger(L, 5));
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getTile(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
int ret = pager->GetTile(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_tointeger(L, 4));
|
||||
lua_pushinteger(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setSolid(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
bool ret = pager->SetSolid(lua_tointeger(L, 2), lua_tointeger(L, 3), lua_toboolean(L, 4));
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getSolid(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
bool ret = pager->GetSolid(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushboolean(L, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->GetRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int loadRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->LoadRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int saveRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->SaveRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int createRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
Region* region = pager->CreateRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
lua_pushlightuserdata(L, region);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int unloadRegion(lua_State* L) {
|
||||
RegionPagerLua* pager = reinterpret_cast<RegionPagerLua*>(lua_touserdata(L, 1));
|
||||
pager->UnloadRegion(lua_tointeger(L, 2), lua_tointeger(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg regionPagerLib[] = {
|
||||
{"GetRegionPager", getRegionPager},
|
||||
{"SetTile", setTile},
|
||||
{"GetTile", getTile},
|
||||
{"SetSolid", setSolid},
|
||||
{"GetSolid", getSolid},
|
||||
{"GetRegion", getRegion},
|
||||
{"LoadRegion", loadRegion},
|
||||
{"SaveRegion", saveRegion},
|
||||
{"CreateRegion", createRegion},
|
||||
{"UnloadRegion", unloadRegion},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
LUAMOD_API int openRegionPagerAPI(lua_State* L) {
|
||||
luaL_newlib(L, regionPagerLib);
|
||||
return 1;
|
||||
}
|
||||