diff --git a/.gitignore b/.gitignore index 7753cbc..3d59779 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# Created by https://www.toptal.com/developers/gitignore/api/c++,sublimetext -# Edit at https://www.toptal.com/developers/gitignore?templates=c++,sublimetext +# Created by https://www.toptal.com/developers/gitignore/api/images,sublimetext,c++ +# Edit at https://www.toptal.com/developers/gitignore?templates=images,sublimetext,c++ ### C++ ### # Prerequisites @@ -10,7 +10,6 @@ *.lo *.o *.obj -*.res # Precompiled Headers *.gch @@ -36,6 +35,71 @@ *.out *.app +### Images ### +# JPEG +*.jpg +*.jpeg +*.jpe +*.jif +*.jfif +*.jfi + +# JPEG 2000 +*.jp2 +*.j2k +*.jpf +*.jpx +*.jpm +*.mj2 + +# JPEG XR +*.jxr +*.hdp +*.wdp + +# Graphics Interchange Format +*.gif + +# RAW +*.raw + +# Web P +*.webp + +# Portable Network Graphics +*.png + +# Animated Portable Network Graphics +*.apng + +# Multiple-image Network Graphics +*.mng + +# Tagged Image File Format +*.tiff +*.tif + +# Scalable Vector Graphics +*.svg +*.svgz + +# Portable Document Format +*.pdf + +# X BitMap +*.xbm + +# BMP +*.bmp +*.dib + +# ICO +*.ico + +# 3D Images +*.3dm +*.max + ### SublimeText ### # Cache files for Sublime Text *.tmlanguage.cache @@ -69,7 +133,4 @@ bh_unicode_properties.cache # https://packagecontrol.io/packages/sublime-github GitHub.sublime-settings -# End of https://www.toptal.com/developers/gitignore/api/c++,sublimetext - -*.wren -*.png \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/images,sublimetext,c++ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 6d26cd6..5290258 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "wrenbind17"] path = wrenbind17 url = https://github.com/matusnovak/wrenbind17 -[submodule "Cube2D-Framework"] - path = Cube2D-Framework - url = https://github.com/mastercuber55/Cube2D-Framework +[submodule "libtinyfiledialogs"] + path = libtinyfiledialogs + url = https://github.com/native-toolkit/libtinyfiledialogs diff --git a/Bindings/Engine.cpp b/Bindings/Engine.cpp deleted file mode 100644 index 0f54422..0000000 --- a/Bindings/Engine.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#define CGE_IMPL -#include -#include - -namespace Wren = wrenbind17; - -struct EngineCls {}; - -void BindEngine(Wren::VM & VM) { - auto& Module = VM.module("Cube2D"); - - Module.append("import \"raylib\" for RL, KEY, COLOR, Rectangle"); - - auto& Cube2DCls = Module.klass("Engine"); - - // Cube2DCls.funcStaticExt<&Engine::Init>("Init"); - // Cube2DCls.funcStaticExt<&Engine::Close>("Close"); - Cube2DCls.funcStaticExt<&Engine::WASDMovement>("WASDMovement"); - Cube2DCls.funcStaticExt<&Engine::AreColorSame>("AreColorsSame"); - Cube2DCls.funcStaticExt<&Engine::GetRandomPosition>("GetRandomPosition"); - - Module.append(R"( - class Scene { - - construct new() { - _BackgroundColor = COLOR["BLACK"] - _KeepRunning = true - _CodeToReturn = 0 - } - construct new(Background) { - _BackgroundColor = Background - _KeepRunning = true - _CodeToReturn = 0 - } - - ShouldClose() { RL.WindowShouldClose() } - Update() {} - Draw() {} - Run() { - while(!this.ShouldClose()) { - this.Update() - RL.BeginDrawing() - RL.ClearBackground(_BackgroundColor) - this.Draw() - RL.EndDrawing() - } - - return _CodeToReturn - } - Close(CodeToReturn) { - _CodeToReturn = CodeToReturn - _KeepRunning = false - } - - - BackgroundColor { _BackgroundColor } - KeepRunning { _KeepRunning } - CodeToReturn { _CodeToReturn } - - BackgroundColor=(Tint) { _BackgroundColor = Tint } - KeepRunning=(Boolean) { _KeepRunning = Boolean } - CodeToReturn=(Code) { _CodeToReturn = Code } - } - )"); - - auto& RectCls = Module.klass("OrignalRect"); - RectCls.ctor(); - - RectCls.var<&Engine::Rect::x>("x"); - RectCls.var<&Engine::Rect::y>("y"); - RectCls.var<&Engine::Rect::w>("w"); - RectCls.var<&Engine::Rect::h>("h"); - - RectCls.var<&Engine::Rect::Rotation>("Rotation"); - - RectCls.var<&Engine::Rect::TextureFile>("TextureFile"); - RectCls.var<&Engine::Rect::Source>("Source"); - RectCls.var<&Engine::Rect::Tint>("Tint"); - - RectCls.func<&Engine::Rect::SetPosition>("SetPosition"); - RectCls.func<&Engine::Rect::SetTextureFile>("SetTextureFile"); - RectCls.func<&Engine::Rect::Draw>("Draw"); - - RectCls.func<&Engine::Rect::GetCenter>("GetCenter"); - RectCls.func<&Engine::Rect::GetPosition>("GetPosition"); - RectCls.func<&Engine::Rect::GetRectangle>("GetRectangle"); - - RectCls.func<&Engine::Rect::IsColliding>("IsColliding"); - - Module.append(R"( - class Rect { - construct new(x, y, w, h) { - _Base = OrignalRect.new(x, y, w, h) - } - x { _Base.x } - x=(rhs) { _Base.x=rhs } - y { _Base.y } - y=(rhs) { _Base.y=rhs } - w { _Base.w } - w=(rhs) { _Base.w=rhs } - h { _Base.h } - h=(rhs) { _Base.h=rhs } - Rotation { _Base.Rotation } - Rotation=(rhs) { _Base.Rotation=rhs } - TextureFile { _Base.TextureFile } - TextureFile=(rhs) { _Base.TextureFile=rhs } - Source { _Base.Source } - Source=(rhs) { _Base.Source=rhs } - Tint { _Base.Tint } - Tint=(rhs) { _Base.Tint=rhs } - - SetPosition(rhs) { _Base.SetPosition(rhs) } - SetTextureFile(rhs) { _Base.SetTextureFile(rhs) } - Draw() { _Base.Draw() } - GetCenter() { _Base.GetCenter() } - GetPosition() { _Base.GetPosition() } - GetRectangle() { _Base.GetRectangle() } - - IsColliding(rhs) { _Base.IsColliding(rhs.Base) } - - Base { _Base } - } - )"); - - Module.append(R"( - var CGE_WHOLE_FILE = Rectangle.new() - CGE_WHOLE_FILE.x = 0 - CGE_WHOLE_FILE.y = 0 - CGE_WHOLE_FILE.width = -1 - CGE_WHOLE_FILE.height = -1 - )"); - -} \ No newline at end of file diff --git a/Bindings/Engine/Engine.cpp b/Bindings/Engine/Engine.cpp new file mode 100644 index 0000000..a8d7e99 --- /dev/null +++ b/Bindings/Engine/Engine.cpp @@ -0,0 +1,40 @@ +#include +#include +#include "Rect.hpp" + +namespace Wren = wrenbind17; + +void BindEngine(Wren::VM & VM) { + + auto& Module = VM.module("Engine"); + + auto& RectCls = Module.klass("ForeignRect"); + RectCls.ctor(); + + // Transform + RectCls.var<&ForeignRect::PositionAndScale>("PositionAndScale"); + RectCls.var<&ForeignRect::Rotation>("Rotation"); + + RectCls.var<&ForeignRect::TextureFile>("TextureFile"); + RectCls.var<&ForeignRect::Source>("Source"); + RectCls.var<&ForeignRect::Tint>("Tint"); + + RectCls.func<&ForeignRect::SetPosition>("SetPosition"); + RectCls.func<&ForeignRect::SetTextureFile>("SetTextureFile"); + RectCls.func<&ForeignRect::Draw>("Draw"); + + RectCls.func<&ForeignRect::GetCenter>("GetCenter"); + RectCls.func<&ForeignRect::GetPosition>("GetPosition"); + + RectCls.func<&ForeignRect::IsColliding>("IsColliding"); + + Module.append("import \"raylib\" for RL, COLOR, Color, KEY, Vector2"); + + Module.append( + #include "Rect.wren" + #include "Scene.wren" + #include "SceneManager.wren" + #include "Tools.wren" + ); + Module.append("var Shared = {}"); +} \ No newline at end of file diff --git a/Bindings/Engine/Rect.hpp b/Bindings/Engine/Rect.hpp new file mode 100644 index 0000000..d84e0fc --- /dev/null +++ b/Bindings/Engine/Rect.hpp @@ -0,0 +1,90 @@ +#define CGE_WHOLE_FILE { 0, 0, -1, -1 } +std::unordered_map Textures; + +struct ForeignRect { + + // Transformm + Rectangle PositionAndScale; + double Rotation; + + std::string TextureFile; + Rectangle Source; + Color Tint; + + // De-Constructers + ForeignRect(float x, float y, float w, float h); + ~ForeignRect(); + + // Setters + void SetTextureFile(std::string TextureFile); + + // Getters + Vector2 GetCenter(); + void SetPosition(Vector2 NewPosition); + Vector2 GetPosition(); + Vector2 GetRectangle(); + + // Utilities + bool IsColliding(ForeignRect * Other); + void Draw(); +}; + +ForeignRect::ForeignRect(float x, float y, float w, float h) { + this->PositionAndScale.x = x, this->PositionAndScale.y = y; + this->PositionAndScale.width = w, this->PositionAndScale.height = h; + this->Tint = WHITE; + this->Source = CGE_WHOLE_FILE, + this->Rotation = 0.0; +} +ForeignRect::~ForeignRect() {} +void ForeignRect::SetTextureFile(std::string TextureFile) { + + this->TextureFile = TextureFile; + if(Textures.find(TextureFile) != Textures.end()) return; + Textures[TextureFile] = LoadTexture(TextureFile.c_str()); + + if( + this->Source.x == 0 && + this->Source.y == 0 && + this->Source.width == -1 && + this->Source.height == -1 + ) { + this->Source.width = Textures[TextureFile].width, + this->Source.height = Textures[TextureFile].height; + } + +} +void ForeignRect::Draw() { + + (this->TextureFile.empty()) ? + DrawRectangleRec(this->PositionAndScale, this->Tint) + : + DrawTexturePro( + Textures[this->TextureFile], + this->Source, + (Rectangle){ + this->PositionAndScale.x + this->PositionAndScale.width / 2.0f, + this->PositionAndScale.y + this->PositionAndScale.height / 2.0f, + this->PositionAndScale.width, + this->PositionAndScale.height + }, + (Vector2){ this->PositionAndScale.width / 2.0f, this->PositionAndScale.height / 2.0f }, + this->Rotation, + this->Tint + ); +} +bool ForeignRect::IsColliding(ForeignRect * Other) { + return CheckCollisionRecs(PositionAndScale, Other->PositionAndScale); +} +void ForeignRect::SetPosition(Vector2 Position) { + this->PositionAndScale.x = Position.x, this->PositionAndScale.y = Position.y; +} +Vector2 ForeignRect::GetCenter() { + return { + this->PositionAndScale.x + this->PositionAndScale.width / 2.0f, + this->PositionAndScale.y + this->PositionAndScale.height / 2.0f + }; +} +Vector2 ForeignRect::GetPosition() { + return { this->PositionAndScale.x, this->PositionAndScale.y }; +} \ No newline at end of file diff --git a/Bindings/Engine/Rect.wren b/Bindings/Engine/Rect.wren new file mode 100644 index 0000000..cecb1aa --- /dev/null +++ b/Bindings/Engine/Rect.wren @@ -0,0 +1,58 @@ +R"( +class Rect { + construct new(x, y, w, h) { + _Base = ForeignRect.new(x, y, w, h) + } + construct new(x, y, w, h, TintOrTextureFile) { + _Base = ForeignRect.new(x, y, w, h) + + if(TintOrTextureFile is String) { + _Base.Tint = COLOR["WHITE"] + _Base.SetTextureFile(TintOrTextureFile) + } else { + _Base.Tint = TintOrTextureFile + } + } + + // Transformation + // Getters + x { _Base.PositionAndScale.x } + y { _Base.PositionAndScale.y } + w { _Base.PositionAndScale.width } + h { _Base.PositionAndScale.height } + // Setters + x=(rhs) { _Base.PositionAndScale.x=rhs } + y=(rhs) { _Base.PositionAndScale.y=rhs } + w=(rhs) { _Base.PositionAndScale.width=rhs } + h=(rhs) { _Base.PositionAndScale.height=rhs } + + // Position object + Position { _Base.GetPosition() } + Position=(rhs) { _Base.SetPosition(rhs) } + Center { _Base.GetCenter() } + + // Position And Scale literal object + PositionAndScale { _Base.PositionAndScale } + PositionAndScale=(rhs) { _Base.PositionAndScale=rhs } + + // Rotation + Rotation { _Base.Rotation } + Rotation=(rhs) { _Base.Rotation=rhs } + + // Other Variables + TextureFile { _Base.TextureFile } + TextureFile=(rhs) { _Base.SetTextureFile(rhs) } + + Source { _Base.Source } + Source=(rhs) { _Base.Source=rhs } + + Tint { _Base.Tint } + Tint=(rhs) { _Base.Tint=rhs } + + Draw() { _Base.Draw() } + + IsColliding(rhs) { _Base.IsColliding(rhs.Base) } + + Base { _Base } +} +)" \ No newline at end of file diff --git a/Bindings/Engine/Scene.wren b/Bindings/Engine/Scene.wren new file mode 100644 index 0000000..91c2500 --- /dev/null +++ b/Bindings/Engine/Scene.wren @@ -0,0 +1,13 @@ +R"( +class Scene { + + construct new() {} + ShouldClose { + if(_ShouldClose is Null) this.ShouldClose = false + return _ShouldClose + } + ShouldClose=(rhs) { _ShouldClose = rhs } + Update(dt) {} + Draw() {} +} +)" \ No newline at end of file diff --git a/Bindings/Engine/SceneManager.wren b/Bindings/Engine/SceneManager.wren new file mode 100644 index 0000000..ed5661c --- /dev/null +++ b/Bindings/Engine/SceneManager.wren @@ -0,0 +1,58 @@ +R"( +var Scenes = [] +class SceneManager /* is List */ { + + // super.Methods + static add (item) { Scenes.add (item) } + static addAll (other) { Scenes.addAll (other) } + static clear () { Scenes.clear () } + static count { Scenes.count } + static indexOf (value) { Scenes.indexOf (value) } + static insert (index, item) { Scenes.insert (index, item) } + static iterate (iterator) { Scenes.iterate (iterator) } + static iteratorValue(iterator) { Scenes.iteratorValue (iterator) } + static remove (value) { Scenes.remove (value) } + static removeAt (index) { Scenes.removeAt (index) } + static swap (index0, index1){ Scenes.swap (index0, index1)} + static [index] { Scenes[index] } + static [index]= (item) { Scenes[index]= item } + static + (other) { Scenes.addAll (other) } + + // this.Methods + static swapTo (item) { + this.clear() + this.add(other) + } + static swapToAll (other) { + this.clear() + this.addAll(other) + } + + static Run(BackgroundColor, KeepRunningCallback) { + + if(this.count == 0) return false + + for(i in 0...this.count) if(this[i] is Class) this[i] = this[i].new() + + while(!KeepRunningCallback.call()) { + for(i in 0...this.count) { + + this[i].Update(RL.GetFrameTime()) + + if(i == 0) { + RL.BeginDrawing() + RL.ClearBackground(BackgroundColor) + } + this[i].Draw() + + if(i == this.count - 1) RL.EndDrawing() + + // if(this[i].ShouldClose) this.removeAt(i) + + } + } + + return true + } +} +)" \ No newline at end of file diff --git a/Bindings/Engine/Tools.wren b/Bindings/Engine/Tools.wren new file mode 100644 index 0000000..760f6ab --- /dev/null +++ b/Bindings/Engine/Tools.wren @@ -0,0 +1,27 @@ +R"( +class Tools { + static WASDMovement(Object, Speed, dt) { + if(RL.IsKeyDown(KEY["W"])) Object.y = Object.y - Speed * dt + if(RL.IsKeyDown(KEY["A"])) Object.x = Object.x - Speed * dt + if(RL.IsKeyDown(KEY["S"])) Object.y = Object.y + Speed * dt + if(RL.IsKeyDown(KEY["D"])) Object.x = Object.x + Speed * dt + } + static AreColorSame(A, B) { RL.ColorToInt(A) == RL.ColorToInt(B) } + static GetRandomPosition(Cam) { + if(__Vector2ToReturn is Null) __Vector2ToReturn = Vector2.new() + + __Vector2ToReturn.x = RL.GetRandomValue(0, Cam.offset.x * 2) + __Vector2ToReturn.y = RL.GetRandomValue(0, Cam.offset.y * 2) + + return RL.GetScreenToWorld2D(__Vector2ToReturn, Cam) + } + static GetRandomColor(a) { + if(__ColorToReturn is Null) __ColorToReturn = Color.new() + __ColorToReturn.r = RL.GetRandomValue(0, 255) + __ColorToReturn.g = RL.GetRandomValue(0, 255) + __ColorToReturn.b = RL.GetRandomValue(0, 255) + __ColorToReturn.a = a is Null ? RL.GetRandomValue(0, 255) : a + return __ColorToReturn + } +} +)" \ No newline at end of file diff --git a/Bindings/External.cpp b/Bindings/External.cpp new file mode 100644 index 0000000..9463f66 --- /dev/null +++ b/Bindings/External.cpp @@ -0,0 +1,33 @@ +#include +#include "RLL.hpp" +#include +#include + +namespace RL { + #include +} + +namespace fs = std::filesystem; +namespace Wren = wrenbind17; + +void LoadPlugins(Wren::VM &VM) { + + if (!fs::exists("Plugins")) return; + + RL::TraceLog(RL::LOG_INFO, "Initializing plugins"); + + for (const auto& Entry : fs::directory_iterator("Plugins")) { + std::string EntryName = Entry.path().filename().string(); + RLL Library("Plugins/" + EntryName); + if(Library.Handle == nullptr) { + RL::TraceLog(RL::LOG_ERROR, " > [%s] Unable to load plugin", EntryName.c_str()); + continue; + } + auto Main = Library.GetFunction("Main"); + if(Main == nullptr) { + RL::TraceLog(RL::LOG_ERROR, " > [%s] Unable to find Main", EntryName.c_str()); + continue; + } + if(Main(VM) == EXIT_SUCCESS) RL::TraceLog(RL::LOG_INFO, " > [%s] Initialized successfully", EntryName.c_str()); + } +} diff --git a/Bindings/RLL.hpp b/Bindings/RLL.hpp new file mode 100644 index 0000000..9f7c55c --- /dev/null +++ b/Bindings/RLL.hpp @@ -0,0 +1,36 @@ +#ifdef _WIN32 + #include + #define HANDLE_TYPE HMODULE + #define LOAD_LIB(LIB) LoadLibrary(LIB.c_str()) + #define UNLOAD_LIB(HANDLE) FreeLibrary(HANDLE) + #define GET_FUNC(HANDLE, FUNC) GetProcAddress(HANDLE, FUNC) +#else + #include + #define HANDLE_TYPE void* + #define LOAD_LIB(LIB) dlopen(LIB.c_str(), RTLD_LAZY) + #define UNLOAD_LIB(HANDLE) dlclose(HANDLE) + #define GET_FUNC(HANDLE, FUNC) dlsym(HANDLE, FUNC) +#endif + +#include + +struct RLL { + + HANDLE_TYPE Handle = nullptr; + + RLL(const std::string& Lib) { + Handle = LOAD_LIB(Lib); + } + + ~RLL() { + if (Handle != nullptr) UNLOAD_LIB(Handle); + } + + template + FunctionType GetFunction(const std::string& FunctionName) { + if (Handle == nullptr) return nullptr; + + FunctionType Function = reinterpret_cast(GET_FUNC(Handle, FunctionName.c_str())); + return Function; + } +}; diff --git a/Cube2D-Framework b/Cube2D-Framework deleted file mode 160000 index ee181e9..0000000 --- a/Cube2D-Framework +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ee181e95994c03761ec3ecaf07a1c42e3a28dbc0 diff --git a/Icon.res b/Icon.res new file mode 100644 index 0000000..462cfcc Binary files /dev/null and b/Icon.res differ diff --git a/Log.txt b/Log.txt new file mode 100644 index 0000000..418d732 --- /dev/null +++ b/Log.txt @@ -0,0 +1,2 @@ +[INFO] Initializing Cube2D Engine +[ERROR] [main.wren] was not found. diff --git a/Makefile b/Makefile index 6e47c9e..3de6efa 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -RLOBJ = Bindings/raylib/main.o\ +BINDINGS = Bindings/raylib/main.o\ Bindings/raylib/Colors.o\ Bindings/raylib/Structs.o\ Bindings/raylib/Enums.o\ @@ -11,19 +11,20 @@ RLOBJ = Bindings/raylib/main.o\ Bindings/raylib/Textures.o \ Bindings/raylib/Text.o\ Bindings/raylib/Models.o\ - Bindings/raylib/Audio.o - -RMOBJ = Bindings/raymath.o + Bindings/raylib/Audio.o\ + Bindings/Engine/Engine.o\ + Bindings/External.o\ + Bindings/raymath.o CPP = g++ CC = gcc WINDRES = windres -OBJ = Icon.res main.o $(RLOBJ) $(RMOBJ) Bindings/Engine.o +OBJ = Icon.res main.o $(BINDINGS) libtinyfiledialogs/tinyfiledialogs.o LINKOBJ = $(OBJ) -LINKERS = -static-libgcc -mwindows -lwren -lraylib -lopengl32 -lgdi32 -lwinmm +LINKERS = -static-libgcc -mwindows -lwren -lraylib -lopengl32 -lgdi32 -lwinmm -lole32 LIBS = -L"C:/TDM-GCC-64/lib" -L"C:/Libraries/raylib/lib" -L"C:/Libraries/wren/lib" $(LINKERS) INCS = -I"C:/TDM-GCC-64/include" -I"C:/Libraries/raylib/include" -I"C:/Libraries/wren/include" -CXXINCS = -I"./wrenbind17/include" -I"./Cube2D-Framework" +CXXINCS = -I"./wrenbind17/include" -I"./libtinyfiledialogs" -I"./RLL/include" BIN = Cube2D.exe CFLAGS = $(INCS) CXXFLAGS = $(CXXINCS) $(CFLAGS) -std=c++17 diff --git a/docs/Documentation.md b/docs/Documentation.md index ce228fb..b7c6d91 100644 --- a/docs/Documentation.md +++ b/docs/Documentation.md @@ -1,7 +1,7 @@ --- title: Documentation layout: default -nav_order: 3 +nav_order: 4 --- # API Documentation diff --git a/docs/ErrorHanding.md b/docs/ErrorHanding.md deleted file mode 100644 index dbbd08a..0000000 --- a/docs/ErrorHanding.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Error Handling -layout: default -nav_order: 5 ---- - -# Error Handling - -As you saw in [Tutorials/Configuration], `Game.wren`'s `Path` variable has a key named "SceneError" which is used for error handling but how exactly? - -Don't worry, It will be real simple. - -Here is a example -```js -import "raylib" for RL, COLOR -import "Cube2D" for Scene - -class SceneError is Scene { - construct new() { - _Error = "NONE" - super() - } - - SetError(Error) { - _Error = Error - } - - Update() { - - } - - Draw() { - if(_Error != "NONE") RL.DrawText(_Error, 32, 32, 16, COLOR["RED"]) - } -} - -var Instance = SceneError.new() -``` -**The above code has been tested with correct paths.** - -You just need a `var` named `Instance` in your error scene file will engine use to throw error and a special method in your scene named `SetError` with signature `_` i.e `SetError(Error)` where you can save the error for displaying later on using Draw() method and as of course you don't need to call `.Run()` cuz the engine does that when the time is right. \ No newline at end of file diff --git a/docs/Installation.md b/docs/Installation.md index 216bb20..1218223 100644 --- a/docs/Installation.md +++ b/docs/Installation.md @@ -19,7 +19,7 @@ see [Build From Source] ## Building From Source ### Requirements -- A C++17+ Compiler Installed ( I Use MinGW32 ) +- A C++17 Compiler Installed ( I Use MinGW32 ) - [raylib] Installed - [wren] Installed diff --git a/docs/Tutorials/Configuration.md b/docs/Tutorials/Configuration.md deleted file mode 100644 index af61605..0000000 --- a/docs/Tutorials/Configuration.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Configuration -layout: default -parent: Tutorials -nav_order: 1 ---- - -# Configuration - -- Any projects needs a folder of its own, so first of all create a folder for your project! -- Now, copy Cube2D executable to this folder -- Create Game.wren such as following - -```js -// File: Game.wren -var Window = { - "Width" : 1280, // (Default: 640) - "Height" : 768, // (Default: 480) - "FPS" : 60, // (Default: 60) - "Title" : "Square Wars", - "Fullscreen": true // (Default: false) -} - -var Path = { - "Icon" : "Icon.png", // (Default: None) - "Scripts" : "Scripts/", // (Default: Scripts/) - "Resources" : "Resources/", // (Default: Resources/) - "MainScript": "Main.wren", // (Default: Main.wren) - "SceneError": "Scenes/SceneError.wren" -} -``` -**The above code has been tested with correct paths.** -As for the current version, it is a absolute must that you have a file named Game.wren in same folder as Cube2D executable or it will crash but sooner or later we will make it so that the engine lets you know that no Game.wren was found atleast. diff --git a/docs/Tutorials/Creating A Scene.md b/docs/Tutorials/Creating A Scene.md index 1d3abd4..7b84fab 100644 --- a/docs/Tutorials/Creating A Scene.md +++ b/docs/Tutorials/Creating A Scene.md @@ -11,11 +11,11 @@ Lets create a simple scene where you can move around player. - Create a folder named "Scenes" in your desired `Scripts` folder (optional) - Create a file for your scene with your desired name ( I Prefer SceneExample ) -- `import "Cube2D" for Scene` +- `import "Engine"` - Create a class as following ```js -import "Cube2D" for Scene +import "Engine" class SceneExample is Scene { diff --git a/docs/Tutorials/Initialization.md b/docs/Tutorials/Initialization.md index 85f063b..3cce23f 100644 --- a/docs/Tutorials/Initialization.md +++ b/docs/Tutorials/Initialization.md @@ -16,7 +16,7 @@ For now, lets make a simple game where you have to move player around. // import whatever you need. import "raylib" for RL, COLOR import "raymath" for RM -import "Cube2D" for Engine, Scene, Rect +import "Engine" // Sorry, Coudn't think of much here. diff --git a/docs/Tutorials/ConfigSave Files.md b/docs/Tutorials/Save Files.md similarity index 62% rename from docs/Tutorials/ConfigSave Files.md rename to docs/Tutorials/Save Files.md index 2ec16c1..de1cf48 100644 --- a/docs/Tutorials/ConfigSave Files.md +++ b/docs/Tutorials/Save Files.md @@ -1,19 +1,19 @@ --- -title: Config/Save Files +title: ConfigSave Files layout: default parent: Tutorials nav_order: 5 --- -# Config/Save Files -You probably need files somewhat files for user configuration or for saving user data to be used in the next session. However, Cube2D Engine supports nothing of a sort but the original idea was to bind [ini.h] & [json] to [wren] for configuration files and save files and previous versions of the engine were using [ini.h] instead of `Game.wren`. I did try to bind [json] to [wren] but my brain just couldn't comprehend the greatness of [json] to be bind-ed into [wren] and as for [ini.h], I never even tried binding it to [wren] so lets see how you do it. +# Save Files +You probably need somewhat files for saving game's current state to be used in the next session. However, Cube2D Engine supports nothing of a sort but the original idea was to bind [ini.h] & [json] to [wren] for that purpose and previous versions of the engine were using [ini.h] instead of `Game.wren`. I did try to bind [json] to [wren] but my brain just couldn't comprehend the greatness of [json] to be bind-ed into [wren] and as for [ini.h], I never even tried binding it to [wren] so lets see how you do it. -# Configuration Files (.wren Files) +# Wren Files {: .note } -When I say configuration files I mean manual configuration by user of your program. +Only for manual configuration, unless you make somesort of wren parser and stringifier. -For configuration files you would want to use [wren] files ( with maps I prefer ) cuz [wren] has really nice `import` statements for those stuff, below are two files demonstrating a example of using [wren] files as configuration files. +[wren] has really nice `import` statements so you may just want to have simple wren files where you have `var`iables, below are two files demonstrating a example of using [wren] files as configuration files. ```js // File: Config.wren @@ -33,14 +33,12 @@ System.print(Config["MyString"]) ``` -# Save Files (.json Files) -{: .note } -This may also be used for non-user configuration files +# Json Files - Q: But didn't you say you were unable to bind [json] to [wren] - A: Yes, but there is a better alternative than binding [json] to [wren] because C++ is not dynamically typed while [wren] is so it would be smarter to just code a json library in [wren] so lets see how to do that. -I wasn't going to code a json library but luckily for you, someone has already made it for wren and its called [wren-json] and if you see the readme.md there is not much to it, it just shows `JSON.parse(Str)` & `JSON.stringify(Obj)` which doesn't explain how to use it but its easy to guess so lets see how to use it. +I wasn't going to code a json library but luckily for you, someone has already made it for wren and its called [wren-json].. {: .note } You need [wren-json] in your desired scripts directory. @@ -60,7 +58,7 @@ First, here's a .json file Second, Here's a .wren file ```js // File: SceneExample.wren -import "Cube2D" for Engine, Scene, Rect +import "Engine" import "raylib" for RL, COLOR import "path/to/json.wren" for JSON @@ -103,4 +101,4 @@ If I'm correct, [wren-json] doesn't have a file loading or saving system or noth [ini.h]: https://giosali.github.io/ini.h/ [json]: https://json.nlohmann.me/ [wren]: https://wren.io -[wren-json]: https://github.com/brandly/wren-json \ No newline at end of file +[wren-json]: https://github.com/ruby0x1/wren-json \ No newline at end of file diff --git a/docs/Tutorials/Textures.md b/docs/Tutorials/Textures.md index 362df00..674bf3d 100644 --- a/docs/Tutorials/Textures.md +++ b/docs/Tutorials/Textures.md @@ -9,7 +9,7 @@ nav_order: 4 [Cube2D Framework]'s `Rect` `class` is the best way to use textures if you are creating rectangles. ```cpp -import "Cube2D" for Engine, Scene, Rect +import "Engine" for Engine, Scene, Rect class SceneGame is Scene { construct new() { diff --git a/docs/Tutorials/index.md b/docs/Tutorials/index.md index d02502a..39dab7b 100644 --- a/docs/Tutorials/index.md +++ b/docs/Tutorials/index.md @@ -1,8 +1,8 @@ --- title: Tutorials layout: default -nav_order: 4 +nav_order: 5 has_children: true --- -# Tutorials \ No newline at end of file +# Tutorials diff --git a/libtinyfiledialogs b/libtinyfiledialogs new file mode 160000 index 0000000..cc6b593 --- /dev/null +++ b/libtinyfiledialogs @@ -0,0 +1 @@ +Subproject commit cc6b593c029110af8045826ce691f540c85e850c diff --git a/main.cpp b/main.cpp index 36fb323..c3b0454 100644 --- a/main.cpp +++ b/main.cpp @@ -1,176 +1,98 @@ -// #include "ini.h/ini.h" #include -#include -#include #include #include #include #include +#include +#include +#include namespace Wren = wrenbind17; - -struct SceneError : Engine::Scene { - - std::string Error; - Vector2 Size; - - SceneError(std::string Error) { - this->Error = Error; - Size = MeasureTextEx(GetFontDefault(), Error.c_str(), 24, 2); - - SetWindowTitle("Cube2D - An Error Occured"); - SetWindowSize(Size.x + 24 / 2, Size.y + 24 / 2); - } - - void Update() {} - void Draw() { - DrawText(Error.c_str(), 24 / 4, 32 / 4, 24, RED); - // GuiTextBox({0, 0, 32 * 5, 32}, const_cast(this->Error.c_str()), 0, false); - } - - ~SceneError() {} -}; - - -// struct SceneGen : Engine::Scene { - -// Vector2 anchor01 = { 0, -24 }; - -// bool TextBoxNameEditMode = false; -// char TextBox001Text[128] = "Name"; -// bool ValueBOx003EditMode = false; -// int ValueBOx003Value = 0; -// bool ValueBOx004EditMode = false; -// int ValueBOx004Value = 0; -// bool CreatePressed = false; -// bool TextBox008EditMode = false; -// char TextBox008Text[128] = "Main Script"; -// bool TextBox009EditMode = false; -// char TextBox009Text[128] = "Scripts"; -// bool TextBox010EditMode = false; -// char TextBox010Text[128] = "Resources"; -// bool Fullscreen = true; -// bool Logging = true; - -// SceneGen() { -// Engine::Init(300, 100, "Cube2D - Game Template Generator"); -// this->BackgroundColor = BLACK; -// } - -// void Update() override { - -// } -// void Draw() override { -// if (GuiTextBox((Rectangle){ anchor01.x + 8, anchor01.y + 32, 96, 24 }, TextBox001Text, 128, TextBoxNameEditMode)) TextBoxNameEditMode = !TextBoxNameEditMode; -// GuiGroupBox((Rectangle){ anchor01.x + 8, anchor01.y + 64, 96, 56 }, "Resolution"); -// if (GuiValueBox((Rectangle){ anchor01.x + 32, anchor01.y + 72, 56, 16 }, "X ", &ValueBOx003Value, 0, 100, ValueBOx003EditMode)) ValueBOx003EditMode = !ValueBOx003EditMode; -// if (GuiValueBox((Rectangle){ anchor01.x + 32, anchor01.y + 96, 56, 16 }, "Y ", &ValueBOx004Value, 0, 100, ValueBOx004EditMode)) ValueBOx004EditMode = !ValueBOx004EditMode; -// CreatePressed = GuiButton((Rectangle){ anchor01.x + 112, anchor01.y + 96, 88, 24 }, "Create"); -// if (GuiTextBox((Rectangle){ anchor01.x + 208, anchor01.y + 32, 88, 24 }, TextBox008Text, 128, TextBox008EditMode)) TextBox008EditMode = !TextBox008EditMode; -// if (GuiTextBox((Rectangle){ anchor01.x + 208, anchor01.y + 64, 88, 24 }, TextBox009Text, 128, TextBox009EditMode)) TextBox009EditMode = !TextBox009EditMode; -// if (GuiTextBox((Rectangle){ anchor01.x + 208, anchor01.y + 96, 88, 24 }, TextBox010Text, 128, TextBox010EditMode)) TextBox010EditMode = !TextBox010EditMode; -// GuiToggle((Rectangle){ anchor01.x + 112, anchor01.y + 32, 88, 24 }, "Fullscreen", &Fullscreen); -// GuiToggle((Rectangle){ anchor01.x + 112, anchor01.y + 64, 88, 24 }, "Logging", &Logging); -// } - -// ~SceneGen() { - -// } -// }; - -// struct SceneError : Engine::Scene { - -// char * Error; - -// SceneError(std::string Error) { -// this->Error = const_cast(Error.c_str()); -// TextCopy(this->Error, Error.c_str()); -// SetWindowSize(32 * 12, 32 * 3); -// SetWindowTitle("Cube2D - An Error Occured"); -// } - -// void Update() override {} -// void Draw() override { -// GuiTextBox({ 0, 0, 32 * 12, 32 * 3 }, this->Error, 32, false); -// } - -// ~SceneError() {} -// }; - -struct paths { - std::string Appdata; - std::string Scripts; - std::string Resources; - std::string MainScript; - std::string SceneError; - std::string Icon; -}; std::ofstream LogFile; -std::ostringstream LogStream; -paths Paths; - -bool Logging; void CustomLog(int LOG_LEVEL, const char * Text, va_list Args); -int InitFromConfig(Wren::VM & VM); void BindRaylib(Wren::VM & VM); void BindRaymath(Wren::VM & VM); void BindEngine(Wren::VM & VM); +void LoadPlugins(Wren::VM & VM); #define FileNotFound(File) Wren::Exception(std::string("[") + File + std::string("] was not found.")) int main() { - + LogFile.open("./Log.txt"); + if(!LogFile.is_open()) { + TraceLog(LOG_WARNING, "Unable to open log file!"); + TraceLog(LOG_WARNING, "Printing only to stderr!"); + } + SetTraceLogCallback(CustomLog); + TraceLog(LOG_INFO, "Initializing Cube2D Engine"); + + if(!FileExists("main.wren")) { + TraceLog(LOG_ERROR, "[%s] was not found.", "main.wren"); + tinyfd_messageBox("Cube2D - An Error Occured" , "[main.wren] was not found." , "ok" , "error", 1); + return EXIT_FAILURE; + } + TraceLog(LOG_INFO, "Initializing Wren::VM"); Wren::VM VM; VM.setPrintFunc([](const char * Text){ + std::clog << ((strlen(Text) != 1) ? "[WREN] " : "") << Text; LogFile << ((strlen(Text) != 1) ? "[WREN] " : "") << Text; }); - VM.setLoadFileFunc([&Paths]( + VM.setLoadFileFunc([]( const std::vector&, const std::string& Name) -> std::string { - std::string File(Paths.Scripts + (IsFileExtension(Name.c_str(), ".wren") ? Name : (Name + ".wren"))); + + std::string File; + Name != "main.wren" ? File = "Scripts/" + (IsFileExtension(Name.c_str(), ".wren") ? Name : (Name + ".wren")) + : File = Name; + if(!FileExists(File.c_str())) { - TraceLog(LOG_ERROR, "[%s] was not found.", File.c_str()); + std::string Error = "[" + File + "] was not found."; + TraceLog(LOG_ERROR, Error.c_str()); + tinyfd_messageBox("Cube2D - An Error Occured", Error.c_str(), "ok", "error", 1); return ""; } - return LoadFileText(File.c_str()); + char * Text = LoadFileText(File.c_str()); + Text = TextReplace(Text, "import \"Engine\"", "import \"Engine\" for Rect, Scene, SceneManager, Tools, Shared"); + std::string ToReturn = Text; + UnloadFileText(Text); + return ToReturn; }); // Bind everything BindRaylib(VM); BindRaymath(VM); BindEngine(VM); + // LoadPlugins(VM); - if(InitFromConfig(VM) == EXIT_FAILURE) return EXIT_FAILURE; - - // return SceneGen().Run(); + InitWindow(640, 480, "Cube2D"); + InitAudioDevice(); + SetExitKey(KEY_NULL); + + std::string Icon = "Resources/Icon.png"; + if(FileExists(Icon.c_str())) SetWindowIcon(LoadImage(Icon.c_str())); try { - VM.runFromModule(Paths.MainScript); + VM.runFromModule("main.wren"); } catch(wrenbind17::Exception& Error) { TraceLog(LOG_ERROR, Error.what()); - // SceneError(Error.what()).Run(); - VM.runFromModule("Scenes/SceneError.wren"); - Wren::Variable Scene = VM.find("Scenes/SceneError.wren", "Instance"); - Wren::Method ErrorSetter = Scene.func("SetError(_)"); - std::string ErrorStr = Error.what(); - ErrorSetter(ErrorStr); - Wren::Method Runner = Scene.func("Run()"); - Runner(); + tinyfd_messageBox("Cube2D - An Error Occured", Error.what(), "ok", "error", 1); } - Engine::Close(); + CloseAudioDevice(); + CloseWindow(); if(LogFile.is_open()) LogFile.close(); + return EXIT_SUCCESS; } void CustomLog(int LOG_LEVEL, const char * Text, va_list Args) { @@ -178,82 +100,17 @@ void CustomLog(int LOG_LEVEL, const char * Text, va_list Args) { std::string Tag; switch(LOG_LEVEL) { - case LOG_INFO: Tag = "[INFO] "; break; - case LOG_ERROR: Tag = "[ERROR] "; break; - case LOG_WARNING: Tag = "[WARN] "; break; - case LOG_DEBUG: Tag = "[DEBUG] "; break; - default: break; - } - - char buffer[1024]; - vsnprintf(buffer, sizeof(buffer), Text, Args); - - std::cout << Tag << buffer << std::endl; - LogFile.is_open() ? (LogFile << Tag << buffer << std::endl) : LogStream << Tag << buffer << std::endl; -} - -int InitFromConfig(Wren::VM & VM) { - // Load Configuration File - if(!FileExists("Game.wren")) { - TraceLog(LOG_ERROR, "[%s] was not found.", "Game.wren"); - Engine::Init(640, 480, "Cube2D - An Error Occured"); - SceneError("[Game.wren] was not found.").Run(); - Engine::Close(); - return EXIT_FAILURE; + case LOG_INFO: Tag = "[INFO] "; break; + case LOG_ERROR: Tag = "[ERROR] "; break; + case LOG_WARNING: Tag = "[WARN] "; break; + case LOG_DEBUG: Tag = "[DEBUG] "; break; + default: break; } - VM.runFromModule("Game.wren"); - // Make var Window usable - Wren::Variable WindowMap = VM.find("Game.wren", "Window"); - Wren::Method WindowGet = WindowMap.func("[_]"); - - // Initialization - int Width; - if(WindowGet("Width").is()) Width = WindowGet("Width").as(); - else { - TraceLog(LOG_WARNING, "Window width was not provided, switching to 640"); - Width = 640; - } - - int Height; - if(WindowGet("Height").is()) Height = WindowGet("Height").as(); - else { - TraceLog(LOG_WARNING, "Window height was not provided, switching to 640"); - Height = 640; - } - - if(!WindowGet("Title").is()) { - TraceLog(LOG_ERROR, "Window title which is a must was not provided."); - return EXIT_FAILURE; - } - std::string Title = WindowGet("Title").as(); - Engine::Init(Width, Height, Title); - - // Other Stuff - Paths.Appdata = std::getenv("APPDATA"); - Paths.Appdata += "/"; - Paths.Appdata += Title; - Paths.Appdata += "/"; + char Buffer[1024]; + vsnprintf(Buffer, sizeof(Buffer), Text, Args); - LogFile.open(Paths.Appdata + "Log.txt"); - LogFile << LogStream.str(); + std::clog << Tag << Buffer << std::endl; + if(LogFile.is_open()) LogFile << Tag << Buffer << std::endl; - if(WindowGet("FPS").is()) SetTargetFPS(WindowGet("FPS").as()); - if(WindowGet("Fullscreen").is() && WindowGet("Fullscreen").as()) ToggleFullscreen(); - - // Make var Path usable - Wren::Variable PathMap = VM.find("Game.wren", "Path"); - Wren::Method PathGet = PathMap.func("[_]"); - - //Set Icon - Paths.Icon = PathGet("Icon").as(); - SetWindowIcon(LoadImage(("Resources/" + Paths.Icon).c_str())); - - Paths.Scripts = PathGet("Scripts").as(); - Paths.Resources = PathGet("Resources").as(); - Paths.MainScript = PathGet("MainScript").as(); - Paths.SceneError = PathGet("SceneError").as(); - - - return EXIT_SUCCESS; } \ No newline at end of file