// Copyright (C) 2011 Valeriano Alfonso Rodriguez (Kableado) #include #include #include "Time.h" #include "Util.h" #include "Draw.h" #include "Input.h" #include "Audio.h" #include "Anim.h" #include "Entity.h" #include "GameLib.h" // Globals int _running; Entity **_entity=NULL; int *_entity_flag=NULL; int _n_entities=0; int _n_entities_res=0; int _entities_lock=0; int _entities_compactate=0; void (*_gameproc)()=NULL; void (*_gamepostproc)()=NULL; void (*_gamedraw)()=NULL; int _ft; int _game_size[2]; int _game_pos[2]; long long t_proc; long long t_col; long long t_over; long long t_postproc; long long t_draw; int fproc_count; int fdraw_count; int gamelib_debug=0; ///////////////////////////// // GameLib_Init // // Initializes the game. int GameLib_Init(int w,int h,char *title,int fps){ if(!Draw_Init(w,h,title,fps)){ return(0); } if(!Input_Init()){ return(0); } Audio_Init(); _game_size[0]=w; _game_size[1]=h; _game_pos[0]=0; _game_pos[1]=0; _ft=1000/fps; return(1); } ///////////////////////////// // GameLib_AddEntity // // Adds an entity to the game. void GameLib_AddEntity(Entity *e){ if(_n_entities>=_n_entities_res){ Entity **entity_aux; int *entity_flag_aux; int i; // Grow the array if(_n_entities_res==0) _n_entities_res=32; else _n_entities_res*=2; entity_aux=malloc(sizeof(Entity *)*_n_entities_res); entity_flag_aux=malloc(sizeof(int)*_n_entities_res); for(i=0;i<_n_entities;i++){ entity_aux[i]=_entity[i]; entity_flag_aux[i]=_entity_flag[i]; } if(_entity){ free(_entity); free(_entity_flag); } _entity=entity_aux; _entity_flag=entity_flag_aux; } // Add the entity _entity[_n_entities]=e; _entity_flag[_n_entities]=1; _n_entities++; // Mark for light update GameLib_EntityUpdateLight(e); } ///////////////////////////// // GameLib_UnrefEntity // // removes the reference to the entity. int GameLib_UnrefEntity(Entity *e){ int i; for(i=0;i<_n_entities;i++){ if(e==_entity[i]){ // Mark or unref if(_entities_lock){ _entity_flag[i]=-2; }else{ _entity[i]=NULL; _entity_flag[i]=0; } _entities_compactate=1; // Mark for light update GameLib_EntityUpdateLight(e); return(i); } } return(-1); } ///////////////////////////// // GameLib_DelEntity // // Adds an entity to the game. int GameLib_DelEntity(Entity *e){ int i; if((i=GameLib_UnrefEntity(e))==-1){ return(0); } if(_entities_lock){ // Delete latter _entity[i]=e; _entity_flag[i]=-1; }else{ // Delete now Entity_Destroy(e); } return(1); } ///////////////////////////// // GameLib_Compactate // // void GameLib_Compactate(){ int i,j; j=0; if(!_entities_compactate) return; for(i=0;i<_n_entities;i++){ if(!_entity[i] || _entity_flag[i]==-2) continue; if(_entity_flag[i]==-1){ Entity_Destroy(_entity[i]); continue; } if(i>j){ _entity[j]=_entity[i]; _entity_flag[j]=_entity_flag[i]; } j++; } _n_entities=j; _entities_compactate=0; _entities_lock=0; } ///////////////////////////// // GameLib_ProcLoop // // Process the loop. int GameLib_ProcLoop(){ int i,j; int repeat,count; long long time; // Process time=Time_GetTime(); GameLib_Compactate();_entities_lock=1; if(_gameproc){ _gameproc(); } for(i=0;i<_n_entities;i++){ if(!_entity[i]) continue; Entity_Process(_entity[i],_ft); } GameLib_Compactate(); t_proc+=Time_GetTime()-time; // Colisions between entities time=Time_GetTime(); GameLib_Compactate();_entities_lock=1; count=0; do{ repeat=0; for(i=0;i<_n_entities;i++){ if(!(_entity[i]->flags&EntityFlag_Collision) || _entity[i]->mass<0.0f) continue; for(j=0;j<_n_entities;j++){ if(!(_entity[j]->flags&EntityFlag_Collision) || i==j) continue; if(Entity_Collide(_entity[i],_entity[j])){ repeat=1; } } } count++; }while(repeat && count<10); // Stop remaining collisions if(count==10){ for(i=0;i<_n_entities;i++){ if(!(_entity[i]->flags&EntityFlag_Collision) || _entity[i]->mass<0.0f) continue; for(j=0;j<_n_entities;j++){ if(!(_entity[j]->flags&EntityFlag_Collision) || i==j) continue; if(Entity_Collide(_entity[i],_entity[j])){ vec2_set(_entity[i]->vel,0,0); vec2_set(_entity[j]->vel,0,0); } } } } GameLib_Compactate(); t_col+=Time_GetTime()-time; // Process Overlaps time=Time_GetTime(); GameLib_Compactate();_entities_lock=1; for(i=0;i<_n_entities;i++){ if(!(_entity[i]->flags&EntityFlag_Overlap) || _entity[i]->mass<0.0f) continue; for(j=0;j<_n_entities;j++){ if(!(_entity[j]->flags&EntityFlag_Overlap) || i==j) continue; Entity_Overlaps(_entity[i],_entity[j]); } } GameLib_Compactate(); t_over+=Time_GetTime()-time; // Sort int n,n2,swap; n=_n_entities; do{ n2=0; for(i=1;izorder > _entity[i]->zorder){ // Lower level swap=1; }else if(_entity[i-1]->zorder < _entity[i]->zorder){ // Upper level }else{ // Same level if(_entity[i-1]->pos[1] > _entity[i]->pos[1]){ swap=1; } } if(swap){ Entity *ent; ent=_entity[i]; _entity[i]=_entity[i-1]; _entity[i-1]=ent; n2=i; } } n=n2; }while(n>0); // PostProcess time=Time_GetTime(); GameLib_Compactate();_entities_lock=1; for(i=0;i<_n_entities;i++){ Entity_PostProcess(_entity[i],_ft); if(_entity[i]->flags&EntityFlag_UpdatedPos){ GameLib_EntityUpdateLight(_entity[i]); } } if(_gamepostproc){ _gamepostproc(); } GameLib_Compactate(); t_postproc+=Time_GetTime()-time; fproc_count++; return(_running); } ///////////////////////////// // GameLib_DrawLoop // // void GameLib_DrawLoop(){ long long time; int i; time=Time_GetTime(); // Update Lights //GameLib_UpdateIlumination(); // Limpiar pantalla Draw_Clean(0,0,0); // Draw entities GameLib_Compactate();_entities_lock=1; for(i=0;i<_n_entities;i++){ Entity *e; // FIXME: This is a hack e=_entity[i]; if(e->pos[0]<(_game_pos[0]-128)) continue; if(e->pos[0]>(_game_pos[0]+_game_size[0]+128)) continue; if(e->pos[1]<(_game_pos[1]-128)) continue; if(e->pos[1]>(_game_pos[1]+_game_size[1]+128)) continue; // Update ilumination of this entity if(e->flags&EntityFlag_UpdateLight){ Entity_Iluminate(e,_entity,_n_entities); e->flags&=~EntityFlag_UpdateLight; } Entity_Draw(e,-_game_pos[0],-_game_pos[1]); } if(_gamedraw){ _gamedraw(); } GameLib_Compactate(); t_draw+=Time_GetTime()-time; fdraw_count++; } ///////////////////////////// // GameLib_Loop // // Loops the game. void GameLib_Loop( void (*gameproc)(), void (*gamepostproc)(), void (*gamedraw)()) { _running=1; _gameproc=gameproc; _gamepostproc=gamepostproc; _gamedraw=gamedraw; t_proc=0; t_col=0; t_over=0; t_postproc=0; t_draw=0; fproc_count=0; fdraw_count=0; Draw_Loop(GameLib_ProcLoop,GameLib_DrawLoop); if (gamelib_debug) { printf("Profiling:::::::::\n"); printf("t_proc.....:%6lld\n",t_proc/fproc_count); printf("t_col......:%6lld\n",t_col/fproc_count); printf("t_over.....:%6lld\n",t_over/fproc_count); printf("t_postproc.:%6lld\n",t_postproc/fproc_count); printf("t_draw.....:%6lld\n",t_draw/fdraw_count); } } ///////////////////////////// // GameLib_BreakLoop // // Breaks the game loop. void GameLib_BreakLoop(){ _running=0; } ///////////////////////////// // GameLib_GetPos // GameLib_SetPos // GameLib_SetPos // // void GameLib_GetPos(int pos[2]){ pos[0]=_game_pos[0]; pos[1]=_game_pos[1]; } void GameLib_SetPos(int pos[2]){ _game_pos[0]=pos[0]; _game_pos[1]=pos[1]; } void GameLib_GetSize(int size[2]){ size[0]=_game_size[0]; size[1]=_game_size[1]; } ///////////////////////////// // GameLib_ForEachEn // // Deletes every entity. void GameLib_DelEnts(){ int i; for(i=0;i<_n_entities;i++){ if(!_entity[i]) continue; Entity_Destroy(_entity[i]); } _n_entities=0; } ///////////////////////////// // GameLib_ForEachEn // // Iterates every entity. void GameLib_ForEachEnt(int (*func)(Entity *ent)){ int i; for(i=0;i<_n_entities;i++){ if(!_entity[i]) continue; if(!func(_entity[i])){ break; } } } ///////////////////////////// // GameLib_PlaySound // // void GameLib_PlaySound(AudioSnd snd,int x,int y){ float vleft,vright,dx,dy; int r,cx,cy,off; // Get the screen context cx=_game_pos[0]+_game_size[0]/2; cy=_game_pos[1]+_game_size[1]/2; if(_game_size[0]>_game_size[1]){ r=_game_size[0]/2; }else{ r=_game_size[1]/2; } r=r*1.2f; off=r/10.0f; // Calculate volumes dx=x-(cx+off); dy=y-(cy); vright=1.0f-(sqrtf(dx*dx+dy*dy)/(float)r); dx=x-(cx-off); dy=y-(cy); vleft=1.0f-(sqrtf(dx*dx+dy*dy)/(float)r); // Clamp to 0 if(vleft<0.0f) vleft=0.0f; if(vright<0.0f) vright=0.0f; if(vleft<=0.0f && vright<=0.0f){ return; } // PLAY! Audio_PlaySound(snd,vleft,vright); } ///////////////////////////// // GameLib_Iluminate // // void GameLib_Iluminate(){ int i; for(i=0;i<_n_entities;i++){ Entity_Iluminate(_entity[i],_entity,_n_entities); } } ///////////////////////////// // GameLib_EntitySetLight // // void GameLib_EntitySetLight(Entity *e,float r,float g,float b,float rad){ if(e->flags&EntityFlag_Light){ GameLib_EntityUpdateLight(e); Entity_SetLight(e,r,g,b,rad); GameLib_EntityUpdateLight(e); }else{ Entity_SetLight(e,r,g,b,rad); e->flags|=EntityFlag_UpdateLight; } } ///////////////////////////// // GameLib_EntityUpdateLight // // void GameLib_EntityUpdateLight(Entity *e){ if(e->flags&EntityFlag_Light){ int i; vec2 max,min; vec2_set(max,e->pos[0]+e->light[3],e->pos[1]+e->light[3]); vec2_set(min,e->pos[0]-e->light[3],e->pos[1]-e->light[3]); for(i=0;i<_n_entities;i++){ if( min[0]<=_entity[i]->pos[0] && max[0]>=_entity[i]->pos[0] && min[1]<=_entity[i]->pos[1] && max[1]>=_entity[i]->pos[1]) { _entity[i]->flags|=EntityFlag_UpdateLight; } } }else{ e->flags|=EntityFlag_UpdateLight; } } ///////////////////////////// // GameLib_UpdateIlumination // // void GameLib_UpdateIlumination(){ int i; for(i=0;i<_n_entities;i++){ if(_entity[i]->flags&EntityFlag_UpdateLight){ Entity_Iluminate(_entity[i],_entity,_n_entities); _entity[i]->flags&=~EntityFlag_UpdateLight; } } }