commit 56ae0a13c9d1af56d293c2669d946cbe5c0941e7 Author: Kayne Ruse Date: Tue Jul 7 23:47:51 2015 +1000 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..497ac38 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +#Editor generated files +*.sln +*.vcproj +*.suo +*.ncb +*.user + +#Directories +Release/ +Debug/ +Out/ +release/ +debug/ +out/ + +#Project generated files +*.db +*.o +*.a +*.exe + +#Shell files +*.bat +*.sh diff --git a/application.cpp b/application.cpp new file mode 100644 index 0000000..4f5ac88 --- /dev/null +++ b/application.cpp @@ -0,0 +1,141 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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 +#include +#include + +void Application::Init(int argc, char* argv[]) { + //create and check the window + window = SDL_CreateWindow( + "Example Caption", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + screenWidth, + screenHeight, + SDL_WINDOW_RESIZABLE); + + if (!window) { + std::ostringstream msg; + msg << "Failed to create the window: " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + + //create and check the renderer + renderer = SDL_CreateRenderer(window, -1, 0); + + if (!renderer) { + std::ostringstream msg; + msg << "Failed to create the renderer: " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + + //screen scaling + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); + SDL_RenderSetLogicalSize(renderer, 800, 600); + + //set the hook for the renderer + BaseScene::SetRenderer(renderer); +} + +void Application::Proc() { + //load the first scene + ProcessSceneSignal(SceneSignal::FIRST); + + //fixed frame rate + typedef std::chrono::steady_clock Clock; + + Clock::time_point simTime = Clock::now(); + Clock::time_point realTime; + constexpr std::chrono::duration frameDelay(16); //~60FPS + + //the game loop continues until the scenes signal QUIT + while(activeScene->GetSceneSignal() != SceneSignal::QUIT) { + //switch scenes if necessary + if(activeScene->GetSceneSignal() != SceneSignal::CONTINUE) { + ProcessSceneSignal(activeScene->GetSceneSignal()); + continue; + } + + //update the current time + realTime = Clock::now(); + + //simulate the game or give the machine a break + if (simTime < realTime) { + while(simTime < realTime) { + //call the user defined functions + activeScene->RunFrame(); + //step to the next frame + simTime += frameDelay; + } + } + else { + SDL_Delay(1); + } + + SDL_RenderClear(renderer); + activeScene->RenderFrame(renderer); + SDL_RenderPresent(renderer); + } + + //cleanup + ClearScene(); +} + +void Application::Quit() { + //cleran up after the program + BaseScene::SetRenderer(nullptr); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + + //TODO: is this necessary? +// SDL_Quit(); +} + +//------------------------- +//Scene management +//------------------------- + +//Add the custom scene headers here +#include "example_scene.hpp" + +void Application::ProcessSceneSignal(SceneSignal signal) { + ClearScene(); + + switch(signal) { + case SceneSignal::FIRST: + case SceneSignal::EXAMPLE_SCENE: + activeScene = new ExampleScene(); + break; + default: { + std::ostringstream msg; + msg << "Failed to recognize the scene signal: " << signal; + throw(std::logic_error(msg.str())); + } + } +} + +void Application::ClearScene() { + delete activeScene; + activeScene = nullptr; +} \ No newline at end of file diff --git a/application.hpp b/application.hpp new file mode 100644 index 0000000..8a7f487 --- /dev/null +++ b/application.hpp @@ -0,0 +1,53 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +#include "base_scene.hpp" +#include "scene_signal.hpp" + +#include "SDL2/SDL.h" + +//TODO: do something with these +constexpr int screenWidth = 800; +constexpr int screenHeight = 600; + +//DOCS: The Application class handles scene switching, utilizing only one window +class Application { +public: + Application() = default; + ~Application() = default; + + void Init(int argc, char* argv[]); + void Proc(); + void Quit(); + +private: + //scene management + void ProcessSceneSignal(SceneSignal); + void ClearScene(); + + BaseScene* activeScene = nullptr; + + //TODO: build a "window" class? + SDL_Window* window = nullptr; + SDL_Renderer* renderer = nullptr; +}; \ No newline at end of file diff --git a/base_scene.cpp b/base_scene.cpp new file mode 100644 index 0000000..128070f --- /dev/null +++ b/base_scene.cpp @@ -0,0 +1,145 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "base_scene.hpp" + +SDL_Renderer* BaseScene::rendererHandle = nullptr; + +BaseScene::BaseScene() { + //EMPTY +} + +BaseScene::~BaseScene() { + //EMPTY +} + +void BaseScene::RunFrame() { + FrameStart(); + ProcessEvents(); + Update(); + FrameEnd(); +} + +void BaseScene::RenderFrame(SDL_Renderer* renderer) { + //EMPTY +} + +void BaseScene::SetRenderer(SDL_Renderer* r) { + rendererHandle = r; +} + +SDL_Renderer* BaseScene::GetRenderer() { + return rendererHandle; +} + +void BaseScene::SetSceneSignal(SceneSignal signal) { + sceneSignal = signal; +} + +SceneSignal BaseScene::GetSceneSignal() { + return sceneSignal; +} + +//------------------------- +//frame phases +//------------------------- + +void BaseScene::FrameStart() { + //EMPTY +} + +void BaseScene::ProcessEvents() { + SDL_Event event; + while(SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_QUIT: + QuitEvent(); + break; + + case SDL_MOUSEMOTION: + MouseMotion(event.motion); + break; + + case SDL_MOUSEBUTTONDOWN: + MouseButtonDown(event.button); + break; + + case SDL_MOUSEBUTTONUP: + MouseButtonUp(event.button); + break; + + case SDL_KEYDOWN: + KeyDown(event.key); + break; + + case SDL_KEYUP: + KeyUp(event.key); + break; + + //TODO: joystick and controller events + } + } +} + +void BaseScene::Update() { + //EMPTY +} + +void BaseScene::FrameEnd() { + //EMPTY +} + +//------------------------- +//input events +//------------------------- + +void BaseScene::QuitEvent() { + sceneSignal = SceneSignal::QUIT; +} + +void BaseScene::MouseMotion(SDL_MouseMotionEvent const& event) { + //EMPTY +} + +void BaseScene::MouseButtonDown(SDL_MouseButtonEvent const& event) { + //EMPTY +} + +void BaseScene::MouseButtonUp(SDL_MouseButtonEvent const& event) { + //EMPTY +} + +void BaseScene::MouseWheel(SDL_MouseWheelEvent const& event) { + //EMPTY +} + +void BaseScene::KeyDown(SDL_KeyboardEvent const& event) { + //preference as a default + switch(event.keysym.sym) { + case SDLK_ESCAPE: + QuitEvent(); + break; + } +} + +void BaseScene::KeyUp(SDL_KeyboardEvent const& event) { + //EMPTY +} diff --git a/base_scene.hpp b/base_scene.hpp new file mode 100644 index 0000000..bc8ed63 --- /dev/null +++ b/base_scene.hpp @@ -0,0 +1,64 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +#include "scene_signal.hpp" + +#include "SDL2/SDL.h" + +class BaseScene { +public: + BaseScene(); + virtual ~BaseScene(); + + virtual void RunFrame(); + virtual void RenderFrame(SDL_Renderer*); + + static void SetRenderer(SDL_Renderer*); + SceneSignal GetSceneSignal(); + +protected: + //control + static SDL_Renderer* GetRenderer(); + void SetSceneSignal(SceneSignal); + + //frame phases + virtual void FrameStart(); + virtual void ProcessEvents(); + virtual void Update(); + virtual void FrameEnd(); + + //input events + virtual void QuitEvent(); + virtual void MouseMotion(SDL_MouseMotionEvent const& event); + virtual void MouseButtonDown(SDL_MouseButtonEvent const& event); + virtual void MouseButtonUp(SDL_MouseButtonEvent const& event); + virtual void MouseWheel(SDL_MouseWheelEvent const& event); + virtual void KeyDown(SDL_KeyboardEvent const& event); + virtual void KeyUp(SDL_KeyboardEvent const& event); + + //TODO: joystick and controller events + +private: + static SDL_Renderer* rendererHandle; + SceneSignal sceneSignal = SceneSignal::CONTINUE; +}; \ No newline at end of file diff --git a/common/image.cpp b/common/image.cpp new file mode 100644 index 0000000..bd9e662 --- /dev/null +++ b/common/image.cpp @@ -0,0 +1,184 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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 "SDL2/SDL_image.h" + +#include +#include + +Image& Image::operator=(Image const& rhs) { + //don't screw yourself + if (this == &rhs) { + return *this; + } + + Free(); + + //Copy the other Image's stuff + texture = rhs.texture; + clip = rhs.clip; + local = false; +} + +Image& Image::operator=(Image&& rhs) { + //don't screw yourself + if (this == &rhs) { + return *this; + } + + Free(); + + //Steal the other Image's stuff + texture = rhs.texture; + clip = rhs.clip; + local = rhs.local; + + rhs.texture = nullptr; + rhs.clip = {0, 0, 0, 0}; + rhs.local = false; +} + +SDL_Texture* Image::Load(SDL_Renderer* renderer, std::string fname) { + Free(); + + //load the file into a surface + SDL_Surface* surface = IMG_Load(fname.c_str()); + if (!surface) { + std::ostringstream msg; + msg << "Failed to load an image file: " << fname; + msg << "; " << IMG_GetError(); + throw(std::runtime_error(msg.str())); + } + + //create a texture from this surface + texture = SDL_CreateTextureFromSurface(renderer, surface); + if (!texture) { + std::ostringstream msg; + msg << "Failed to convert a newly loaded image file: " << fname; + msg << "; " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + + //set the metadata + clip.x = 0; + clip.y = 0; + if (SDL_QueryTexture(texture, nullptr, nullptr, &clip.w, &clip.h)) { + std::ostringstream msg; + msg << "Failed to record metadata for a newly loaded image file: " << fname; + msg << "; " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + local = true; + + //free the surface & return + SDL_FreeSurface(surface); + return texture; +} + +SDL_Texture* Image::Create(SDL_Renderer* renderer, Uint16 w, Uint16 h) { + Free(); + + //make the texture + texture = SDL_CreateTexture(renderer, + SDL_PIXELFORMAT_RGBA8888, + SDL_TEXTUREACCESS_STATIC, + w, h); + + if (!texture) { + std::ostringstream msg; + msg << "Failed to create a texture; " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + + //set the metadata + clip.x = 0; + clip.y = 0; + if (SDL_QueryTexture(texture, nullptr, nullptr, &clip.w, &clip.h)) { + std::ostringstream msg; + msg << "Failed to record metadata for a newly created image"; + msg << "; " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + local = true; + + return texture; +} + +SDL_Texture* Image::SetTexture(SDL_Texture* ptr) { + Free(); + + texture = ptr; + + //set the metadata + clip.x = 0; + clip.y = 0; + if (SDL_QueryTexture(texture, nullptr, nullptr, &clip.w, &clip.h)) { + std::ostringstream msg; + msg << "Failed to record metadata for a newly image image"; + msg << "; " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + local = false; + + return texture; +} + +SDL_Texture* Image::GetTexture() const { + return texture; +} + +void Image::Free() { + if (local) { + SDL_DestroyTexture(texture); + local = false; + } + texture = nullptr; + clip = {0, 0, 0, 0}; +} + +void Image::DrawTo(SDL_Renderer* const renderer, Sint16 x, Sint16 y, double scaleX, double scaleY) { + if (!texture) { + throw(std::logic_error("No image texture to draw")); + } + SDL_Rect sclip = clip; + SDL_Rect dclip = {x, y, Uint16(clip.w * scaleX), Uint16(clip.h * scaleY)}; + SDL_RenderCopy(renderer, texture, &sclip, &dclip); +} + +void Image::SetAlpha(Uint8 a) { + if (SDL_SetTextureAlphaMod(texture, a)) { + std::ostringstream msg; + msg << "Failed to set alpha; " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } +} + +Uint8 Image::GetAlpha() { + Uint8 ret = 0; + if (SDL_GetTextureAlphaMod(texture, &ret)) { + std::ostringstream msg; + msg << "Failed to get alpha; " << SDL_GetError(); + throw(std::runtime_error(msg.str())); + } + return ret; +} \ No newline at end of file diff --git a/common/image.hpp b/common/image.hpp new file mode 100644 index 0000000..f6685e4 --- /dev/null +++ b/common/image.hpp @@ -0,0 +1,72 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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. +*/ +#pragma once + +#include "SDL2/SDL.h" + +#include + +class Image { +public: + Image() = default; + Image(Image const& rhs) { *this = rhs; } + Image(Image&& rhs) { *this = std::move(rhs); } + Image(SDL_Renderer* r, std::string fname) { Load(r, fname); } + Image(SDL_Renderer* r, Uint16 w, Uint16 h) { Create(r, w, h); } + Image(SDL_Texture* p) { SetTexture(p); } + virtual ~Image() { Free(); } + + Image& operator=(Image const&); + Image& operator=(Image&&); + + SDL_Texture* Load(SDL_Renderer* renderer, std::string fname); + SDL_Texture* Create(SDL_Renderer* renderer, Uint16 w, Uint16 h); + SDL_Texture* SetTexture(SDL_Texture*); + SDL_Texture* GetTexture() const; + virtual void Free(); + + void DrawTo(SDL_Renderer* const, Sint16 x, Sint16 y, double scaleX = 1.0, double scaleY = 1.0); + + void SetAlpha(Uint8 a); + Uint8 GetAlpha(); + + //Clip handlers + SDL_Rect SetClip(SDL_Rect r) { return clip = r; } + SDL_Rect GetClip() const { return clip; } + + Sint16 SetClipX(Sint16 x) { return clip.x = x; } + Sint16 SetClipY(Sint16 y) { return clip.y = y; } + Uint16 SetClipW(Uint16 w) { return clip.w = w; } + Uint16 SetClipH(Uint16 h) { return clip.h = h; } + + Sint16 GetClipX() const { return clip.x; } + Sint16 GetClipY() const { return clip.y; } + Uint16 GetClipW() const { return clip.w; } + Uint16 GetClipH() const { return clip.h; } + + bool GetLocal() const { return local; } + +protected: + SDL_Texture* texture = nullptr; + SDL_Rect clip = {0, 0, 0, 0}; + bool local = false; +}; \ No newline at end of file diff --git a/common/makefile b/common/makefile new file mode 100644 index 0000000..2b33c56 --- /dev/null +++ b/common/makefile @@ -0,0 +1,32 @@ +#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 $@ $< diff --git a/example_scene.cpp b/example_scene.cpp new file mode 100644 index 0000000..33be9ab --- /dev/null +++ b/example_scene.cpp @@ -0,0 +1,83 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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 "example_scene.hpp" + +ExampleScene::ExampleScene() { + // +} + +ExampleScene::~ExampleScene() { + // +} + +//------------------------- +//frame phases +//------------------------- + +void ExampleScene::FrameStart() { + // +} + +void ExampleScene::Update() { + // +} + +void ExampleScene::FrameEnd() { + // +} + +void ExampleScene::RenderFrame(SDL_Renderer* renderer) { + // +} + +//------------------------- +//input events +//------------------------- + +void ExampleScene::MouseMotion(SDL_MouseMotionEvent const& event) { + // +} + +void ExampleScene::MouseButtonDown(SDL_MouseButtonEvent const& event) { + // +} + +void ExampleScene::MouseButtonUp(SDL_MouseButtonEvent const& event) { + // +} + +void ExampleScene::MouseWheel(SDL_MouseWheelEvent const& event) { + // +} + +void ExampleScene::KeyDown(SDL_KeyboardEvent const& event) { + //preference as a default + switch(event.keysym.sym) { + case SDLK_ESCAPE: + QuitEvent(); + break; + } +} + +void ExampleScene::KeyUp(SDL_KeyboardEvent const& event) { + // +} diff --git a/example_scene.hpp b/example_scene.hpp new file mode 100644 index 0000000..2f18af1 --- /dev/null +++ b/example_scene.hpp @@ -0,0 +1,46 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +#include "base_scene.hpp" + +class ExampleScene : public BaseScene { +public: + ExampleScene(); + ~ExampleScene(); + + void RenderFrame(SDL_Renderer* renderer) override; + +private: + //frame phases + void FrameStart() override; + void Update() override; + void FrameEnd() override; + + //input events + void MouseMotion(SDL_MouseMotionEvent const& event) override; + void MouseButtonDown(SDL_MouseButtonEvent const& event) override; + void MouseButtonUp(SDL_MouseButtonEvent const& event) override; + void MouseWheel(SDL_MouseWheelEvent const& event) override; + void KeyDown(SDL_KeyboardEvent const& event) override; + void KeyUp(SDL_KeyboardEvent const& event) override; +}; diff --git a/libmap/makefile b/libmap/makefile new file mode 100644 index 0000000..d52def2 --- /dev/null +++ b/libmap/makefile @@ -0,0 +1,32 @@ +#config +INCLUDES+=. ../common +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)/,libmap.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 $@ $< diff --git a/libmap/region.cpp b/libmap/region.cpp new file mode 100644 index 0000000..1815d36 --- /dev/null +++ b/libmap/region.cpp @@ -0,0 +1,82 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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 +#include +#include + +int snapToBase(int base, int x) { + return floor((double)x / base) * base; +} + +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) { + if (x < 0 || y < 0 || z < 0 || x >= REGION_WIDTH || y >= REGION_HEIGHT || z >= REGION_DEPTH) { + throw(std::out_of_range("Region::SetTile() argument out of range")); + } + return tiles[x][y][z] = v; +} + +Region::type_t Region::GetTile(int x, int y, int z) { + if (x < 0 || y < 0 || z < 0 || x >= REGION_WIDTH || y >= REGION_HEIGHT || z >= REGION_DEPTH) { + throw(std::out_of_range("Region::GetTile() argument out of range")); + } + return tiles[x][y][z]; +} + +bool Region::SetSolid(int x, int y, bool b) { + if (x < 0 || y < 0 || x >= REGION_WIDTH || y >= REGION_HEIGHT) { + throw(std::out_of_range("Region::SetSolid() argument out of range")); + } + return solid[x * REGION_WIDTH + y] = b; +} + +bool Region::GetSolid(int x, int y) { + if (x < 0 || y < 0 || x >= REGION_WIDTH || y >= REGION_HEIGHT) { + throw(std::out_of_range("Region::GetSolid() argument out of range")); + } + return solid[x * REGION_WIDTH + y]; +} + +int Region::GetX() const { + return x; +} + +int Region::GetY() const { + return y; +} + +std::bitset* Region::GetSolidBitset() { + return &solid; +} \ No newline at end of file diff --git a/libmap/region.hpp b/libmap/region.hpp new file mode 100644 index 0000000..68511be --- /dev/null +++ b/libmap/region.hpp @@ -0,0 +1,60 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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. +*/ +#pragma once + +#include + +//the region's storage format +constexpr int REGION_WIDTH = 20; +constexpr int REGION_HEIGHT = 20; +constexpr int REGION_DEPTH = 3; + +//utility function +int snapToBase(int base, int x); + +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; + int GetY() const; + + std::bitset* GetSolidBitset(); +private: + const int x; + const int y; + + type_t tiles[REGION_WIDTH][REGION_HEIGHT][REGION_DEPTH]; + std::bitset solid; +}; diff --git a/libmap/region_api.cpp b/libmap/region_api.cpp new file mode 100644 index 0000000..1c0f848 --- /dev/null +++ b/libmap/region_api.cpp @@ -0,0 +1,99 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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(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(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(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(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(lua_touserdata(L, 1)); + lua_pushinteger(L, region->GetX()); + return 1; +} + +static int getY(lua_State* L) { + Region* region = reinterpret_cast(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 const luaL_Reg regionLib[] = { + {"SetTile",setTile}, + {"GetTile",getTile}, + {"SetSolid",setSolid}, + {"GetSolid",getSolid}, + {"GetX",getX}, + {"GetY",getY}, + + //the global macros + {"GetWidth",getWidth}, + {"GetHeight",getHeight}, + {"GetDepth",getDepth}, + {nullptr, nullptr} +}; + +LUAMOD_API int openRegionAPI(lua_State* L) { + luaL_newlib(L, regionLib); + return 1; +} \ No newline at end of file diff --git a/libmap/region_api.hpp b/libmap/region_api.hpp new file mode 100644 index 0000000..e855bcb --- /dev/null +++ b/libmap/region_api.hpp @@ -0,0 +1,27 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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. +*/ +#pragma once + +#include "lua.hpp" + +#define TORTUGA_REGION_API "region" +LUAMOD_API int openRegionAPI(lua_State* L); diff --git a/libmap/region_pager_api.cpp b/libmap/region_pager_api.cpp new file mode 100644 index 0000000..fd366db --- /dev/null +++ b/libmap/region_pager_api.cpp @@ -0,0 +1,172 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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" + +//DOCS: These glue functions simply wrap RegionPagerLua's methods +//NOTE: zero indexing is used here, but not in the region API + +static int setTile(lua_State* L) { + RegionPagerLua* pager = reinterpret_cast(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(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(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(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(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(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(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(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(lua_touserdata(L, 1)); + + //two argument types: coords & the region itself + switch(lua_type(L, 2)) { + case LUA_TNUMBER: + pager->UnloadIf([&](Region const& region) -> bool { + int x = lua_tointeger(L, 2); + int y = lua_tointeger(L, 3); + return region.GetX() == x && region.GetY() == y; + }); + break; + case LUA_TLIGHTUSERDATA: + pager->UnloadIf([&](Region const& region) -> bool { + return (®ion) == lua_touserdata(L, 2); + }); + break; + } + return 0; +} + +static int setOnLoad(lua_State* L) { + RegionPagerLua* pager = reinterpret_cast(lua_touserdata(L, 1)); + luaL_unref(L, LUA_REGISTRYINDEX, pager->GetLoadReference()); + pager->SetLoadReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + +static int setOnSave(lua_State* L) { + RegionPagerLua* pager = reinterpret_cast(lua_touserdata(L, 1)); + luaL_unref(L, LUA_REGISTRYINDEX, pager->GetSaveReference()); + pager->SetSaveReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + +static int setOnCreate(lua_State* L) { + RegionPagerLua* pager = reinterpret_cast(lua_touserdata(L, 1)); + luaL_unref(L, LUA_REGISTRYINDEX, pager->GetCreateReference()); + pager->SetCreateReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + +static int setOnUnload(lua_State* L) { + RegionPagerLua* pager = reinterpret_cast(lua_touserdata(L, 1)); + luaL_unref(L, LUA_REGISTRYINDEX, pager->GetUnloadReference()); + pager->SetUnloadReference(luaL_ref(L, LUA_REGISTRYINDEX)); + return 0; +} + +//debugging +static int containerSize(lua_State* L) { + RegionPagerLua* pager = static_cast(lua_touserdata(L, 1)); + lua_pushinteger(L, pager->GetContainer()->size()); + return 1; +} + +static const luaL_Reg regionPagerLib[] = { + //curry + {"SetTile", setTile}, + {"GetTile", getTile}, + {"SetSolid", setSolid}, + {"GetSolid", getSolid}, + + //access and control + {"GetRegion", getRegion}, + {"LoadRegion", loadRegion}, + {"SaveRegion", saveRegion}, + {"CreateRegion", createRegion}, + {"UnloadRegion", unloadRegion}, + + //triggers + {"SetOnLoad",setOnLoad}, + {"SetOnSave",setOnSave}, + {"SetOnCreate",setOnCreate}, + {"SetOnUnload",setOnUnload}, + + //debugging + {"ContainerSize", containerSize}, + + //sentinel + {nullptr, nullptr} +}; + +LUAMOD_API int openRegionPagerAPI(lua_State* L) { + luaL_newlib(L, regionPagerLib); + return 1; +} \ No newline at end of file diff --git a/libmap/region_pager_api.hpp b/libmap/region_pager_api.hpp new file mode 100644 index 0000000..965b400 --- /dev/null +++ b/libmap/region_pager_api.hpp @@ -0,0 +1,27 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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. +*/ +#pragma once + +#include "lua.hpp" + +#define TORTUGA_REGION_PAGER_API "region_pager" +LUAMOD_API int openRegionPagerAPI(lua_State* L); diff --git a/libmap/region_pager_base.cpp b/libmap/region_pager_base.cpp new file mode 100644 index 0000000..857dabd --- /dev/null +++ b/libmap/region_pager_base.cpp @@ -0,0 +1,106 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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_base.hpp" + +#include +#include + +RegionPagerBase::~RegionPagerBase() { + UnloadAll(); +}; + +Region::type_t RegionPagerBase::SetTile(int x, int y, int z, Region::type_t v) { + Region* ptr = GetRegion(x, y); + return ptr->SetTile(x - ptr->GetX(), y - ptr->GetY(), z, v); +} + +Region::type_t RegionPagerBase::GetTile(int x, int y, int z) { + Region* ptr = GetRegion(x, y); + return ptr->GetTile(x - ptr->GetX(), y - ptr->GetY(), z); +} + +bool RegionPagerBase::SetSolid(int x, int y, int b) { + Region* ptr = GetRegion(x, y); + return ptr->SetSolid(x - ptr->GetX(), y - ptr->GetY(), b); +} + +bool RegionPagerBase::GetSolid(int x, int y) { + Region* ptr = GetRegion(x, y); + return ptr->GetSolid(x - ptr->GetX(), y - ptr->GetY()); +} + +Region* RegionPagerBase::GetRegion(int x, int y) { + x = snapToBase(REGION_WIDTH, x); + y = snapToBase(REGION_HEIGHT, y); + + //get the region by various means + Region* ptr = nullptr; + ptr = FindRegion(x, y); + if (ptr) return ptr; + ptr = LoadRegion(x, y); + if (ptr) return ptr; + return CreateRegion(x, y); +} + +Region* RegionPagerBase::FindRegion(int x, int y) { + //find the region + std::list::iterator it = find_if(regionList.begin(), regionList.end(), [x, y](Region& region) -> bool { + return region.GetX() == x && region.GetY() == y; + }); + return it != regionList.end() ? &(*it) : nullptr; +} + +Region* RegionPagerBase::PushRegion(Region* const ptr) { + //BUG: #45 Some regions are occasionally losing their tile data + regionList.push_front(*ptr); + return ®ionList.front(); +} + +Region* RegionPagerBase::LoadRegion(int x, int y) { + //EMPTY, intended for override + return nullptr; +} + +Region* RegionPagerBase::SaveRegion(int x, int y) { + //EMPTY, intended for override + return nullptr; +} + +Region* RegionPagerBase::CreateRegion(int x, int y) { + if (FindRegion(x, y)) { + throw(std::logic_error("Cannot overwrite an existing region")); + } + regionList.emplace_front(x, y); + return ®ionList.front(); +} + +void RegionPagerBase::UnloadIf(std::function fn) { + regionList.remove_if(fn); +} + +void RegionPagerBase::UnloadAll() { + regionList.clear(); +} + +std::list* RegionPagerBase::GetContainer() { + return ®ionList; +} \ No newline at end of file diff --git a/libmap/region_pager_base.hpp b/libmap/region_pager_base.hpp new file mode 100644 index 0000000..a53083d --- /dev/null +++ b/libmap/region_pager_base.hpp @@ -0,0 +1,58 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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. +*/ +#pragma once + +#include "region.hpp" + +#include +#include + +class RegionPagerBase { +public: + RegionPagerBase() = default; + virtual ~RegionPagerBase(); + + //tile manipulation + virtual Region::type_t SetTile(int x, int y, int z, Region::type_t v); + virtual Region::type_t GetTile(int x, int y, int z); + + //solid manipulation + virtual bool SetSolid(int x, int y, int b); + virtual bool GetSolid(int x, int y); + + //region manipulation + virtual Region* GetRegion(int x, int y); + virtual Region* FindRegion(int x, int y); + virtual Region* PushRegion(Region* const); + + virtual Region* LoadRegion(int x, int y); + virtual Region* SaveRegion(int x, int y); + virtual Region* CreateRegion(int x, int y); + + virtual void UnloadIf(std::function fn); + virtual void UnloadAll(); + + //accessors & mutators + std::list* GetContainer(); +protected: + std::list regionList; +}; diff --git a/libmap/region_pager_lua.cpp b/libmap/region_pager_lua.cpp new file mode 100644 index 0000000..4e0a973 --- /dev/null +++ b/libmap/region_pager_lua.cpp @@ -0,0 +1,200 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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_lua.hpp" + +#include + +//DOCS: Load, Save and Create fail unless the lua function has been set +//DOCS: UnloadIf and UnloadAll will still continue without the function set + +RegionPagerLua::~RegionPagerLua() { + //unload all regions + UnloadAll(); + //clear any stored functions + luaL_unref(lua, LUA_REGISTRYINDEX, loadRef); + luaL_unref(lua, LUA_REGISTRYINDEX, saveRef); + luaL_unref(lua, LUA_REGISTRYINDEX, createRef); + luaL_unref(lua, LUA_REGISTRYINDEX, unloadRef); +} + +//return the loaded region, or nullptr on failure +Region* RegionPagerLua::LoadRegion(int x, int y) { + //get the pager's function from the registry + lua_rawgeti(lua, LUA_REGISTRYINDEX, loadRef); + + //check if this function is available + if (lua_isnil(lua, -1)) { + lua_pop(lua, 1); + return nullptr; + } + + //something to work on + Region tmpRegion(x, y); + lua_pushlightuserdata(lua, &tmpRegion); + + //call the funtion, 1 arg, 1 return + if (lua_pcall(lua, 1, 1, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + + //check the return value, success or failure + if (lua_toboolean(lua, -1)) { + lua_pop(lua, 1); + regionList.push_front(tmpRegion); + return ®ionList.front(); + } + else { + lua_pop(lua, 1); + return nullptr; + } +} + +//return the saved region, or nullptr on failure +Region* RegionPagerLua::SaveRegion(int x, int y) { + //get the pager's function from the registry + lua_rawgeti(lua, LUA_REGISTRYINDEX, saveRef); + + //check if this function is available + if (lua_isnil(lua, -1)) { + lua_pop(lua, 1); + return nullptr; + } + + //find the specified region + Region* ptr = FindRegion(x, y); + if (!ptr) { + lua_pop(lua, 1); + return nullptr; + } + lua_pushlightuserdata(lua, ptr); + + //call the function, 1 arg, 1 return + if (lua_pcall(lua, 1, 1, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + + //check the return value, success or failure + if (lua_toboolean(lua, -1)) { + lua_pop(lua, 1); + return ptr; + } + else { + lua_pop(lua, 1); + return nullptr; + } +} + +//return the created region, or nullptr on failure +Region* RegionPagerLua::CreateRegion(int x, int y) { + if (FindRegion(x, y)) { + throw(std::logic_error("Cannot overwrite an existing region")); + } + + //get the pager's function from the registry + lua_rawgeti(lua, LUA_REGISTRYINDEX, createRef); + + //check if this function is available + if (lua_isnil(lua, -1)) { + lua_pop(lua, 1); + return nullptr; + } + + //something to work on + Region tmpRegion(x, y); + lua_pushlightuserdata(lua, &tmpRegion); + + //call the function, 1 arg, 0 return + if (lua_pcall(lua, 1, 0, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + + //return the new region + regionList.push_front(tmpRegion); + return ®ionList.front(); +} + +//no return +void RegionPagerLua::UnloadIf(std::function fn) { + //get the pager's function from the registry + lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef); + + //check if this function is available + if (lua_isnil(lua, -1)) { + lua_pop(lua, 1); + //remove the regions anyway + regionList.remove_if(fn); + return; + } + + //run each region through this lambda + regionList.remove_if([&](Region& region) -> bool { + if (fn(region)) { + + //push a copy of the function onto the stack with the region + lua_pushvalue(lua, -1); + lua_pushlightuserdata(lua, static_cast(®ion)); + + //call the function, 1 arg, 0 return + if (lua_pcall(lua, 1, 0, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + + //signal to the container + return true; + } + //signal to the container + return false; + }); + + //pop the base copy of the function + lua_pop(lua, 1); +} + +void RegionPagerLua::UnloadAll() { + //get the pager's function from the registry + lua_rawgeti(lua, LUA_REGISTRYINDEX, unloadRef); + + //check if this function is available + if (lua_isnil(lua, -1)) { + lua_pop(lua, 1); + //remove the regions anyway + regionList.clear(); + return; + } + + for (auto& it : regionList) { + //push a copy of the function onto the stack with the region + lua_pushvalue(lua, -1); + lua_pushlightuserdata(lua, &it); + + //call the function, 1 arg, 0 return + if (lua_pcall(lua, 1, 0, 0) != LUA_OK) { + throw(std::runtime_error(std::string() + "Lua error: " + lua_tostring(lua, -1) )); + } + } + + //pop the base copy of the function + lua_pop(lua, 1); + + //remove from memory + regionList.clear(); +} \ No newline at end of file diff --git a/libmap/region_pager_lua.hpp b/libmap/region_pager_lua.hpp new file mode 100644 index 0000000..0b64b0a --- /dev/null +++ b/libmap/region_pager_lua.hpp @@ -0,0 +1,66 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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. +*/ +#pragma once + +#include "region_pager_base.hpp" + +#include "lua.hpp" + +#include +#include + +class RegionPagerLua : public RegionPagerBase { +public: + RegionPagerLua() = default; + ~RegionPagerLua(); + + //region manipulation + Region* LoadRegion(int x, int y) override; + Region* SaveRegion(int x, int y) override; + Region* CreateRegion(int x, int y) override; + + void UnloadIf(std::function fn) override; + void UnloadAll() override; + + //accessors & mutators + lua_State* SetLuaState(lua_State* L) { return lua = L; } + lua_State* GetLuaState() { return lua; } + + //utilities for the API + int SetLoadReference(int i) { return loadRef = i; } + int SetSaveReference(int i) { return saveRef = i; } + int SetCreateReference(int i) { return createRef = i; } + int SetUnloadReference(int i) { return unloadRef = i; } + + int GetLoadReference() { return loadRef; } + int GetSaveReference() { return saveRef; } + int GetCreateReference() { return createRef; } + int GetUnloadReference() { return unloadRef; } + +protected: + lua_State* lua = nullptr; + + int loadRef = LUA_NOREF; + int saveRef = LUA_NOREF; + int createRef = LUA_NOREF; + int unloadRef = LUA_NOREF; +}; diff --git a/libmap/tile_sheet.cpp b/libmap/tile_sheet.cpp new file mode 100644 index 0000000..137b77a --- /dev/null +++ b/libmap/tile_sheet.cpp @@ -0,0 +1,106 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. +*/ +#include "tile_sheet.hpp" + +TileSheet& TileSheet::operator=(TileSheet const& rhs) { + //don't screw yourself + if (this == &rhs) { + return *this; + } + + Free(); + + //Copy the other TileSheet's stuff + texture = rhs.texture; + clip = rhs.clip; + local = false; + countX = rhs.countX; + countY = rhs.countY; +} + +TileSheet& TileSheet::operator=(TileSheet&& rhs) { + //don't screw yourself + if (this == &rhs) { + return *this; + } + + Free(); + + //Copy the other TileSheet's stuff + texture = rhs.texture; + clip = rhs.clip; + local = false; + countX = rhs.countX; + countY = rhs.countY; + + rhs.texture = nullptr; + rhs.clip = {0, 0, 0, 0}; + rhs.local = false; + rhs.countX = 0; + rhs.countY = 0; +} + +void TileSheet::Load(SDL_Renderer* renderer, std::string fname, int tileWidth, int tileHeight) { + Image::Load(renderer, fname); + countX = clip.w / tileWidth; + countY = clip.h / tileHeight; + clip.w = tileWidth; + clip.h = tileHeight; +} + +SDL_Texture* TileSheet::SetTexture(SDL_Texture* ptr, int tileWidth, int tileHeight) { + Image::SetTexture(ptr); + countX = clip.w / tileWidth; + countY = clip.h / tileHeight; + clip.w = tileWidth; + clip.h = tileHeight; +} + +void TileSheet::Free() { + Image::Free(); + countX = countY = 0; +} + +void TileSheet::DrawLayerTo(SDL_Renderer* const renderer, Region* const region, int layer, int camX, int camY, double scaleX, double scaleY) { + //TODO: empty +} + +void TileSheet::DrawRegionTo(SDL_Renderer* const renderer, Region* const region, int camX, int camY, double scaleX, double scaleY) { + //TODO: (2) make TileSheet a friend class of Region + Region::type_t tile = 0; + for (register int i = 0; i < REGION_WIDTH; ++i) { + for (register int j = 0; j < REGION_HEIGHT; ++j) { + for (register int k = 0; k < REGION_DEPTH; ++k) { + tile = region->GetTile(i, j, k); + //0 is invisible + if (tile == 0) continue; + clip.x = (tile-1) % countX * clip.h; + clip.y = (tile-1) / countX * clip.w; + //TODO: (2) raw rendering; improve preformance + Image::DrawTo(renderer, + (region->GetX() + i) * clip.w - camX, + (region->GetY() + j) * clip.h - camY, + scaleX, scaleY); + } + } + } +} diff --git a/libmap/tile_sheet.hpp b/libmap/tile_sheet.hpp new file mode 100644 index 0000000..f327151 --- /dev/null +++ b/libmap/tile_sheet.hpp @@ -0,0 +1,67 @@ +/* Copyright: (c) Kayne Ruse 2013-2015 + * + * 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. +*/ +#pragma once + +#include "region.hpp" + +#include "image.hpp" + +#include + +class TileSheet : public Image { +public: + TileSheet() = default; + TileSheet(TileSheet const& rhs) { *this = rhs; } + TileSheet(TileSheet&& rhs) { *this = std::move(rhs); } + TileSheet(SDL_Renderer* r, std::string fn, int tw, int th) { Load(r, fn, tw, th); } + TileSheet(SDL_Texture* p, int tw, int th) { SetTexture(p, tw, th); } + ~TileSheet() = default; + + TileSheet& operator=(TileSheet const&); + TileSheet& operator=(TileSheet&&); + + void Load(SDL_Renderer*, std::string fname, int tileWidth, int tileHeight); + SDL_Texture* SetTexture(SDL_Texture*, int tileWidth, int tileHeight); + void Free() override; + + void DrawLayerTo(SDL_Renderer* const renderer, Region* const region, int layer, int camX, int camY, double scaleX = 1.0, double scaleY = 1.0); + void DrawRegionTo(SDL_Renderer* const renderer, Region* const region, int camX, int camY, double scaleX = 1.0, double scaleY = 1.0); + + //accessors + //DOCS: reuse Image::clip for tile sizes + int GetCountX() { return countX; } + int GetCountY() { return countY; } + int GetTileW() { return clip.w; } + int GetTileH() { return clip.h; } + +protected: + int countX = 0, countY = 0; + + using Image::Load; + using Image::Create; + using Image::SetTexture; + using Image::SetClip; + using Image::SetClipX; + using Image::SetClipY; + using Image::SetClipW; + using Image::SetClipH; +}; diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..ae47b38 --- /dev/null +++ b/main.cpp @@ -0,0 +1,41 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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 "SDL2/SDL.h" + +#include +#include + +int main(int argc, char** argv) { + try { + Application app; + app.Init(argc, argv); + app.Proc(); + app.Quit(); + } + catch(std::exception& e) { + std::cerr << "Fatal Error: " << e.what() << std::endl; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..180faa3 --- /dev/null +++ b/makefile @@ -0,0 +1,58 @@ +#include directories +INCLUDES+=. common libmap + +#libraries +#the order of the $(LIBS) is important, at least for MinGW +LIBS+=libcommon.a libmap.a +ifeq ($(OS),Windows_NT) + LIBS+=-lmingw32 +endif +LIBS+=-lSDL2main -lSDL2 -lSDL2_image -llua + +#flags +CXXFLAGS+=-std=c++11 $(addprefix -I,$(INCLUDES)) +ifeq ($(shell uname), Linux) + #read data about the current install + CXXFLAGS+=$(shell sdl-config --cflags --static-libs) +endif + +#source +CXXSRC=$(wildcard *.cpp) + +#objects +OBJDIR=obj +OBJ+=$(addprefix $(OBJDIR)/,$(CXXSRC:.cpp=.o)) + +#output +OUTDIR=out +OUT=$(addprefix $(OUTDIR)/,map) + +#targets +all: $(OBJ) $(OUT) + $(MAKE) -C common + $(MAKE) -C libmap + $(CXX) $(CXXFLAGS) -o $(OUT) $(OBJ) $(LIBS) + +$(OBJ): | $(OBJDIR) + +$(OUT): | $(OUTDIR) + +$(OBJDIR): + mkdir $(OBJDIR) + +$(OUTDIR): + mkdir $(OUTDIR) + +$(OBJDIR)/%.o: %.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +clean: +ifeq ($(OS),Windows_NT) + $(RM) *.o *.a *.exe +else ifeq ($(shell uname), Linux) + find . -type f -name '*.o' -exec rm -f -r -v {} \; + find . -type f -name '*.a' -exec rm -f -r -v {} \; + rm -f -v $(OUT) +endif + +rebuild: clean all diff --git a/scene_signal.hpp b/scene_signal.hpp new file mode 100644 index 0000000..49e0bcb --- /dev/null +++ b/scene_signal.hpp @@ -0,0 +1,32 @@ +/* Copyright: (c) Kayne Ruse 2015 + * + * 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. +*/ +#pragma once + +enum SceneSignal { + //reserved members for internal use + QUIT = -1, + CONTINUE = 0, + FIRST = 1, + + //custom scenes + EXAMPLE_SCENE +}; \ No newline at end of file