diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/blr3.dtp | bin | 0 -> 459577 bytes | |||
-rw-r--r-- | src/core/bullet.cpp | 101 | ||||
-rw-r--r-- | src/core/bullet.hpp | 49 | ||||
-rw-r--r-- | src/core/corepublic.hpp | 26 | ||||
-rw-r--r-- | src/core/coreshared.hpp | 5 | ||||
-rw-r--r-- | src/core/fncmodules.cpp | 1 | ||||
-rw-r--r-- | src/core/fncmodules.hpp | 1 | ||||
-rw-r--r-- | src/core/fncwrapper.hpp | 1 | ||||
-rw-r--r-- | src/core/gamescene.cpp | 70 | ||||
-rw-r--r-- | src/core/laser.cpp | 1 | ||||
-rw-r--r-- | src/core/player.cpp | 40 | ||||
-rw-r--r-- | src/core/player.hpp | 21 | ||||
-rw-r--r-- | src/core/scriptshared.hpp | 150 | ||||
-rw-r--r-- | src/core/tower.cpp | 1 | ||||
-rw-r--r-- | src/core/vmrunner.cpp | 280 | ||||
-rw-r--r-- | src/core/vmrunner.hpp | 48 | ||||
-rw-r--r-- | src/main.cpp | 30 | ||||
-rw-r--r-- | src/makefile | 41 | ||||
-rw-r--r-- | src/master/init.cpp | 1 | ||||
-rw-r--r-- | src/master/intro.cpp | 202 | ||||
-rw-r--r-- | src/master/master.hpp | 64 | ||||
-rw-r--r-- | src/master/resources.cpp | 18 | ||||
-rw-r--r-- | src/master/resources.hpp | 7 | ||||
-rw-r--r-- | src/master/scenemgr.cpp | 63 | ||||
-rw-r--r-- | src/ui/mainmenu.cpp | 69 | ||||
-rw-r--r-- | src/ui/menuframework/menuclass.cpp | 115 | ||||
-rw-r--r-- | src/ui/menuframework/menuframework.hpp | 56 | ||||
-rw-r--r-- | src/ui/menus.hpp | 16 |
28 files changed, 1477 insertions, 0 deletions
diff --git a/src/blr3.dtp b/src/blr3.dtp Binary files differnew file mode 100644 index 0000000..1f62320 --- /dev/null +++ b/src/blr3.dtp diff --git a/src/core/bullet.cpp b/src/core/bullet.cpp new file mode 100644 index 0000000..175bae4 --- /dev/null +++ b/src/core/bullet.cpp @@ -0,0 +1,101 @@ +#include "bullet.hpp" +#include "../master/resources.hpp" +#include <cstdlib> +const char* bsnames[]={"green_bullet","cyan_bullet","yellow_bullet","purple_bullet", + "red_bullet","white_bullet","blue_bullet","orange_bullet", + "grey_bullet","circle_bullet"}; +void bulletBase::init(...){exist=true;renderscale=1;} +void bulletBase::update() +{ + if(!exist)return; + vel=vel+acc; + if(vel.l()>velim&&velim>0)vel=velim*vel.getNormalized(); + pos=pos-vel; + if(!extborder&&(pos.x<-10||pos.y<-10||pos.x>810||pos.y>610))exist=false; + //check clr & collision +} +void bulletBase::render() +{ + //test view mode + bmInstance->getBulEntity2D(basecolor)->setColor(0xC0FFFFFF); + bmInstance->getBulEntity2D(basecolor)->render(pos.x,pos.y,0,renderscale*0.6); +} +bulletBase::~bulletBase(){} + +void bulletBonus::update() +{ + //the player is not implemented yet... +} + +void bulletManager::init() +{ + alloced=used=0; + for(int i=0;i<(int)COLOR_COUNT;++i) + { + bulent2d[i]=new smEntity2D(ssanm.getTextureInfo(bsnames[i])->tex,ssanm.getTextureInfo(bsnames[i])->rect); + bulent3d[i]=new smEntity3D(ssanm.getTextureInfo(bsnames[i])->tex,ssanm.getTextureInfo(bsnames[i])->rect); + } +} +void bulletManager::deinit() +{ + if(alloced){for(int i=0;i<alloced;++i)delete bullets[i];alloced=used=0;} + for(int i=0;i<(int)COLOR_COUNT;++i) + {delete bulent2d[i];delete bulent3d[i];} +} +template<class T> +int bulletManager::allocBullet() +{ + if(!alloced) + { + alloced=1; + bullets[0]=new T; + return 0; + } + else + { + int i; + for(i=0;i<alloced;++i) + if(!bullets[i]->exist)break; + if(i==alloced) + bullets[alloced++]=new T; + return i; + } + return -1; +} +template<class T> +int bulletManager::createBullet() +{ + //stub... + int ptr=allocBullet<T>(); + bullets[ptr]->init(); + return ptr; +} +void bulletManager::updateBullet() +{ + static int b=0; + ++b; + if(b>15) + { + int a=createBullet<bulletBase>(); + bulletBase* x=getHandle(a); + x->pos=smvec2d(400,300); + x->vel=smvec2d(rand()%100-50,rand()%100-50); + x->vel.normalize(); + b=0; + } + for(int i=0;i<alloced;++i) + if(bullets[i]->exist) + bullets[i]->update(); +} +void bulletManager::renderBullet() +{ + for(int i=0;i<alloced;++i) + if(bullets[i]->exist) + { + bullets[i]->render(); + } +} +smEntity2D* bulletManager::getBulEntity2D(TColors col){return bulent2d[col];} +smEntity3D* bulletManager::getBulEntity3D(TColors col){return bulent3d[col];} +bulletBase* bulletManager::getHandle(int id){if(id<alloced)return bullets[id];else return NULL;} +bulletManager *bmInstance; diff --git a/src/core/bullet.hpp b/src/core/bullet.hpp new file mode 100644 index 0000000..5f4fe2f --- /dev/null +++ b/src/core/bullet.hpp @@ -0,0 +1,49 @@ +#ifndef BULLET_H +#define BULLET_H +#include "smmath.hpp" +#include "smentity.hpp" +#include "coreshared.hpp" +class bulletBase +{ +public: + smvec2d pos,vel,acc; + float velim; + //velim: velocity scalar limit. + float collrange,scollrange,renderscale; + //collision range and semi-collision range. Replacing "collable" and "scollable". + bool extborder,invincible; + //extborder: true=not removed if out of screen. + //invincible: true=not removed if collided with player or in range of CLR. + bool exist,addblend; + int attrd[8]; + float attrf[8]; + TColors basecolor; + virtual void init(...); + virtual void update(); + virtual void render(); + virtual ~bulletBase(); +}; +class bulletBonus:public bulletBase +{ + void update()override; +}; +class bulletManager +{ +private: + bulletBase* bullets[10240]; + int alloced,used; + smEntity2D* bulent2d[COLOR_COUNT]; + smEntity3D* bulent3d[COLOR_COUNT]; +public: + void init(); + void deinit(); + template<class T>int allocBullet(); + template<class T>int createBullet(); + void updateBullet(); + void renderBullet(); + bulletBase* getHandle(int id); + smEntity2D* getBulEntity2D(TColors col); + smEntity3D* getBulEntity3D(TColors col); +}; +extern bulletManager *bmInstance; +#endif diff --git a/src/core/corepublic.hpp b/src/core/corepublic.hpp new file mode 100644 index 0000000..fb06073 --- /dev/null +++ b/src/core/corepublic.hpp @@ -0,0 +1,26 @@ +#ifndef COREPUBLIC_H +#define COREPUBLIC_H +#include "smelt.hpp" +#include "smttfont.hpp" +#include "bullet.hpp" +#include "player.hpp" +#include "../master/master.hpp" +class gameScene:public scenePrototype +{ +private: + bool tpmode; + static SMELT *sm; + SMTRG rtarget; + smQuad tgquad; + smTTFont ttfont; + float udly; + int utime; +public: + gameScene(); + ~gameScene(); + bool sceneUpdate()override; + bool sceneRender()override; + bool threadUpdate()override; +}; +extern gameScene* gameScn; +#endif diff --git a/src/core/coreshared.hpp b/src/core/coreshared.hpp new file mode 100644 index 0000000..7c49afd --- /dev/null +++ b/src/core/coreshared.hpp @@ -0,0 +1,5 @@ +#ifndef CORESHARED_H +#define CORESHARED_H +enum TColors +{green=0,cyan,yellow,purple,red,white,blue,orange,grey,circle,COLOR_COUNT}; +#endif diff --git a/src/core/fncmodules.cpp b/src/core/fncmodules.cpp new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/src/core/fncmodules.cpp @@ -0,0 +1 @@ + diff --git a/src/core/fncmodules.hpp b/src/core/fncmodules.hpp new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/src/core/fncmodules.hpp @@ -0,0 +1 @@ + diff --git a/src/core/fncwrapper.hpp b/src/core/fncwrapper.hpp new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/src/core/fncwrapper.hpp @@ -0,0 +1 @@ + diff --git a/src/core/gamescene.cpp b/src/core/gamescene.cpp new file mode 100644 index 0000000..3bda53f --- /dev/null +++ b/src/core/gamescene.cpp @@ -0,0 +1,70 @@ +#include "../master/master.hpp" +#include "../master/resources.hpp" +#include "corepublic.hpp" +#include "bullet.hpp" +#include "player.hpp" +SMELT* gameScene::sm=NULL; +gameScene::gameScene() +{ + sm=smGetInterface(SMELT_APILEVEL); + rtarget=sm->smTargetCreate(800,600); + tgquad.tex=sm->smTargetTexture(rtarget); + tgquad.blend=BLEND_ALPHABLEND; + tgquad.v[0].x=190;tgquad.v[0].y=75; + tgquad.v[1].x=950;tgquad.v[1].y=75; + tgquad.v[2].x=950;tgquad.v[2].y=645; + tgquad.v[3].x=190;tgquad.v[3].y=645; + for(int i=0;i<4;++i)tgquad.v[i].z=0.5,tgquad.v[i].col=0xFFFFFFFF; + int rw=sm->smTextureGetWidth(tgquad.tex); + int rh=sm->smTextureGetHeight(tgquad.tex); + tgquad.v[0].tx=0;tgquad.v[0].ty=0; + tgquad.v[1].tx=800./rw;tgquad.v[1].ty=0; + tgquad.v[2].tx=800./rw;tgquad.v[2].ty=600./rh; + tgquad.v[3].tx=0;tgquad.v[3].ty=600./rh; + bmInstance=new bulletManager; + player=new playerBase; + utime=0; + ttfont.loadTTFFromMemory(blrdtp.getFilePtr("FreeMono.ttf"),blrdtp.getFileSize("FreeMono.ttf"),12); + bmInstance->init(); +} +gameScene::~gameScene() +{ + bmInstance->deinit(); + delete bmInstance; + delete player; + bmInstance=NULL; + ttfont.releaseTTF(); + sm->smTargetFree(rtarget); + sm->smRelease(); +} +bool gameScene::sceneUpdate() +{ + sm->smRenderBegin2D(true,rtarget); + sm->smClrscr(0xFF000000); + bmInstance->renderBullet(); + player->render(); + sm->smRenderEnd(); + return false; +} +bool gameScene::sceneRender() +{ + sm->smClrscr(0xFF000080); + sm->smRenderQuad(&tgquad); + udly+=sm->smGetDelta(); + extern sceneManager *sceneMgr;float lps=sceneMgr->getLPS(); + if(udly>1){udly=0;utime=sceneMgr->getTHUpdateTime();} + ttfont.updateString(L"LPS: %.2f",lps); + ttfont.render(0,680,0xFFFFFFFF,ALIGN_LEFT); + ttfont.updateString(L"Update Time: %dns",utime); + ttfont.render(0,695,0xFFFFFFFF,ALIGN_LEFT); + ttfont.updateString(L"FPS: %.2f",sm->smGetFPS()); + ttfont.render(0,710,0xFFFFFFFF,ALIGN_LEFT); + return false; +} +bool gameScene::threadUpdate() +{ + bmInstance->updateBullet(); + player->update(); + return false; +} +gameScene* gameScn; diff --git a/src/core/laser.cpp b/src/core/laser.cpp new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/src/core/laser.cpp @@ -0,0 +1 @@ + diff --git a/src/core/player.cpp b/src/core/player.cpp new file mode 100644 index 0000000..3407a0c --- /dev/null +++ b/src/core/player.cpp @@ -0,0 +1,40 @@ +#include "smelt.hpp" +#include "player.hpp" +#include "../master/resources.hpp" +SMELT* playerBase::sm=NULL; +playerBase::playerBase(float _x,float _y) +{ + sm=smGetInterface(SMELT_APILEVEL); + playerent=new smEntity2D(ssanm.getTextureInfo("player")->tex,ssanm.getTextureInfo("player")->rect); + playerent->setCentre(12,12); + pos.x=_x;pos.y=_y; + plyrctl[0]=SMK_UP;plyrctl[1]=SMK_DOWN; + plyrctl[2]=SMK_LEFT;plyrctl[3]=SMK_RIGHT; + plyrctl[4]=SMK_SHIFT; + rot=0; +} +playerBase::~playerBase() +{ + delete playerent;sm->smRelease(); +} +void playerBase::update() +{ + //player control... + static float realspeed=0; + if(sm->smGetKeyState(plyrctl[4])) + realspeed=0.85;else realspeed=3.5; + if(sm->smGetKeyState(plyrctl[0])) + {if(pos.y>15)pos.y-=realspeed;else pos.y=15;} + if(sm->smGetKeyState(plyrctl[1])) + {if(pos.y<585)pos.y+=realspeed;else pos.y=585;} + if(sm->smGetKeyState(plyrctl[2])) + {if(pos.x>15)pos.x-=realspeed;else pos.x=15;} + if(sm->smGetKeyState(plyrctl[3])) + {if(pos.x<785)pos.x+=realspeed;else pos.x=785;} + rot+=17./1800.*PI; +} +void playerBase::render() +{ + playerent->render(pos.x,pos.y,rot,0.7); +} +playerBase* player; diff --git a/src/core/player.hpp b/src/core/player.hpp new file mode 100644 index 0000000..408c174 --- /dev/null +++ b/src/core/player.hpp @@ -0,0 +1,21 @@ +#ifndef PLAYER_H +#define PLAYER_H +#include "smmath.hpp" +#include "smentity.hpp" +class playerBase +{ +private: + smEntity2D* playerent; + static SMELT* sm; +public: + smvec2d pos; + float rot,vel,velp; + int plyrctl[6]; + + playerBase(float _x=400,float _y=400); + ~playerBase(); + void update(); + void render(); +}; +extern playerBase* player; +#endif diff --git a/src/core/scriptshared.hpp b/src/core/scriptshared.hpp new file mode 100644 index 0000000..01d423a --- /dev/null +++ b/src/core/scriptshared.hpp @@ -0,0 +1,150 @@ +#ifndef SCRIPTSHARED_H +#define SCRIPTSHARED_H +#include <cmath> +#define eps 1e-6 +typedef union _Udata{//data union + int i;float r;unsigned long d; + _Udata(){d=0;} +}Udata; +typedef struct _Idata{//data union, with type tag and operators + _Udata D; + int type;//0=int, 1=float + _Idata(){D.d=0;type=0;} + _Idata(int _type,int _data) + {type=_type;if(type==0)D.i=_data;else D.r=(float)_data;} + float &r(){return D.r;} + int &i(){return D.i;} + unsigned long &d(){return D.d;} + _Idata operator =(_Idata r) + { + if(type==1&&r.type==0)this->r()=(float)r.i(); + else if(type==0&&r.type==1)this->i()=(int)r.r(); + else this->d()=r.d(); + return *this; + } + _Idata operator +=(_Idata r) + { + if(type==1&&r.type==0)this->r()+=(float)r.i(); + if(type==0&&r.type==1)this->i()+=(int)r.r(); + if(type==0&&r.type==0)this->i()+=r.i(); + if(type==1&&r.type==1)this->r()+=r.r(); + return *this; + } + _Idata operator -=(_Idata r) + { + if(type==1&&r.type==0)this->r()-=(float)r.i(); + if(type==0&&r.type==1)this->i()-=(int)r.r(); + if(type==0&&r.type==0)this->i()-=r.i(); + if(type==1&&r.type==1)this->r()-=r.r(); + return *this; + } + _Idata operator *=(_Idata r) + { + if(type==1&&r.type==0)this->r()*=(float)r.i(); + if(type==0&&r.type==1)this->i()*=(int)r.r(); + if(type==0&&r.type==0)this->i()*=r.i(); + if(type==1&&r.type==1)this->r()*=r.r(); + return *this; + } + _Idata operator /=(_Idata r) + { + if(type==1&&r.type==0)this->r()/=(float)r.i(); + if(type==0&&r.type==1)this->i()/=(int)r.r(); + if(type==0&&r.type==0)this->i()/=r.i(); + if(type==1&&r.type==1)this->r()/=r.r(); + return *this; + } + _Idata operator %=(_Idata r) + { + if(type==1&&r.type==0)throw; + if(type==0&&r.type==1)throw; + if(type==0&&r.type==0)this->i()%=r.i(); + if(type==1&&r.type==1)throw; + return *this; + } + _Idata operator &=(_Idata r) + { + if(type==1&&r.type==0)throw; + if(type==0&&r.type==1)throw; + if(type==0&&r.type==0)this->i()&=r.i(); + if(type==1&&r.type==1)throw; + return *this; + } + _Idata operator |=(_Idata r) + { + if(type==1&&r.type==0)throw; + if(type==0&&r.type==1)throw; + if(type==0&&r.type==0)this->i()|=r.i(); + if(type==1&&r.type==1)throw; + return *this; + } + _Idata operator ^=(_Idata r) + { + if(type==1&&r.type==0)throw; + if(type==0&&r.type==1)throw; + if(type==0&&r.type==0)this->i()^=r.i(); + if(type==1&&r.type==1)throw; + return *this; + } + _Idata operator ~() + { + if(type==1)throw; + if(type==0)i()=~i(); + return *this; + } + _Idata operator ++() + { + if(type==1)throw; + if(type==0)i()=i()+1; + return *this; + } + _Idata operator --() + { + if(type==1)throw; + if(type==0)i()=i()-1; + return *this; + } + bool ltz() + { + if(type==0)return i()<0; + if(type==1)return fabs(r())>eps&&r()<0; + throw; + } + bool elz() + { + if(type==0)return i()<=0; + if(type==1)return fabs(r())<eps||(fabs(r())>eps&&r()<0); + throw; + } + bool gtz() + { + if(type==0)return i()>0; + if(type==1)return fabs(r())>eps&&r()>0; + throw; + } + bool egz() + { + if(type==0)return i()>=0; + if(type==1)return fabs(r())<eps||(fabs(r())>eps&&r()>0); + throw; + } + bool eqz() + { + if(type==0)return i()==0; + if(type==1)return fabs(r())<eps; + throw; + } + bool nez() + { + if(type==0)return i()!=0; + if(type==1)return fabs(r())>eps; + throw; + } +}Idata; +typedef struct _SPara{Udata data;int type;char *fnc;}SPara;//parameters +typedef struct _SInst//instructions +{ + int id; + SPara para1,para2; +}SInst; +#endif diff --git a/src/core/tower.cpp b/src/core/tower.cpp new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/src/core/tower.cpp @@ -0,0 +1 @@ + diff --git a/src/core/vmrunner.cpp b/src/core/vmrunner.cpp new file mode 100644 index 0000000..1942d74 --- /dev/null +++ b/src/core/vmrunner.cpp @@ -0,0 +1,280 @@ +#include "vmrunner.hpp" +#include "coreshared.hpp" +#include <cstdlib> +unsigned getHash(const char *s) +{ + unsigned r=5381;char c; + while((c=(*s++)))r=((r<<5)+r)+c; + return r; +} +Idata& blrScriptVM::fetchData(SPara para,bool forcerw) +{ + static Idata cret; + switch (para.type) + { + case 0: + if(forcerw)throw; + cret.i()=para.data.i;cret.type=0; + return cret; + case 1: + if(forcerw)throw; + cret.r()=para.data.r;cret.type=1; + return cret; + case 2: + return ir[para.data.i]; + case 3: + return rr[para.data.i]; + case 4: + return ia[para.data.i]; + case 5: + return ra[para.data.i]; + case 6: + return ia[ir[para.data.i].i()]; + case 7: + return ra[ir[para.data.i].i()]; + default: + throw; + } +} +int blrScriptVM::mgetc() +{ + if(cbyte-sbyte<fsize) + {++cbyte;return (int)*(cbyte-1);} + else return -1; +} +void blrScriptVM::readPara(SPara *para) +{ + para->type=mgetc(); + para->data.d=0; + int l=0; + switch(para->type) + { + case 1: l=8;break; + case 0: case 4: case 5: l=4;break; + case 2: case 3: case 6: case 7: l=1;break; + default: break; + } + for(int i=0;i<l;++i) + { + para->data.d<<=8LL; + para->data.d|=(unsigned long long)mgetc(); + } +} +int blrScriptVM::loadLSBFromMemory(const char *ptr,DWORD size) +{ + cbyte=sbyte=ptr;fsize=size; + int ibyt=0,infunc=0; + while(~(ibyt=mgetc())) + { + ++ic;inst[ic].id=ibyt; + switch(inst[ic].id) + { + case 0xFF: case 0x02: + { + int nl=mgetc(); + if(nl==-1)return 1; + if(inst[ic].id==0xFF){if(infunc)return 1;else infunc=1;} + if(inst[ic].id==0x02)if(!infunc)return 1; + inst[ic].para1.fnc=(char*)calloc(sizeof(char),nl+1); + inst[ic].para1.type=8; + for(int i=0;i<nl;++i)inst[ic].para1.fnc[i]=mgetc(); + if(inst[ic].id==0xFF) + { + fncent[fncnt].pos=ic; + fncent[fncnt++].hash=getHash(inst[ic].para1.fnc); + } + } + break; + case 0x00: break; + case 0xFE: + if(!infunc)return 1; + infunc=0; + break; + case 0x0F: + if(!infunc)return 1; + break; + case 0x01: case 0x0C: case 0x0D: + case 0x0E: case 0x11: case 0x12: + case 0x13: case 0x14: case 0x15: + case 0x16: case 0x21: + if(!infunc)return 1; + readPara(&inst[ic].para1); + break; + case 0x03: case 0x04: case 0x05: + case 0x06: case 0x07: case 0x08: + case 0x09: case 0x0A: case 0x0B: + case 0x22: case 0x23: + if(!infunc)return 1; + readPara(&inst[ic].para1); + readPara(&inst[ic].para2); + break; + } + } + return 0; +} +int blrScriptVM::getInstCount(){return pinst;} +void blrScriptVM::runFunction(const char *fncnym) +{ + int nymhash=getHash(fncnym),cur=0;pinst=0; + for(int i=0;i<fncnt;++i)if(nymhash==fncent[i].hash){cur=fncent[i].pos;break;} + while(inst[cur].id!=0xFE) + { + int jmp=0;++pinst; + //printf("@offset %d, instId 0x%x\n",cur,inst[cur].id); + rr[100].r()=0.01667; + //printf("r00: %f, r01: %f\n",rr[0].r(),rr[1].r()); + switch(inst[cur].id) + { + case 0x00: + //no-op + break; + case 0xFF: + //no-op + break; + case 0x01: + callStk.push(fetchData(inst[cur].para1)); + break; + case 0x02: + //callFnc(inst[cur].para1.fnc); + //callstk.clear(); + //printf("stubbed call %s\n",inst[cur].para1.fnc); + break; + case 0x03: + fetchData(inst[cur].para1,true)=fetchData(inst[cur].para2); + break; + case 0x04: + fetchData(inst[cur].para1,true)+=fetchData(inst[cur].para2); + break; + case 0x05: + fetchData(inst[cur].para1,true)-=fetchData(inst[cur].para2); + break; + case 0x06: + fetchData(inst[cur].para1,true)*=fetchData(inst[cur].para2); + break; + case 0x07: + fetchData(inst[cur].para1,true)/=fetchData(inst[cur].para2); + break; + case 0x08: + fetchData(inst[cur].para1,true)%=fetchData(inst[cur].para2); + break; + case 0x09: + fetchData(inst[cur].para1,true)&=fetchData(inst[cur].para2); + break; + case 0x0A: + fetchData(inst[cur].para1,true)|=fetchData(inst[cur].para2); + break; + case 0x0B: + fetchData(inst[cur].para1,true)^=fetchData(inst[cur].para2); + break; + case 0x0C: + fetchData(inst[cur].para1,true)=~fetchData(inst[cur].para1,true); + break; + case 0x0D: + ++fetchData(inst[cur].para1,true); + break; + case 0x0E: + --fetchData(inst[cur].para1,true); + break; + case 0x0F: + callStk.clear(); + break; + case 0x11: + switch (fetchData(inst[cur].para1,true).type) + { + case 0: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).ltz()?ione:izero; + break; + case 1: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).ltz()?rone:rzero; + break; + } + break; + case 0x12: + switch (fetchData(inst[cur].para1,true).type) + { + case 0: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).elz()?ione:izero; + break; + case 1: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).elz()?rone:rzero; + break; + } + break; + case 0x13: + switch (fetchData(inst[cur].para1,true).type) + { + case 0: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).gtz()?ione:izero; + break; + case 1: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).gtz()?rone:rzero; + break; + } + break; + case 0x14: + switch (fetchData(inst[cur].para1,true).type) + { + case 0: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).egz()?ione:izero; + break; + case 1: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).egz()?rone:rzero; + break; + } + break; + case 0x15: + switch (fetchData(inst[cur].para1,true).type) + { + case 0: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).eqz()?ione:izero; + break; + case 1: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).eqz()?rone:rzero; + break; + } + break; + case 0x16: + switch (fetchData(inst[cur].para1,true).type) + { + case 0: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).nez()?ione:izero; + break; + case 1: + fetchData(inst[cur].para1,true)= + fetchData(inst[cur].para1,true).nez()?rone:rzero; + break; + } + break; + case 0x21: + cur=fetchData(inst[cur].para1).i(); + jmp=1; + break; + case 0x22: + if(fetchData(inst[cur].para1).eqz()) + cur=fetchData(inst[cur].para2).i(),jmp=1; + break; + case 0x23: + if(fetchData(inst[cur].para1).nez()) + cur=fetchData(inst[cur].para2).i(),jmp=1; + break; + } + if(!jmp)++cur; + } +} +void blrScriptVM::vmInit() +{ +} +void blrScriptVM::vmDeinit() +{ +} diff --git a/src/core/vmrunner.hpp b/src/core/vmrunner.hpp new file mode 100644 index 0000000..60bc2ce --- /dev/null +++ b/src/core/vmrunner.hpp @@ -0,0 +1,48 @@ +#ifndef VMRUNNER_H +#define VMRUNNER_H +#include "smelt.hpp" +#include "smrandom.hpp" +#include "scriptshared.hpp" +const Idata ione=Idata(0,1),izero=Idata(0,0); +const Idata rone=Idata(1,1),rzero=Idata(1,0); +template<class memb> +class callStack//a queue, in fact. +{ +private: + int l,r; + memb data[16]; +public: + callStack(){clear();} + void clear(){l=0;r=-1;} + int size(){return r-l+1;} + bool empty(){return size()==0;} + void push(memb a){data[++r]=a;if(r>15)throw;} + memb pop(){if(l<=r+1)return data[l++];else throw;} + memb front(){return data[l];} + memb back(){return data[r];} +}; +callStack<Idata> callStk; +typedef struct _fncEntry{int hash,pos;}fncEntry; +class blrScriptVM +{ +private: + smRandomEngine* re; + Idata ir[101],ia[10000]; + Idata rr[103],ra[10000]; + SInst inst[65537]; + int ic,fncnt,pinst; + fncEntry fncent[8]; + const char *sbyte,*cbyte; + DWORD fsize; + void readPara(SPara *para); + int mgetc(); + Idata& fetchData(SPara para,bool forcerw=false); +public: + blrScriptVM(){ic=fncnt=pinst=0;} + int loadLSBFromMemory(const char* ptr,DWORD size); + int getInstCount(); + void runFunction(const char *fncnym); + void vmInit(); + void vmDeinit(); +}; +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..afe37d4 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,30 @@ +#include "smelt.hpp" +#include "master/master.hpp" +#include "master/resources.hpp" +#include <cstdlib> +SMELT *sm; +sceneManager *sceneMgr; +bool update(){return sceneMgr->update();} +bool foc(){if(sceneMgr->isSceneActive(sceneMgr->getSceneID("GameScene")))sceneMgr->startUpdate();return false;} +bool unfoc(){if(sceneMgr->isSceneActive(sceneMgr->getSceneID("GameScene"))&&sceneMgr->isThreadActive())sceneMgr->stopUpdate();return false;} +int main(int argc,char **argv) +{ + srand(time(NULL)); + sm=smGetInterface(SMELT_APILEVEL); + sceneMgr=new sceneManager; + resourcesLoad(); + sm->smVidMode(960,720,true); + sm->smUpdateFunc(update); + sm->smFocFunc(foc);sm->smUnFocFunc(unfoc); + sm->smWinTitle("Bullet Lab Remix 3"); + sm->smSetFPS(FPS_VSYNC); + sm->smInit(); + introScene *insc=new introScene; + insc->introInit(); + sm->smMainLoop(); + sm->smFinale(); + resourcesUnload(); + delete sceneMgr; + sm->smRelease(); + return 0; +} diff --git a/src/makefile b/src/makefile new file mode 100644 index 0000000..57d9356 --- /dev/null +++ b/src/makefile @@ -0,0 +1,41 @@ +CC= g++ +CXXFLAGS= -std=c++11 -Wall -g -I/home/chrisoft/devel/BulletLabRemixIII/include +LINK= -L../smelt/sdl -L../extensions -lsmeltext -lsmelt -lCxImage -lSDL2 -lvorbis -lvorbisfile -lopenal -ljpeg -lpng -lfreetype -lz -pthread + +all: main + +main: main.o scenemgr.o intro.o menuclass.o resources.o mainmenu.o bullet.o gamescene.o player.o vmrunner.o + $(CC) main.o scenemgr.o intro.o menuclass.o mainmenu.o resources.o bullet.o gamescene.o player.o vmrunner.o $(LINK) -o BLR3 + +main.o: main.cpp + $(CC) $(CXXFLAGS) -c main.cpp + +scenemgr.o: master/scenemgr.cpp + $(CC) $(CXXFLAGS) -c master/scenemgr.cpp + +resources.o: master/resources.cpp + $(CC) $(CXXFLAGS) -c master/resources.cpp + +intro.o: master/intro.cpp + $(CC) $(CXXFLAGS) -c master/intro.cpp + +menuclass.o: ui/menuframework/menuclass.cpp + $(CC) $(CXXFLAGS) -c ui/menuframework/menuclass.cpp + +mainmenu.o: ui/mainmenu.cpp + $(CC) $(CXXFLAGS) -c ui/mainmenu.cpp + +bullet.o: core/bullet.cpp + $(CC) $(CXXFLAGS) -c core/bullet.cpp + +gamescene.o: core/gamescene.cpp + $(CC) $(CXXFLAGS) -c core/gamescene.cpp + +player.o: core/player.cpp + $(CC) $(CXXFLAGS) -c core/player.cpp + +vmrunner.o: core/vmrunner.cpp + $(CC) $(CXXFLAGS) -c core/vmrunner.cpp + +clean: + rm *.o BLR3
\ No newline at end of file diff --git a/src/master/init.cpp b/src/master/init.cpp new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/src/master/init.cpp @@ -0,0 +1 @@ + diff --git a/src/master/intro.cpp b/src/master/intro.cpp new file mode 100644 index 0000000..f8cf46b --- /dev/null +++ b/src/master/intro.cpp @@ -0,0 +1,202 @@ +#include "master.hpp" +#include "resources.hpp" +#include <cmath> +#include <cstdlib> +#include <ctime> +#include "../ui/menus.hpp" +#define XOFFSET 75 +#define YOFFSET 100 + +extern sceneManager *sceneMgr; +SMELT *introScene::sm=0; +bool introScene::sceneUpdate() +{ + bool done=bcnt>400; + for(int i=0;i<bcnt;++i) + { + pos[i]=pos[i]+vel[i]; + vel[i]=vel[i]+acc[i]; + if(pos[i].x>-40&&pos[i].x<1000&&pos[i].y>-40&&pos[i].y<800)done=false; + if(scale[i]>0.7)scale[i]-=0.1;else scale[i]=0.6; + } + if(done) + { + mainMenuScn=new mainMenuScene; + sceneMgr->activateScene("MainMenu"); + delete this; + } + delay+=sm->smGetDelta(); + if(delay<0.016)return false; + delay=0; + for(int cc=0;cc<3;++cc) + { + ++step; + if(ch==0)//C + { + float angle=(60-step)/45.*PI+PI/3.; + pos[bcnt]=smvec2d(100+XOFFSET+80*cos(angle),200+YOFFSET+80*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + if(step>=60){++ch;step=0;} + } + if(ch==1)//h + { + if(step<=40) + { + pos[bcnt]=smvec2d(180+XOFFSET,120+YOFFSET+step*4); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>40&&step<70) + { + float angle=(step-40)/30.*PI+PI; + pos[bcnt]=smvec2d(210+XOFFSET+30*cos(angle),220+YOFFSET+30*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>=70) + { + pos[bcnt]=smvec2d(240+XOFFSET,220+YOFFSET+(step-70)*4); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + if(step>=85){++ch;step=0;} + } + } + if(ch==2)//r + { + if(step<=20) + { + pos[bcnt]=smvec2d(280+XOFFSET,200+YOFFSET+step*4); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>20) + { + float angle=(step-20)/30.*PI+PI; + pos[bcnt]=smvec2d(310+XOFFSET+30*cos(angle),230+YOFFSET+30*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + if(step>=45){++ch;step=0;} + } + } + if(ch==3)//i + { + if(step<=20) + { + pos[bcnt]=smvec2d(360+XOFFSET,200+YOFFSET+step*4); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>20) + { + pos[bcnt]=smvec2d(360+XOFFSET,180+YOFFSET); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + ++ch;step=0; + } + } + if(ch==4)//s + { + if(step<=30) + { + float angle=(30-step)/30.*PI+2*PI/3.; + pos[bcnt]=smvec2d(450+XOFFSET+40*cos(angle),170+YOFFSET+40*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>30) + { + float angle=(step-30)/30.*PI+5*PI/3.; + pos[bcnt]=smvec2d(410+XOFFSET+40*cos(angle),239.282+YOFFSET+40*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + if(step>60){++ch;step=0;} + } + } + if(ch==5) + { + float angle=-step/30.*PI+3*PI/2.; + pos[bcnt]=smvec2d(520+XOFFSET+40*cos(angle),240+YOFFSET+40*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + if(step>60){++ch;step=0;} + } + if(ch==6) + { + if(step<=30) + { + float angle=(30-step)/30.*PI+PI; + pos[bcnt]=smvec2d(620+XOFFSET+30*cos(angle),160+YOFFSET+30*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>30&&step<=55) + { + pos[bcnt]=smvec2d(590+XOFFSET,160+YOFFSET+(step-30)*5); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>55) + { + pos[bcnt]=smvec2d(570+XOFFSET+(step-55)*4,190+YOFFSET); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + if(step>75){++ch;step=0;} + } + } + if(ch==7) + { + if(step<=20) + { + pos[bcnt]=smvec2d(700+XOFFSET,160+YOFFSET+step*5); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>25&&step<=55) + { + float angle=(55-step)/30.*PI; + pos[bcnt]=smvec2d(730+XOFFSET+30*cos(angle),260+YOFFSET+30*sin(angle)); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + } + if(step>55) + { + pos[bcnt]=smvec2d(680+XOFFSET+(step-55)*4,190+YOFFSET); + vel[bcnt]=smvec2d(0,0);acc[bcnt]=smvec2d(0,0);scale[bcnt]=1.5;++bcnt; + if(step>75){++ch;step=0;} + } + } + if(ch==8) + {if(step>120){++ch;step=0;}} + if(ch==9) + { + for(int i=0;i<bcnt;++i) + { + do{acc[i]=smvec2d(rand()%100-50.,rand()%100-50.);acc[i].normalize(); + }while(acc[i].l()<1E-6); + acc[i]=(rand()%100/400.+0.2)*acc[i]; + } + ++ch; + } + if(ch==10) + {if(step>180){++ch;step=0;}} + } + return false; +} +bool introScene::sceneRender() +{ + if(ch!=11) + sm->smClrscr(0xFF000000); + else + {int c=step*4>255?255:step*4;sm->smClrscr(ARGB(255,c,c,c));} + for(int i=0;i<bcnt;++i) + blt->render(pos[i].x,pos[i].y,0,scale[i],scale[i]); + return false; +} +introScene::introScene() +{ + sm=smGetInterface(SMELT_APILEVEL); + pos=new smvec2d[1024];vel=new smvec2d[1024]; + scale=new float[1024];acc=new smvec2d[1024]; + extern const char* bsnames[]; + smTexInfo *ti=ssanm.getTextureInfo(bsnames[rand()%8]); + blt=new smEntity2D(ti->tex,ti->rect); + blt->setCentre(12,12); + blt->setColor(0xC0FFFFFF); + sceneMgr->registerScene(this,"Intro",1000); +} +void introScene::introInit() +{ + bcnt=step=ch=0; + sceneMgr->activateScene("Intro"); +} +introScene::~introScene() +{ + sceneMgr->deactivateScene("Intro"); + delete[] pos;delete[] vel;delete[] acc;delete[] scale;delete blt; + sm->smRelease(); +} diff --git a/src/master/master.hpp b/src/master/master.hpp new file mode 100644 index 0000000..8ccb740 --- /dev/null +++ b/src/master/master.hpp @@ -0,0 +1,64 @@ +#ifndef MASTER_H +#define MASTER_H +#include "smelt.hpp" +#include "smdatapack.hpp" +#include "smmath.hpp" +#include "smentity.hpp" +#include "smanim.hpp" +#include <thread> +#include <chrono> +struct pn{int p,n;}; +class scenePrototype +{ +public: + virtual bool sceneUpdate(){return false;} + virtual bool sceneRender(){return false;} + virtual bool threadUpdate(){return false;} + virtual ~scenePrototype(){} +}; +class sceneManager +{ +private: + scenePrototype *sps[256]; + static SMELT* sm; + static std::thread* uth; + char names[256][16]; + bool active[256],thactive; + int scnt,dlps,lp,utime; + float lps,lpsud; + pn pq[256]; +public: + sceneManager(); + ~sceneManager(); + int registerScene(scenePrototype *sp,const char* scenename,int priority); + void activateScene(const char* scene); + void deactivateScene(const char* scene); + void startUpdate(); + void stopUpdate(); + bool isThreadActive(); + int getSceneID(const char* scene); + bool isSceneActive(int sceneid); + void setLPS(int lps); + float getLPS(); + int getTHUpdateTime(); + bool update(); + void threadUpdate(); +}; + +class introScene:public scenePrototype +{ +private: + char* ssptr;DWORD sssez; + smvec2d *pos,*vel,*acc; + float *scale,delay; + smEntity2D *blt; + int bcnt,step,ch; + static SMELT *sm; +public: + introScene(); + ~introScene(); + void introInit(); + bool sceneUpdate()override; + bool sceneRender()override; +}; +#endif diff --git a/src/master/resources.cpp b/src/master/resources.cpp new file mode 100644 index 0000000..1ae35cf --- /dev/null +++ b/src/master/resources.cpp @@ -0,0 +1,18 @@ +#include "smdatapack.hpp" +#include "smbmfont.hpp" +smDtpFileR blrdtp; +smBMFont lcdfont; +smAnmFile ssanm; +void resourcesLoad() +{ + blrdtp.openDtp("blr3.dtp"); + lcdfont.loadAnmFromMemory(blrdtp.getFilePtr("lcdfont.anm"),blrdtp.getFileSize("lcdfont.anm")); + lcdfont.setScale(0.6); + ssanm.loadAnmFromMemory(blrdtp.getFilePtr("ss.anm"),blrdtp.getFileSize("ss.anm")); +} +void resourcesUnload() +{ + blrdtp.closeDtp(); + lcdfont.close(); + ssanm.close(); +} diff --git a/src/master/resources.hpp b/src/master/resources.hpp new file mode 100644 index 0000000..2cfb497 --- /dev/null +++ b/src/master/resources.hpp @@ -0,0 +1,7 @@ +#include "smdatapack.hpp" +#include "smbmfont.hpp" +extern smDtpFileR blrdtp; +extern smBMFont lcdfont; +extern smAnmFile ssanm; +extern void resourcesLoad(); +extern void resourcesUnload(); diff --git a/src/master/scenemgr.cpp b/src/master/scenemgr.cpp new file mode 100644 index 0000000..1399d63 --- /dev/null +++ b/src/master/scenemgr.cpp @@ -0,0 +1,63 @@ +#include "master.hpp" +#include <cstring> +#include <cstdlib> +int cmp(const void* a,const void* b){return ((pn*)b)->p-((pn*)a)->p;} +extern sceneManager *sceneMgr; +SMELT* sceneManager::sm=NULL; +std::thread* sceneManager::uth=NULL; +sceneManager::sceneManager(){sm=smGetInterface(SMELT_APILEVEL);utime=scnt=0;thactive=false;dlps=64;} +sceneManager::~sceneManager(){sm->smRelease();} +int sceneManager::registerScene(scenePrototype *sp,const char* scenename,int priority) +{ + for(int i=0;i<scnt;++i)if(!strncmp(scenename,names[i],16))return -1; + sps[scnt]=sp; + strncpy(names[scnt],scenename,16); + active[scnt]=false; + pq[scnt].p=priority;pq[scnt].n=scnt;++scnt; + qsort(pq,scnt,sizeof(pn),cmp); + return scnt-1; +} +void sceneManager::activateScene(const char* scene) +{for(int i=0;i<scnt;++i)if(!strncmp(scene,names[i],16)){active[i]=true;break;}} +void sceneManager::deactivateScene(const char* scene) +{for(int i=0;i<scnt;++i)if(!strncmp(scene,names[i],16)){active[i]=false;break;}} +void sceneManager::startUpdate(){thactive=true;uth=new std::thread(&sceneManager::threadUpdate,sceneMgr);} +void sceneManager::stopUpdate(){thactive=false;uth->join();delete uth;} +bool sceneManager::isThreadActive(){return thactive;} +int sceneManager::getSceneID(const char* scene) +{for(int i=0;i<scnt;++i)if(!strncmp(scene,names[i],16))return i;return -1;} +bool sceneManager::isSceneActive(int sceneid){return active[sceneid];} +void sceneManager::setLPS(int lps){dlps=lps;} +float sceneManager::getLPS(){return lps;} +int sceneManager::getTHUpdateTime(){return utime;} +//Update functions return true if it wants to terminate the application. +//Render functions should never return true. +bool sceneManager::update() +{ + for(int i=0;i<scnt;++i) + if(active[pq[i].n])if(sps[pq[i].n]->sceneUpdate())return true; + sm->smRenderBegin2D(true); + for(int i=0;i<scnt;++i) + if(active[pq[i].n])sps[pq[i].n]->sceneRender(); + sm->smRenderEnd(); + if(sm->smGetKeyState(SMK_S)==SMKST_HIT)sm->smScreenShot("ss0.bmp"); + return false; +} +void sceneManager::threadUpdate() +{ + long ddlay; + while(thactive) + { + ddlay=1000000000/dlps; + using namespace std::chrono; + high_resolution_clock::time_point b=high_resolution_clock::now(); + for(int i=0;i<scnt;++i) + if(active[pq[i].n])sps[pq[i].n]->threadUpdate(); + high_resolution_clock::time_point a=high_resolution_clock::now(); + auto updateTime=a-b;utime=updateTime.count(); + ++lp;lpsud+=updateTime.count()>ddlay?updateTime.count():ddlay; + if(lpsud>=1000000000){lps=(float)lp/(lpsud/1000000000.);lp=0;lpsud=0;} + if(updateTime<(duration<long,std::ratio<1l,1000000000l>>)ddlay) + std::this_thread::sleep_for((duration<long,std::ratio<1l,1000000000l>>)ddlay-updateTime); + } +} diff --git a/src/ui/mainmenu.cpp b/src/ui/mainmenu.cpp new file mode 100644 index 0000000..7bb62b8 --- /dev/null +++ b/src/ui/mainmenu.cpp @@ -0,0 +1,69 @@ +#include "menus.hpp" +#include "../master/resources.hpp" +#include "../core/corepublic.hpp" +#include <cstdlib> +smAnmFile menubg; +smEntity2D *menubEnt; +smEntity2D *whitexf; +BYTE whitea; +bool exitPressed(int key){if((key==SMK_ENTER)||(key==SMK_Z))return true;return false;} +bool startPressed(int key) +//stub +{ + if((key==SMK_ENTER)||(key==SMK_Z)) + { + extern sceneManager *sceneMgr; + gameScn=new gameScene; + sceneMgr->registerScene(gameScn,"GameScene",900); + sceneMgr->activateScene("GameScene"); + sceneMgr->deactivateScene("MainMenu"); + sceneMgr->startUpdate(); + } + return false; +} +SMELT* mainMenuScene::sm=NULL; +mainMenuScene::mainMenuScene() +{ + extern sceneManager *sceneMgr; + sm=smGetInterface(SMELT_APILEVEL); + menubg.loadAnmFromMemory(blrdtp.getFilePtr("menu.anm"),blrdtp.getFileSize("menu.anm")); + menubEnt=new smEntity2D(menubg.getTextureInfo("menubg")->tex,menubg.getTextureInfo("menubg")->rect); + whitexf=new smEntity2D(0,0,0,960,720);whitea=0xFF;whitexf->setZ(1); + sceneMgr->registerScene(this,"MainMenu",990); + menu=new menuLCD(43,20,7,360,370,&lcdfont); + menu->addCtrl(new menuCtrlLCD(0,20,&lcdfont)); + menu->getCtrl(0)->setText(NULL,"START"); + menu->getCtrl(0)->onKeyPressed(startPressed); + menu->addCtrl(new menuCtrlLCD(1,20,&lcdfont)); + menu->getCtrl(1)->setText(NULL,"HIGHSCORE"); + menu->addCtrl(new menuCtrlLCD(2,20,&lcdfont)); + menu->getCtrl(2)->setText(NULL,"REPLAY"); + menu->addCtrl(new menuCtrlLCD(3,20,&lcdfont)); + menu->getCtrl(3)->setText(NULL,"CONSOLE"); + menu->addCtrl(new menuCtrlLCD(4,20,&lcdfont)); + menu->getCtrl(4)->setText(NULL,"NOW PLAYING"); + menu->addCtrl(new menuCtrlLCD(5,20,&lcdfont)); + menu->getCtrl(5)->setText(NULL,"OPTIONS"); + menu->addCtrl(new menuCtrlLCD(6,20,&lcdfont)); + menu->getCtrl(6)->setText(NULL,"HELP"); + menu->addCtrl(new menuCtrlLCD(7,20,&lcdfont)); + menu->getCtrl(7)->setText(NULL,"EXIT"); + menu->getCtrl(7)->onKeyPressed(exitPressed); +} +mainMenuScene::~mainMenuScene() +{ + delete menu;delete menubEnt;delete whitexf; + menubg.close();sm->smRelease(); +} +bool mainMenuScene::sceneUpdate(){return menu->update();} +bool mainMenuScene::sceneRender() +{ + sm->smClrscr(0xFF000000); + if(whitea>6)whitea-=6;else whitea=0; + whitexf->setColor(SETA(0x00FFFFFF,whitea)); + menubEnt->render(0,0); + menu->render(); + whitexf->render(0,0); + return false; +} +mainMenuScene *mainMenuScn; diff --git a/src/ui/menuframework/menuclass.cpp b/src/ui/menuframework/menuclass.cpp new file mode 100644 index 0000000..d135a01 --- /dev/null +++ b/src/ui/menuframework/menuclass.cpp @@ -0,0 +1,115 @@ +#include "menuframework.hpp" +#include <cstring> +#include <cmath> +SMELT* menuCtrlLCD::sm=NULL; +SMELT* menuLCD::sm=NULL; +void menuCtrlLCD::render(float x,float y) +{ + fnt->setColor(color); + fnt->render(x+skv,y,1,ALIGN_LEFT,NULL,rt); +} +void menuCtrlLCD::update() +{ + if(overlen) + { + if(selected) + { + ++scd; + if(scd>30)++scv,scd=0; + if(scv>(int)strlen(tr))scv=0; + char rr[48];sprintf(rr,"%s %s",tr,tr); + sprintf(rt,"%s %.*s",tl,(int)(maxw-strlen(tl)-1),rr+scv); + } + else + { + scv=0; + sprintf(rt,"%s %.*s...",tl,(int)(maxw-strlen(tl)-4),tr); + } + } + if(skd>0){skv=-skv;--skd;}else skd=skv=0; + if(selected) + {color=SETA(color,(int)(0x60*fabsf(sin(6*sm->smGetTime())))+0x90);} + else + color=SETA(color,0x80); +} +void menuCtrlLCD::setText(const char* l,const char* r) +{ + if(!l)l="";if(!r)r=""; + tl=l;tr=r; + if((int)(strlen(l)+strlen(r)+1)>maxw) + { + overlen=true;scv=0;scd=0; + } + else + { + overlen=false; + sprintf(rt,"%s %*s",l,(int)(maxw-strlen(l)-1),r); + } +} +void menuLCD::addCtrl(menuCtrlLCD *ctrl) +{ + if(ctrl->id==0)ctrl->selected=true;else ctrl->selected=false; + menuCtrlLCD *last=ctrls; + if(!ctrls) + { + ctrls=ctrl; + ctrl->last=0; + ctrl->next=0; + } + else + { + while(last->next)last=last->next; + last->next=ctrl; + ctrl->last=last; + ctrl->next=0; + } + ctrl->color=0x80333333; +} +menuCtrlLCD* menuLCD::getCtrl(int id) +{ + for(menuCtrlLCD* i=ctrls;i;i=i->next) + if(i->id==id)return i; + return NULL; +} +bool menuLCD::update() +{ + if(sm->smGetKeyState(SMK_DOWN)==SMKST_HIT) + { + getCtrl(selected)->selected=false; + menuCtrlLCD* c; + for(int i=selected+1;(c=getCtrl(i));++i) + {if(c->enabled){selected=i;break;}} + getCtrl(selected)->selected=true; + } + if(sm->smGetKeyState(SMK_UP)==SMKST_HIT) + { + getCtrl(selected)->selected=false; + menuCtrlLCD* c; + for(int i=selected-1;(c=getCtrl(i));++i) + {if(c->enabled){selected=i;break;}} + getCtrl(selected)->selected=true; + } + for(menuCtrlLCD* i=ctrls;i;i=i->next)i->update(); + if(sm->smGetKey()) + return getCtrl(selected)->ikp(); + else return false; +} +void menuLCD::render() +{ + int cr=rows/2+1; + getCtrl(selected)->render(x,y+(cr-1)*itemh); + menuCtrlLCD* t=getCtrl(selected); + for(int ccr=cr-1;ccr>0;--ccr) + { + if(t)t=getCtrl(t->id-1); + if(!t){fnt->setColor(0x80333333);fnt->printf(x,y+(ccr-1)*itemh,1,ALIGN_LEFT,NULL,"%*s",maxw," ");} + else t->render(x,y+(ccr-1)*itemh); + } + t=getCtrl(selected); + for(int ccr=cr+1;ccr<=rows;++ccr) + { + if(t)t=getCtrl(t->id+1); + if(!t){fnt->setColor(0x80333333);fnt->printf(x,y+(ccr-1)*itemh,1,ALIGN_LEFT,NULL,"%*s",maxw," ");} + else t->render(x,y+(ccr-1)*itemh); + } +} diff --git a/src/ui/menuframework/menuframework.hpp b/src/ui/menuframework/menuframework.hpp new file mode 100644 index 0000000..1879686 --- /dev/null +++ b/src/ui/menuframework/menuframework.hpp @@ -0,0 +1,56 @@ +#ifndef BLRMENUFW_H +#define BLRMENUFW_H +#include "smelt.hpp" +#include "smbmfont.hpp" +typedef bool (*smHooki)(int); +class menuCtrlLCD +{ +protected: + static SMELT *sm; +private: + smHooki keyPressedf; + bool overlen; + const char *tl,*tr; + int scv,scd,maxw,skv,skd; + char rt[64]; +public: + int id; + bool enabled,selected; + DWORD color; + menuCtrlLCD *next,*last; + smBMFont *fnt; + menuCtrlLCD(int _id,int mw,smBMFont *font) + { + sm=smGetInterface(SMELT_APILEVEL);enabled=true;keyPressedf=NULL; + color=0xFFFFFFFF;id=_id;maxw=mw;fnt=font;skv=0;next=last=NULL; + } + virtual ~menuCtrlLCD(){sm->smRelease();} + void render(float x,float y); + void update(); + virtual void updateHook(){} + void setText(const char *l,const char *r); + void onKeyPressed(smHooki kpf){keyPressedf=kpf;}//parameter is the key pressed. The return value has no effect. + void shake(int intv,int dur){skv=intv;skd=dur;} + bool ikp(){if(keyPressedf)return keyPressedf(sm->smGetKey());else return false;} +}; +class menuLCD +{ +private: + static SMELT *sm; + float itemh,x,y; + int maxw,rows,selected; + menuCtrlLCD *ctrls; + smBMFont *fnt; +public: + menuLCD(float ih,int mw,int rowc,float _x,float _y,smBMFont *font) + { + ctrls=NULL;selected=0;sm=smGetInterface(SMELT_APILEVEL); + maxw=mw;itemh=ih;rows=rowc;x=_x;y=_y;fnt=font; + } + ~menuLCD(){menuCtrlLCD *c,*n;c=ctrls;while(c){n=c->next;delete c;c=n;}sm->smRelease();} + void addCtrl(menuCtrlLCD *ctrl); + menuCtrlLCD* getCtrl(int id); + bool update(); + void render(); +}; +#endif diff --git a/src/ui/menus.hpp b/src/ui/menus.hpp new file mode 100644 index 0000000..780a3a6 --- /dev/null +++ b/src/ui/menus.hpp @@ -0,0 +1,16 @@ +#include "../master/master.hpp" +#include "menuframework/menuframework.hpp" +extern smAnmFile menubg; +extern smEntity2D *menubEnt; +class mainMenuScene:public scenePrototype +{ +private: + menuLCD *menu; + static SMELT* sm; +public: + mainMenuScene(); + ~mainMenuScene(); + bool sceneUpdate()override; + bool sceneRender()override; +}; +extern mainMenuScene *mainMenuScn; |