From d36dc68f8aa5fa9620a23c6e51a408751ebbb61f Mon Sep 17 00:00:00 2001 From: kin fuyuki Date: Thu, 25 Dec 2025 13:21:58 -0300 Subject: [PATCH] starting the rewrite of forespend. --- engine/src/engine.h | 11 +- engine/src/program.cpp | 6 + engine/src/program.h | 4 + engine/src/resmgr.h | 12 + engine/src/scenes/node2d.h | 569 ++++++++++-------- engine/src/scenes/node2drelative.h | 362 +++++++++++ engine/src/scenes/nodes.h | 18 +- engine/src/scenes/scene.h | 12 +- engine/test.cpp | 12 +- games/endlauncher/src/main.cpp | 13 +- games/forespend/src/client/client.cpp | 36 +- games/forespend/src/client/client.h | 3 +- games/forespend/src/client/scenes/game.cpp | 1 + games/forespend/src/client/scenes/game.h | 7 + .../forespend/src/client/scenes/mainmenu.cpp | 2 +- games/forespend/src/client/scenes/mainmenu.h | 20 +- games/forespend/src/main.cpp | 50 +- games/forespend/src/server/server.h | 2 +- include/incmgr.h | 1 + 19 files changed, 842 insertions(+), 299 deletions(-) create mode 100644 engine/src/resmgr.h create mode 100644 engine/src/scenes/node2drelative.h create mode 100644 games/forespend/src/client/scenes/game.cpp create mode 100644 games/forespend/src/client/scenes/game.h diff --git a/engine/src/engine.h b/engine/src/engine.h index a4888df..f2f7746 100644 --- a/engine/src/engine.h +++ b/engine/src/engine.h @@ -1,5 +1,14 @@ +#pragma once + #include "net.h" #include "gr.h" #include "aud.h" #include "program.h" -#include "scenes/scene.h" \ No newline at end of file +#include "scenes/scene.h" +enum PLATFORM { + WINDOWS,LINUX,MACOS, + ANDROID,IOS +}; +extern PLATFORM platform; +extern std::string androidpackage; +#include "resmgr.h" \ No newline at end of file diff --git a/engine/src/program.cpp b/engine/src/program.cpp index eba248d..692a326 100644 --- a/engine/src/program.cpp +++ b/engine/src/program.cpp @@ -9,3 +9,9 @@ long long calibrate() { return (__rdtsc() - start) * 10; } const long long enginend::CPUCLOCK=calibrate(); +void enginend::program::changescene(scene *scn) { + this->currentscene->exit(); + delete this->currentscene; + this->currentscene = scn; + this->currentscene->boot(); +} diff --git a/engine/src/program.h b/engine/src/program.h index 9787e8e..1d7d517 100644 --- a/engine/src/program.h +++ b/engine/src/program.h @@ -3,6 +3,8 @@ #include #include +#include "scenes/scene.h" + namespace enginend{ extern const long long CPUCLOCK; inline const char* COMMONCONFIG(); @@ -10,8 +12,10 @@ class program { unsigned long long currenttick = __rdtsc(); unsigned long long currentframe = __rdtsc(); public: + scene *currentscene; int tickrate; int framerate; + void changescene(scene*scn); program():client(false){} program(bool isclient):client(isclient){} virtual const char* CONF()=0; diff --git a/engine/src/resmgr.h b/engine/src/resmgr.h new file mode 100644 index 0000000..206166a --- /dev/null +++ b/engine/src/resmgr.h @@ -0,0 +1,12 @@ +#pragma once +#include +#include "engine.h" +inline const char *AT(std::string path) { + if (platform==LINUX || platform==WINDOWS || platform==MACOS) { + return path.c_str(); + }else { + if (platform==ANDROID) { + return ("/data/data/"+androidpackage+"/files/"+path).c_str(); + } + } +} diff --git a/engine/src/scenes/node2d.h b/engine/src/scenes/node2d.h index 07fa934..0857f66 100644 --- a/engine/src/scenes/node2d.h +++ b/engine/src/scenes/node2d.h @@ -4,78 +4,115 @@ #include "nodes.h" namespace enginend { - struct node2d :public node { - Vector2 pos; - node2d(){} - node2d(float x,float y):pos(Vector2{x,y}){} - }; - struct rect :virtual public node2d{ - Vector2 size; - rect(){} - rect(float x,float y,float w,float h):size(Vector2{w,h}){ - this->pos=Vector2{x,y}; - } - }; - struct textured :virtual public rect{ - Texture2D* texture; - textured(){} - textured(Texture2D* texture,float x,float y,float w,float h):texture(texture){ - this->pos=Vector2{x,y};this->size=Vector2{w,h}; - } - void boot()override{} - void tick()override{} - void draw()override{if(texture!=nullptr)DrawTexture(*texture,pos.x,pos.y,WHITE);} - void exit()override{} - }; - struct colored :virtual public rect{ - Color c; - colored(){} - colored(Color color,float x,float y,float w,float h):c(color){ - this->pos=Vector2{x,y};this->size=Vector2{w,h}; - } - void boot()override{} - void tick()override{} - void draw()override{DrawRectangle(pos.x,pos.y,size.x,size.y,c);} - void exit()override{} - }; - struct tinted :virtual public colored,virtual public textured{ - tinted(){} - tinted(Texture2D* texture,Color color,float x,float y,float w,float h): - node2d(x,y), - rect(x,y,w,h), - colored(color,x,y,w,h), - textured(texture,x,y,w,h) - {} - void boot()override{this->colored::boot();this->textured::boot();} - void tick()override{this->colored::tick();this->textured::tick();} - void draw()override{if(texture!=nullptr)DrawTexture(*texture,pos.x,pos.y,c);} - void exit()override{this->colored::exit();this->textured::exit();} - }; - struct text :public tinted { - protected: - std::string result; - public: - Font font; - float fs; - Color txc; - std::string content; - text(){fs=20;} - text(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize,std::string txt): - font(f),fs(fsize),content(txt) - { - this->pos=Vector2{x,y};this->size=Vector2{w,h};this->texture=texture;this->c=color;this->txc=txcol; - - result=content; - size_t initp=0; - while((initp=result.find("\n",initp))!=std::string::npos){ - result.replace(initp,1,"\\n"); - initp+=2; + namespace nodes { + struct node2d :public node { + Vector2 pos; + node2d(){} + node2d(float x,float y):pos(Vector2{x,y}){} + }; + struct rect :virtual public node2d{ + Vector2 size; + rect(){} + rect(float x,float y,float w,float h):size(Vector2{w,h}){ + this->pos=Vector2{x,y}; } - } - void boot()override{this->tinted::boot();} - void tick()override { - this->tinted::tick(); - if(result!=content){ + }; + struct textured :virtual public rect{ + Texture2D* texture; + textured(){} + textured(Texture2D* texture,float x,float y,float w,float h):texture(texture){ + this->pos=Vector2{x,y};this->size=Vector2{w,h}; + } + void boot()override{} + void tick()override{} + void draw()override{if(texture!=nullptr)DrawTexture(*texture,pos.x,pos.y,WHITE);} + void exit()override{delete texture;} + }; + struct animated : virtual public textured { + Image animimage; + int frames; + int currentframe; + int framedelay; + int framecounter; + unsigned int nextframeoffset; + + animated() : frames(0), currentframe(0), framedelay(6), framecounter(0), nextframeoffset(0) { + animimage.data = nullptr; + } + + animated(const char* gifpath, Vector2 position, Vector2 size, int delay = 6) + : textured(nullptr, position.x, position.y, size.x, size.y), + framedelay(delay), currentframe(0), framecounter(0), frames(0), nextframeoffset(0) + { + animimage = LoadImageAnim(gifpath, &frames); + if (frames > 0) { + texture = new Texture2D(LoadTextureFromImage(animimage)); + } + } + + void tick() override { + textured::tick(); + if (frames <= 1) return; + + framecounter++; + if (framecounter >= framedelay) { + framecounter = 0; + currentframe++; + if (currentframe >= frames) currentframe = 0; + nextframeoffset = animimage.width * animimage.height * 4 * currentframe; + UpdateTexture(*texture, ((unsigned char*)animimage.data) + nextframeoffset); + } + } + void draw() override { + textured::draw(); + } + void exit() override { + if (animimage.data) UnloadImage(animimage); + if (texture) { + UnloadTexture(*texture); + delete texture; + texture = nullptr; + } + } + }; + struct colored :virtual public rect{ + Color c; + colored(){} + colored(Color color,float x,float y,float w,float h):c(color){ + this->pos=Vector2{x,y};this->size=Vector2{w,h}; + } + void boot()override{} + void tick()override{} + void draw()override{DrawRectangle(pos.x,pos.y,size.x,size.y,c);} + void exit()override{} + }; + struct tinted :virtual public colored,virtual public textured{ + tinted(){} + tinted(Texture2D* texture,Color color,float x,float y,float w,float h): + node2d(x,y), + rect(x,y,w,h), + colored(color,x,y,w,h), + textured(texture,x,y,w,h) + {} + void boot()override{this->colored::boot();this->textured::boot();} + void tick()override{this->colored::tick();this->textured::tick();} + void draw()override{if(texture!=nullptr)DrawTexture(*texture,pos.x,pos.y,c);} + void exit()override{this->colored::exit();this->textured::exit();} + }; + struct text :public tinted { + protected: + std::string result; + public: + Font font; + float fs; + Color txc; + std::string content; + text(){fs=20;} + text(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize,std::string txt): + font(f),fs(fsize),content(txt) + { + this->pos=Vector2{x,y};this->size=Vector2{w,h};this->texture=texture;this->c=color;this->txc=txcol; + result=content; size_t initp=0; while((initp=result.find("\n",initp))!=std::string::npos){ @@ -83,202 +120,214 @@ namespace enginend { initp+=2; } } - } - void draw()override { - Vector2 minsize=MeasureTextEx(font,content.c_str(),fs,1); - Vector2 charsize=MeasureTextEx(font," ",fs,1); - float p=charsize.x>charsize.y?charsize.x/minsize.x:charsize.y/minsize.y; - p=p*2; - int minh=(minsize.y>size.y)?minsize.y:size.y; - int minw=(minsize.x>size.x)?minsize.x:size.x; - DrawRectangle(pos.x-charsize.x,pos.y-charsize.y,minw+p,minh+p,c); - DrawTextEx(font,content.c_str(),pos,fs,1,txc); - } - void exit()override{this->tinted::exit();} - }; - struct button :virtual public tinted{ - std::function func; - bool pressed; - bool hover; - button():pressed(false){} - button(Texture2D* texture,Color color,float x,float y,float w,float h,std::function f):func(f),pressed(false){ - this->pos=Vector2{x,y};this->size=Vector2{w,h};this->texture=texture;this->c=color; - } - void boot()override{this->tinted::boot();} - void tick()override{ - this->tinted::tick(); - Vector2 mouse=GetMousePosition(); - if(CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y})){hover=true; - if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ - pressed=true; - if(func)func(); - }else{ - pressed=false; - } - }else{ - hover=false; - } - } - void draw()override { - if(this->texture!=nullptr)DrawTexture(*texture,pos.x,pos.y,c); - else DrawRectangle(pos.x,pos.y,size.x,size.y,c); - } - void exit()override{this->tinted::exit();} - }; - struct labeledbutton :virtual public button { - std::string label; - Font font; - int fs; - Color txc; - labeledbutton(std::string name,Texture2D* texture,Color color,Color text, - float x,float y,float w,float h,std::function f, - Font fnt,int size):font(fnt),fs(size),txc(text){ - this->pos=Vector2{x,y};this->size=Vector2{w,h};this->texture=texture;this->c=color; - this->func=f;this->pressed=false; - this->label=name; - } - void boot()override{this->button::boot();} - void tick()override{this->button::tick();} - void draw()override{ - this->button::draw(); - Vector2 tsize=MeasureTextEx(font,label.c_str(),fs,1); - Vector2 tpos={ - pos.x+(size.x-tsize.x)/2, - pos.y+(size.y-tsize.y)/2 - }; - DrawTextEx(font,label.c_str(),tpos,fs,1,txc); - } - void exit()override{this->button::exit();} - }; - struct slider :virtual public tinted{ - float val; - float minv; - float maxv; - slider():val(0),minv(0),maxv(1){} - slider(Texture2D* texture,Color color,float x,float y,float w,float h,float min,float max,float v):val(v),minv(min),maxv(max){ - this->pos=Vector2{x,y};this->size=Vector2{x,y};this->texture=texture;this->c=color; - } - void boot()override{this->tinted::boot();} - void tick()override{ - this->tinted::tick(); - Vector2 mouse=GetMousePosition(); - if(CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y})&&IsMouseButtonDown(MOUSE_LEFT_BUTTON)){ - float t=(mouse.x-pos.x)/size.x; - val=minv+t*(maxv-minv); - if(valmaxv)val=maxv; - } - } - void draw()override{ - DrawRectangle(pos.x,pos.y,size.x,size.y,DARKGRAY); - float t=(val-minv)/(maxv-minv); - DrawRectangle(pos.x,pos.y,size.x*t,size.y,c); - } - void exit()override{this->tinted::exit();} - }; - struct textfield :public text{ - textfield(){} - textfield(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize,std::string txt): - text(texture,txcol,color,x,y,w,h,f,fsize,txt){} - void boot()override{this->text::boot();} - void tick()override{this->text::tick();} - void draw()override{ - Vector2 p=pos; - Vector2 charsize=MeasureTextEx(font," ",fs,0); - Vector2 minsize=MeasureTextEx(font,content.c_str(),fs,charsize.x/2); - float po=charsize.x>charsize.y?charsize.x/charsize.y:charsize.y/charsize.x;po=po*5; - int minh=(minsize.y>size.y)?minsize.y:size.y; - int minw=(minsize.x>size.x)?minsize.x:size.x; - DrawRectangle(pos.x-(po/2),pos.y-(po/2),minw+(po*1.1),minh+(po*1.1),c); - DrawTextEx(font,content.c_str(),p,fs,charsize.x/2,this->txc); - } - void exit()override{this->text::exit();} - }; - struct textinput :public text{ - bool active; - int cpos; - textinput():active(false),cpos(0){} - textinput(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize):active(false),cpos(0){ - this->pos=Vector2{x,y};this->size=Vector2{x,y};this->texture=texture;this->c=color;this->font=f;this->content=""; - this->txc=txcol;this->fs=fsize; - } - void boot()override{this->text::boot();} - void tick()override{ - this->text::tick(); - Vector2 mouse=GetMousePosition(); - if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ - active=CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y}); - } - if(active){ - int key=GetCharPressed(); - while(key>0){ - if(key>=32&&key<=125){ - content+=static_cast(key); - cpos++; + void boot()override{this->tinted::boot();} + void tick()override { + this->tinted::tick(); + if(result!=content){ + result=content; + size_t initp=0; + while((initp=result.find("\n",initp))!=std::string::npos){ + result.replace(initp,1,"\\n"); + initp+=2; } - key=GetCharPressed(); - } - if(IsKeyPressed(KEY_BACKSPACE)&&content.length()>0){ - content.pop_back(); - cpos--; } } - } - void draw()override{ - this->text::draw(); - if(active)DrawRectangle(pos.x+MeasureText(content.c_str(),fs),pos.y,2,fs,{0,0,0,127}); - } - void exit()override{this->text::exit();} - }; - struct textinputfield :public textfield{ - bool active; - int cpos; - textinputfield():active(false),cpos(0){} - textinputfield(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize):active(false),cpos(0), - textfield(texture,txcol,color,x,y,w,h,f,fsize,""){} - void boot()override{this->textfield::boot();} - void tick()override{ - this->textfield::tick(); - Vector2 mouse=GetMousePosition(); - if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ - active=CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y}); + void draw()override { + Vector2 minsize=MeasureTextEx(font,content.c_str(),fs,1); + Vector2 charsize=MeasureTextEx(font," ",fs,1); + float p=charsize.x>charsize.y?charsize.x/minsize.x:charsize.y/minsize.y; + p=p*2; + int minh=(minsize.y>size.y)?minsize.y:size.y; + int minw=(minsize.x>size.x)?minsize.x:size.x; + DrawRectangle(pos.x-charsize.x,pos.y-charsize.y,minw+p,minh+p,c); + DrawTextEx(font,content.c_str(),pos,fs,1,txc); } - if(active){ - int key=GetCharPressed(); - while(key>0){ - if(key>=32&&key<=125){ - content+=static_cast(key); - cpos++; - } - key=GetCharPressed(); - } - if(IsKeyPressed(KEY_BACKSPACE)&&content.length()>0){ - content.pop_back(); - cpos--; - } - if(IsKeyPressed(KEY_ENTER)){ - content+='\n'; - cpos++; - } + void exit()override{this->tinted::exit();} + }; + struct button :virtual public tinted{ + std::function func; + bool pressed; + bool hover; + button():pressed(false){} + button(Texture2D* texture,Color color,float x,float y,float w,float h,std::function f):func(f),pressed(false){ + this->pos=Vector2{x,y};this->size=Vector2{w,h};this->texture=texture;this->c=color; } - } - void draw()override{ - this->textfield::draw(); - if(active){ - Vector2 p=pos; - float lh=fs+2; - std::string line=""; - for(char ch:content){ - if(ch=='\n'){ - p.y+=lh; - line=""; + void boot()override{this->tinted::boot();} + void tick()override{ + this->tinted::tick(); + Vector2 mouse=GetMousePosition(); + if(CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y})){hover=true; + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ + pressed=true; + if(func)func(); }else{ - line+=ch; + pressed=false; + } + }else{ + hover=false; + } + } + void draw()override { + if(this->texture!=nullptr)DrawTexture(*texture,pos.x,pos.y,c); + else DrawRectangle(pos.x,pos.y,size.x,size.y,c); + } + void exit()override{this->tinted::exit();} + }; + struct labeledbutton :virtual public button { + std::string label; + Font font; + int fs; + Color txc; + labeledbutton(std::string name,Texture2D* texture,Color color,Color text, + float x,float y,float w,float h,std::function f, + Font fnt,int size):font(fnt),fs(size),txc(text){ + this->pos=Vector2{x,y};this->size=Vector2{w,h};this->texture=texture;this->c=color; + this->func=f;this->pressed=false; + this->label=name; + } + void boot()override{this->button::boot();} + void tick()override{this->button::tick();} + void draw()override{ + this->button::draw(); + Vector2 tsize=MeasureTextEx(font,label.c_str(),fs,1); + Vector2 tpos={ + pos.x+(size.x-tsize.x)/2, + pos.y+(size.y-tsize.y)/2 + }; + DrawTextEx(font,label.c_str(),tpos,fs,1,txc); + } + void exit()override{this->button::exit();} + }; + struct slider :virtual public tinted{ + float val; + float minv; + float maxv; + slider():val(0),minv(0),maxv(1){} + slider(Texture2D* texture,Color color,float x,float y,float w,float h,float min,float max,float v):val(v),minv(min),maxv(max){ + this->pos=Vector2{x,y};this->size=Vector2{x,y};this->texture=texture;this->c=color; + } + void boot()override{this->tinted::boot();} + void tick()override{ + this->tinted::tick(); + Vector2 mouse=GetMousePosition(); + if(CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y})&&IsMouseButtonDown(MOUSE_LEFT_BUTTON)){ + float t=(mouse.x-pos.x)/size.x; + val=minv+t*(maxv-minv); + if(valmaxv)val=maxv; + } + } + void draw()override{ + DrawRectangle(pos.x,pos.y,size.x,size.y,DARKGRAY); + float t=(val-minv)/(maxv-minv); + DrawRectangle(pos.x,pos.y,size.x*t,size.y,c); + } + void exit()override{this->tinted::exit();} + }; + struct textfield :public text{ + textfield(){} + textfield(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize,std::string txt): + text(texture,txcol,color,x,y,w,h,f,fsize,txt){} + void boot()override{this->text::boot();} + void tick()override{this->text::tick();} + void draw()override{ + Vector2 p=pos; + Vector2 charsize=MeasureTextEx(font," ",fs,0); + Vector2 minsize=MeasureTextEx(font,content.c_str(),fs,charsize.x/2); + float po=charsize.x>charsize.y?charsize.x/charsize.y:charsize.y/charsize.x;po=po*5; + int minh=(minsize.y>size.y)?minsize.y:size.y; + int minw=(minsize.x>size.x)?minsize.x:size.x; + DrawRectangle(pos.x-(po/2),pos.y-(po/2),minw+(po*1.1),minh+(po*1.1),c); + DrawTextEx(font,content.c_str(),p,fs,charsize.x/2,this->txc); + } + void exit()override{this->text::exit();} + }; + struct textinput :public text{ + bool active; + int cpos; + textinput():active(false),cpos(0){} + textinput(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize):active(false),cpos(0){ + this->pos=Vector2{x,y};this->size=Vector2{x,y};this->texture=texture;this->c=color;this->font=f;this->content=""; + this->txc=txcol;this->fs=fsize; + } + void boot()override{this->text::boot();} + void tick()override{ + this->text::tick(); + Vector2 mouse=GetMousePosition(); + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ + active=CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y}); + } + if(active){ + int key=GetCharPressed(); + while(key>0){ + if(key>=32&&key<=125){ + content+=static_cast(key); + cpos++; + } + key=GetCharPressed(); + } + if(IsKeyPressed(KEY_BACKSPACE)&&content.length()>0){ + content.pop_back(); + cpos--; } } - DrawRectangle(p.x+MeasureText(line.c_str(),fs),p.y,2,fs,BLACK); } - } - void exit()override{this->textfield::exit();} - }; + void draw()override{ + this->text::draw(); + if(active)DrawRectangle(pos.x+MeasureText(content.c_str(),fs),pos.y,2,fs,{0,0,0,127}); + } + void exit()override{this->text::exit();} + }; + struct textinputfield :public textfield{ + bool active; + int cpos; + textinputfield():active(false),cpos(0){} + textinputfield(Texture2D* texture,Color txcol,Color color,float x,float y,float w,float h,Font f,float fsize):active(false),cpos(0), + textfield(texture,txcol,color,x,y,w,h,f,fsize,""){} + void boot()override{this->textfield::boot();} + void tick()override{ + this->textfield::tick(); + Vector2 mouse=GetMousePosition(); + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ + active=CheckCollisionPointRec(mouse,{pos.x,pos.y,size.x,size.y}); + } + if(active){ + int key=GetCharPressed(); + while(key>0){ + if(key>=32&&key<=125){ + content+=static_cast(key); + cpos++; + } + key=GetCharPressed(); + } + if(IsKeyPressed(KEY_BACKSPACE)&&content.length()>0){ + content.pop_back(); + cpos--; + } + if(IsKeyPressed(KEY_ENTER)){ + content+='\n'; + cpos++; + } + } + } + void draw()override{ + this->textfield::draw(); + if(active){ + Vector2 p=pos; + float lh=fs+2; + std::string line=""; + for(char ch:content){ + if(ch=='\n'){ + p.y+=lh; + line=""; + }else{ + line+=ch; + } + } + DrawRectangle(p.x+MeasureText(line.c_str(),fs),p.y,2,fs,BLACK); + } + } + void exit()override{this->textfield::exit();} + }; + } } \ No newline at end of file diff --git a/engine/src/scenes/node2drelative.h b/engine/src/scenes/node2drelative.h new file mode 100644 index 0000000..7b9c80c --- /dev/null +++ b/engine/src/scenes/node2drelative.h @@ -0,0 +1,362 @@ +#pragma once +#pragma once +#include + +#include "nodes.h" + +namespace enginend{ + namespace nodes{ + namespace relative { + struct node2d :public node { + double x; + double y; + double w; + double h; + node2d(){x=0;y=0;w=0;h=0;} + node2d(double x,double y,double w=0,double h=0):x(x),y(y),w(w),h(h){} + }; + struct rect :virtual public node2d{ + rect(){} + rect(double x,double y,double w,double h):node2d(x,y,w,h){} + }; + struct textured :virtual public rect{ + Texture2D* texture; + textured(){texture=nullptr;} + textured(Texture2D* texture,double x,double y,double w,double h):texture(texture),rect(x,y,w,h){} + void draw()override{ + if(texture==nullptr)return; + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float aw=w*sw; + float ah=h*sh; + DrawTexturePro(*texture,{0,0,(float)texture->width,(float)texture->height},{ax,ay,aw,ah},{0,0},0,WHITE); + } + void exit()override { + UnloadTexture(*texture); + delete texture; + } + }; + struct animated :virtual public textured{ + Image animimage; + int frames; + int currentframe; + int framedelay; + int framecounter; + unsigned int nextframeoffset; + animated():frames(0),currentframe(0),framedelay(6),framecounter(0),nextframeoffset(0){ + animimage.data=nullptr; + } + void boot()override{} + animated(const char* gifpath,double x,double y,double w,double h,int delay=6): + textured(nullptr,x,y,w,h),framedelay(delay),currentframe(0),framecounter(0),frames(0),nextframeoffset(0) + { + animimage=LoadImageAnim(gifpath,&frames); + if(frames>0){ + texture=new Texture2D(LoadTextureFromImage(animimage)); + } + } + void tick()override{ + if(frames<=1)return; + framecounter++; + if(framecounter>=framedelay){ + framecounter=0; + currentframe++; + if(currentframe>=frames)currentframe=0; + nextframeoffset=animimage.width*animimage.height*4*currentframe; + UpdateTexture(*texture,((unsigned char*)animimage.data)+nextframeoffset); + } + } + void draw()override { + textured::draw(); + } + void exit(){ + if(animimage.data)UnloadImage(animimage); + textured::exit(); + } + }; + struct colored :virtual public rect{ + Color c; + colored(){} + colored(Color color,double x,double y,double w,double h):c(color),rect(x,y,w,h){} + void draw()override{ + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float aw=w*sw; + float ah=h*sh; + DrawRectangle(ax,ay,aw,ah,c); + } + }; + struct tinted :virtual public colored,virtual public textured{ + tinted(){} + tinted(Texture2D* texture,Color color,double x,double y,double w,double h): + node2d(x,y,w,h), + rect(x,y,w,h), + colored(color,x,y,w,h), + textured(texture,x,y,w,h) + {} + void draw()override{ + if(texture==nullptr)return; + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float aw=w*sw; + float ah=h*sh; + DrawTexturePro(*texture,{0,0,(float)texture->width,(float)texture->height},{ax,ay,aw,ah},{0,0},0,c); + } + }; + struct text :public tinted { + protected: + std::string result; + public: + Font font; + float fs; + Color txc; + std::string content; + text(){fs=20;} + text(Texture2D* texture,Color txcol,Color color,double x,double y,double w,double h,Font f,float fsize,std::string txt): + tinted(texture,color,x,y,w,h), + font(f),fs(fsize),content(txt),txc(txcol) + { + result=content; + size_t initp=0; + while((initp=result.find("\n",initp))!=std::string::npos){ + result.replace(initp,1,"\\n"); + initp+=2; + } + } + void tick()override { + tinted::tick(); + if(result!=content){ + result=content; + size_t initp=0; + while((initp=result.find("\n",initp))!=std::string::npos){ + result.replace(initp,1,"\\n"); + initp+=2; + } + } + } + void draw()override { + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float aw=w*sw; + float ah=h*sh; + Vector2 minsize=MeasureTextEx(font,content.c_str(),fs,1); + Vector2 charsize=MeasureTextEx(font," ",fs,1); + float p=charsize.x>charsize.y?charsize.x/minsize.x:charsize.y/minsize.y; + p=p*2; + int minh=(minsize.y>ah)?minsize.y:ah; + int minw=(minsize.x>aw)?minsize.x:aw; + DrawRectangle(ax-charsize.x,ay-charsize.y,minw+p,minh+p,c); + DrawTextEx(font,content.c_str(),{ax,ay},fs,1,txc); + } + }; + struct button :virtual public tinted{ + void(*func)(); + bool pressed; + bool hover; + button():func(nullptr),pressed(false){} + button(Texture2D* texture,Color color,double x,double y,double w,double h,void(*f)()):func(f),pressed(false),tinted(texture,color,x,y,w,h){} + void tick()override{ + tinted::tick(); + Vector2 mouse=GetMousePosition(); + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + Rectangle r={float(x*sw),float(y*sh),float(w*sw),float(h*sh)}; + if(CheckCollisionPointRec(mouse,r)){hover=true; + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ + pressed=true; + if(func)func(); + }else{ + pressed=false; + } + }else{ + hover=false; + } + } + void draw()override { + tinted::draw(); + } + }; + struct labeledbutton :virtual public button { + std::string label; + Font font; + int fs; + Color txc; + labeledbutton(std::string name,Texture2D* texture,Color color,Color text, + double x,double y,double w,double h,void(*f)(), + Font fnt,int size):font(fnt),fs(size),txc(text),label(name), + button(texture,color,x,y,w,h,f) + {} + void draw()override{ + button::draw(); + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float aw=w*sw; + float ah=h*sh; + Vector2 tsize=MeasureTextEx(font,label.c_str(),fs,1); + Vector2 tpos={ + ax+(aw-tsize.x)/2, + ay+(ah-tsize.y)/2 + }; + DrawTextEx(font,label.c_str(),tpos,fs,1,txc); + } + }; + struct slider :virtual public tinted{ + float val; + float minv; + float maxv; + slider():val(0),minv(0),maxv(1){} + slider(Texture2D* texture,Color color,double x,double y,double w,double h,float min,float max,float v):val(v),minv(min),maxv(max),tinted(texture,color,x,y,w,h){} + void tick()override{ + tinted::tick(); + Vector2 mouse=GetMousePosition(); + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + Rectangle r={float(x*sw),float(y*sh),float(w*sw),float(h*sh)}; + if(CheckCollisionPointRec(mouse,r)&&IsMouseButtonDown(MOUSE_LEFT_BUTTON)){ + float t=(mouse.x-(x*sw))/(w*sw); + val=minv+t*(maxv-minv); + if(valmaxv)val=maxv; + } + } + void draw()override{ + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float aw=w*sw; + float ah=h*sh; + DrawRectangle(ax,ay,aw,ah,DARKGRAY); + float t=(val-minv)/(maxv-minv); + DrawRectangle(ax,ay,aw*t,ah,c); + } + }; + struct textfield :public text{ + textfield(){} + textfield(Texture2D* texture,Color txcol,Color color,double x,double y,double w,double h,Font f,float fsize,std::string txt): + text(texture,txcol,color,x,y,w,h,f,fsize,txt){} + void draw()override{ + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float aw=w*sw; + float ah=h*sh; + Vector2 charsize=MeasureTextEx(font," ",fs,0); + Vector2 minsize=MeasureTextEx(font,content.c_str(),fs,charsize.x/2); + float po=charsize.x>charsize.y?charsize.x/charsize.y:charsize.y/charsize.x;po=po*5; + int minh=(minsize.y>ah)?minsize.y:ah; + int minw=(minsize.x>aw)?minsize.x:aw; + DrawRectangle(ax-(po/2),ay-(po/2),minw+(po*1.1),minh+(po*1.1),c); + DrawTextEx(font,content.c_str(),{ax,ay},fs,charsize.x/2,txc); + } + }; + struct textinput :public text{ + bool active; + int cpos; + textinput():active(false),cpos(0){} + textinput(Texture2D* texture,Color txcol,Color color,double x,double y,double w,double h,Font f,float fsize):active(false),cpos(0), + text(texture,txcol,color,x,y,w,h,f,fsize,""){} + void tick()override{ + text::tick(); + Vector2 mouse=GetMousePosition(); + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + Rectangle r={float(x*sw),float(y*sh),float(w*sw),float(h*sh)}; + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ + active=CheckCollisionPointRec(mouse,r); + } + if(active){ + int key=GetCharPressed(); + while(key>0){ + if(key>=32&&key<=125){ + content+=static_cast(key); + cpos++; + } + key=GetCharPressed(); + } + if(IsKeyPressed(KEY_BACKSPACE)&&content.length()>0){ + content.pop_back(); + cpos--; + } + } + } + void draw()override{ + text::draw(); + if(active){ + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + DrawRectangle(ax+MeasureTextEx(font,content.c_str(),fs,1).x,ay,2,fs,{0,0,0,127}); + } + } + }; + struct textinputfield :public textfield{ + bool active; + int cpos; + textinputfield():active(false),cpos(0){} + textinputfield(Texture2D* texture,Color txcol,Color color,double x,double y,double w,double h,Font f,float fsize):active(false),cpos(0), + textfield(texture,txcol,color,x,y,w,h,f,fsize,""){} + void tick()override{ + textfield::tick(); + Vector2 mouse=GetMousePosition(); + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + Rectangle r={float(x*sw),float(y*sh),float(w*sw),float(h*sh)}; + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ + active=CheckCollisionPointRec(mouse,r); + } + if(active){ + int key=GetCharPressed(); + while(key>0){ + if(key>=32&&key<=125){ + content+=static_cast(key); + cpos++; + } + key=GetCharPressed(); + } + if(IsKeyPressed(KEY_BACKSPACE)&&content.length()>0){ + content.pop_back(); + cpos--; + } + if(IsKeyPressed(KEY_ENTER)){ + content+='\n'; + cpos++; + } + } + } + void draw()override{ + textfield::draw(); + if(active){ + float sw=GetScreenWidth(); + float sh=GetScreenHeight(); + float ax=x*sw; + float ay=y*sh; + float lh=fs+2; + Vector2 p={ax,ay}; + std::string line=""; + for(char ch:content){ + if(ch=='\n'){ + p.y+=lh; + line=""; + }else{ + line+=ch; + } + } + DrawRectangle(p.x+MeasureTextEx(font,line.c_str(),fs,1).x,p.y,2,fs,BLACK); + } + } + }; + } + }} \ No newline at end of file diff --git a/engine/src/scenes/nodes.h b/engine/src/scenes/nodes.h index 2def91f..55693ac 100644 --- a/engine/src/scenes/nodes.h +++ b/engine/src/scenes/nodes.h @@ -4,13 +4,15 @@ #include "../net.h" #include -namespace enginend { - struct node{ - public: + namespace enginend { +namespace nodes { + struct node{ + public: - virtual void boot()=0; - virtual void tick()=0; - virtual void draw()=0; - virtual void exit()=0; - }; + virtual void boot()=0; + virtual void tick()=0; + virtual void draw()=0; + virtual void exit()=0; + }; + } } \ No newline at end of file diff --git a/engine/src/scenes/scene.h b/engine/src/scenes/scene.h index 35a24ea..117f970 100644 --- a/engine/src/scenes/scene.h +++ b/engine/src/scenes/scene.h @@ -1,14 +1,16 @@ +#pragma once + #include "nodes.h" #include namespace enginend { struct scene{ - std::list nodes; + std::list nodes; virtual void boot() { int i=0; tiny::echo((char*)"initializing scene"); - for (enginend::node* n : nodes) { + for (enginend::nodes::node* n : nodes) { tiny::echo((char*)"initializing object of ID: %i",i++); n->boot(); } @@ -17,18 +19,18 @@ namespace enginend { ClearBackground(BLANK); BeginDrawing(); - for (enginend::node* n : nodes) { + for (enginend::nodes::node* n : nodes) { n->draw(); } EndDrawing(); } virtual void tick() { - for (enginend::node* n : nodes) { + for (enginend::nodes::node* n : nodes) { n->tick(); } } virtual void exit() { - for (enginend::node* n : nodes) { + for (enginend::nodes::node* n : nodes) { n->exit(); } } diff --git a/engine/test.cpp b/engine/test.cpp index 3f9fed2..074db2e 100644 --- a/engine/test.cpp +++ b/engine/test.cpp @@ -14,13 +14,13 @@ public: InitWindow(500,500,"test"); SetTargetFPS(GetMonitorRefreshRate(GetCurrentMonitor())); this->tickrate=GetMonitorRefreshRate(GetCurrentMonitor()); - s.nodes=std::list{ + s.nodes=std::list{ - new colored(Color{255,255,255,255},0,0,500,500), - new textfield(nullptr,Color{255,127,127,255},Color{127,127,127,255} - ,100,100,220,32,GetFontDefault(),32, - "welcome to enginend!\n" - "hehe" + new nodes::colored(Color{255,255,255,255},0,0,500,500), + new nodes::textfield(nullptr,Color{255,127,127,255},Color{127,127,127,255} + ,100,100,220,32,GetFontDefault(),32, + "welcome to enginend!\n" + "hehe" ) }; s.boot(); diff --git a/games/endlauncher/src/main.cpp b/games/endlauncher/src/main.cpp index 194c887..3b5f24d 100644 --- a/games/endlauncher/src/main.cpp +++ b/games/endlauncher/src/main.cpp @@ -7,7 +7,7 @@ #include using namespace enginend; - +using namespace enginend::nodes; netio nete{}; /* @@ -111,7 +111,6 @@ public: Texture2D buttonslabel[8]; Font gamename,changelog,information; bool vsync=true; - scene s; RenderTexture2D target; text version; std::string selectedversion=""; @@ -169,7 +168,7 @@ public: playbtn[0]=LoadTexture("res/playoff.png"); playbtn[1]=LoadTexture("res/playon.png"); playbutton= new button(&playbtn[0], {255,255,255,255},406,(18*11)+17+9,153,59,std::function(playbuttonfunc)); - s.nodes=std::list{ + currentscene->nodes=std::list{ new background(&bg,0,0,600,300), new textured(&buttonfore,3,36,62,62), new textured(&buttonlock,3,36+((62+4)*1),62,62), @@ -189,7 +188,7 @@ public: new text(nullptr,Color{255,255,255,255},Color{0,0,0,0},96+16,(16*14)-3,1,1,information,20,"downloaded verified"), &version, }; - s.boot(); + currentscene->boot(); } int buttondelay=0; void tick() override { @@ -234,14 +233,14 @@ public: } } } - s.tick(); + currentscene->tick(); buttondelay--; } bool changedmenu=true; bool itemchanged=true; void draw() override { BeginTextureMode(target); - s.draw(); + currentscene->draw(); EndTextureMode(); BeginDrawing(); ClearBackground(BLANK); @@ -267,7 +266,7 @@ public: } } void exit() override { - s.exit(); + currentscene->exit(); } }; diff --git a/games/forespend/src/client/client.cpp b/games/forespend/src/client/client.cpp index 4816e67..00559cb 100644 --- a/games/forespend/src/client/client.cpp +++ b/games/forespend/src/client/client.cpp @@ -1,9 +1,35 @@ #include "client.h" -client::client(){} -void client::boot() {} -void client::draw() {} -void client::exit() {} -void client::tick() {} + +#include "scenes/mainmenu.h" + +client::client() { + +} +void client::boot() { + this->framerate=60; + this->tickrate=20; + InitWindow(380,240,"forespend - 0.03h"); +// SetConfigFlags(); + this->currentscene=new mainmenu(); + this->currentscene->boot(); + target=LoadRenderTexture(380,240); +} +void client::draw() { + BeginTextureMode(target); + this->currentscene->draw(); + EndTextureMode(); + BeginDrawing(); + ClearBackground(WHITE); + DrawTexturePro(target.texture, {0, 0, 380,240}, {0, 0, (float)GetScreenWidth(), (float)GetScreenHeight()}, {0, 0}, 0, WHITE); + EndDrawing(); +} +void client::exit() { + this->currentscene->exit(); + delete this->currentscene; +} +void client::tick() { + this->currentscene->tick(); +} diff --git a/games/forespend/src/client/client.h b/games/forespend/src/client/client.h index a0553e5..1545dae 100644 --- a/games/forespend/src/client/client.h +++ b/games/forespend/src/client/client.h @@ -1,9 +1,10 @@ #pragma once #include -class client :public program{ +class client :public enginend::program{ public: + RenderTexture2D target; const char* CONF() final{return "client.tdf";} client(); void boot() override; diff --git a/games/forespend/src/client/scenes/game.cpp b/games/forespend/src/client/scenes/game.cpp new file mode 100644 index 0000000..679fedf --- /dev/null +++ b/games/forespend/src/client/scenes/game.cpp @@ -0,0 +1 @@ +#include "game.h" \ No newline at end of file diff --git a/games/forespend/src/client/scenes/game.h b/games/forespend/src/client/scenes/game.h new file mode 100644 index 0000000..294415b --- /dev/null +++ b/games/forespend/src/client/scenes/game.h @@ -0,0 +1,7 @@ +#pragma once +#include + + +class game :public virtual enginend::scene { + +}; \ No newline at end of file diff --git a/games/forespend/src/client/scenes/mainmenu.cpp b/games/forespend/src/client/scenes/mainmenu.cpp index 12bdeb0..968b3da 100644 --- a/games/forespend/src/client/scenes/mainmenu.cpp +++ b/games/forespend/src/client/scenes/mainmenu.cpp @@ -1 +1 @@ -#include "mainmenu.h" \ No newline at end of file +#include "mainmenu.h" diff --git a/games/forespend/src/client/scenes/mainmenu.h b/games/forespend/src/client/scenes/mainmenu.h index dee6cf5..58a02b6 100644 --- a/games/forespend/src/client/scenes/mainmenu.h +++ b/games/forespend/src/client/scenes/mainmenu.h @@ -1,6 +1,22 @@ #pragma once #include +#include -class mainmenu :public virtual scene{ - +class mainmenu :public virtual enginend::scene{ +public: + void boot() override { + this->nodes=std::list{ + new enginend::nodes::relative::animated(AT("res/images/sky.gif"),0,0,10,10,5) + }; + enginend::scene::boot(); + } + void tick() override { + enginend::scene::tick(); + } + void draw() override { + enginend::scene::draw(); + } + void exit() override { + enginend::scene::exit(); + } }; diff --git a/games/forespend/src/main.cpp b/games/forespend/src/main.cpp index 97f251a..7696e09 100644 --- a/games/forespend/src/main.cpp +++ b/games/forespend/src/main.cpp @@ -1,11 +1,57 @@ +#include #include +#include +#include "server/server.h" +#include "client/client.h" +PLATFORM platform=LINUX; +std::string androidpackage="kn.kinfuyuki.forespend"; inline const char* COMMONCONFIG(){return "common.tdf";} tiny::ErrorLevel tiny::level{6}; - int main(int argc, char** argv) { + enginend::program* game; tiny::startup("forespend","0.03g-rewrite"); + bool isserver = false; if (argc>1) { - + for (int i=1;iboot(); + std::atomic running{true}; + std::thread tickthread([game, &running]() { + double tickrate=1.0/game->tickrate; + auto lasttick=std::chrono::high_resolution_clock::now(); + + while (running) { + auto now=std::chrono::high_resolution_clock::now(); + double elapsed=std::chrono::duration_cast>(now-lasttick).count(); + + if (elapsed>=tickrate) { + game->tick(); + lasttick=now; + } else { + std::this_thread::sleep_for(std::chrono::duration(tickrate-elapsed)); + } + } + }); + + double framerate=1.0/game->framerate; + auto lastframe=std::chrono::high_resolution_clock::now(); + while (!WindowShouldClose()) { + auto now=std::chrono::high_resolution_clock::now(); + double elapsed=std::chrono::duration_cast>(now-lastframe).count(); + + if (elapsed>=framerate) { + game->draw(); + lastframe=now; + } else { + WaitTime(framerate-elapsed); + } + } + game->exit(); + return 0; } \ No newline at end of file diff --git a/games/forespend/src/server/server.h b/games/forespend/src/server/server.h index 76d1f9b..71e1c64 100644 --- a/games/forespend/src/server/server.h +++ b/games/forespend/src/server/server.h @@ -2,7 +2,7 @@ #include -class server : public program{ +class server : public enginend::program{ public: server(); const char* CONF() final{return "client.tdf";} diff --git a/include/incmgr.h b/include/incmgr.h index 9268075..41f083f 100644 --- a/include/incmgr.h +++ b/include/incmgr.h @@ -1,3 +1,4 @@ +#pragma once #include #include #include