Advertisement
Kitomas

2024-07-19 (6/13)

Jul 19th, 2024
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 33.05 KB | None | 0 0
  1. /******************************************************************************/
  2. /******************************************************************************/
  3. //"kw32g\src\globals_audioManager.cpp":
  4. #include <globals.hpp>
  5. #include <tile.hpp>
  6.  
  7. using namespace kit;
  8.  
  9. #define AM_LOOP_WAIT  0050  //in milliseconds
  10. #define MUS_VOLUME   0.030f //default volume for music modules
  11. #define AMB_VOLUME   0.015f //default volume for ambient tracks
  12. #define AMB_FADE     1.000f //fade in/out of 1000ms
  13.  
  14.  
  15. //turbo janky setup because it turns out my mutexes
  16.  //do not work at all across multiple threads (which makes them useless >:( )
  17.  //(probably the reason i can't call gl_snd's
  18.  //deconstructor without a crash!)
  19. #define AM_LOOP_START {                          \
  20.   while(gl_audioManager_occ_sfx) time::sleep(0); \
  21.   gl_audioManager_occ_thr = true;                }
  22.  
  23. #define AM_LOOP_END {               \
  24.   gl_audioManager_occ_thr = false;  \
  25.   time::sleep(AM_LOOP_WAIT);        }
  26.  
  27. #define STOPPED (0xFFFF)
  28. #define FAILURE (-1)
  29.  
  30.  
  31.  
  32.  
  33. //using gl_fstr outside the main thread causes conflicts, so here's another fstr
  34. FStr am_fstr;
  35.  
  36.  
  37.  
  38.  
  39. static inline void musicLoad(u16 id){
  40.   try {
  41.     gl_snd->musicLoadModule(am_fstr.fmt("dat/music/%s",gl_music[id]));
  42.  
  43.   } catch(const char* errorText){
  44. #ifdef _DEBUG
  45.     _printf("ERROR LOADING MUSIC \"%s\": \"%s\"\n", am_fstr.ptr(), errorText);
  46. #else
  47.     FStr am_fstr2; //2 formats are needed for this, so create yet another fstr
  48.     am_fstr2.fmt("ERROR LOADING MUSIC \"%s\": \"%s\"", am_fstr.ptr(), errorText);
  49.  
  50.     showMessageBox(am_fstr2.ptr(),
  51.                    "NON-FATAL EXCEPTION OCCURRED! COMPLAIN TO THE DEV! (lol)",
  52.                    MSGBOX_ICN_ERROR);
  53. #endif
  54.  
  55.   }
  56.  
  57. }
  58.  
  59. //aliases & other variables
  60. #define musicRelease   gl_snd->musicReleaseModule
  61. #define musicStop      gl_snd->musicStop
  62. #define musicStart     gl_snd->musicStart
  63. #define music_playing  gl_snd->musicIsPlaying() //() intentionally used here
  64. #define music_id       gl_scene.music
  65. static u16  music_id_prev  = STOPPED;
  66. static bool music_stopping = false;
  67.  
  68.  
  69.  
  70. #define startVol 0.00001f //can't be exactly 0 or else it stops immediately lol
  71. static inline s32 ambiencePlay(u16 id){
  72.   s32 new_track = gl_snd->sfxPlay(gl_ambience[id], startVol,startVol);
  73.  
  74.   if(new_track != FAILURE)
  75.     gl_snd->sfxSetVolumeDelta(new_track, AMB_FADE, AMB_FADE);
  76.  
  77.   return new_track;
  78.  
  79. }
  80.  
  81. //make sure not to never use SoundEffect here,
  82.  //as that will lock up the audioManager thread!
  83. //(also, when stopping an sfx track to fit a new
  84.  //ambience track, make sure to use stopForced!)
  85. #define sfxStopForced           gl_snd->sfxStopForced
  86. #define ambienceFadeout(_track) gl_snd->sfxSetVolumeDelta(_track, -(AMB_FADE),-(AMB_FADE))
  87. #define ambience_a_id           gl_scene.ambience_a
  88. #define ambience_b_id           gl_scene.ambience_b
  89. static u16 ambience_a_id_prev = STOPPED;
  90. static u16 ambience_b_id_prev = STOPPED;
  91.  
  92. //'which track is ambience_x assigned to?'
  93. static s32 ambience_a_track = -1;
  94. static s32 ambience_b_track = -1;
  95.  
  96.  
  97.  
  98.  
  99.  
  100. static inline void update_music(){
  101.   //if music isn't supposed to change at all right now
  102.    //(including if music_id is the current one)
  103.   if(!music_id  ||  music_id == music_id_prev) return;
  104.  
  105.  
  106.   if(!music_stopping){
  107.     music_stopping = true;
  108.     if(music_playing) musicStop();
  109.  
  110.   } else if(!music_playing){
  111.     music_stopping = false;
  112.     music_id_prev = music_id;
  113.     musicRelease();
  114.  
  115.     //if music is supposed to change rather than completely stop
  116.     if(music_id != STOPPED){
  117.       musicLoad(music_id);
  118.       musicStart();
  119.     }
  120.  
  121.   }
  122.  
  123.  
  124. }
  125.  
  126.  
  127.  
  128.  
  129.  
  130. #define ambience_id      (*ambience_id_ptr)
  131. #define ambience_id_prev (*ambience_id_prev_ptr)
  132. #define ambience_track   (*ambience_track_ptr)
  133. //+2 instead of +1, because there are 2 ambience tracks
  134. #define increment_ambience_track() ( ambience_track = (ambience_track+2)%SND_TRACK_COUNT )
  135. void update_ambience(bool update_a_instead_of_b){ //(not inlined)
  136.   u16* ambience_id_ptr;
  137.   u16* ambience_id_prev_ptr;
  138.   s32* ambience_track_ptr;
  139.  
  140.   if(update_a_instead_of_b){
  141.     ambience_id_ptr      = &ambience_a_id;
  142.     ambience_id_prev_ptr = &ambience_a_id_prev;
  143.     ambience_track_ptr   = &ambience_a_track;
  144.   } else {
  145.     ambience_id_ptr      = &ambience_b_id;
  146.     ambience_id_prev_ptr = &ambience_b_id_prev;
  147.     ambience_track_ptr   = &ambience_b_track;
  148.   }
  149.  
  150.  
  151.  
  152.   //if ambience isn't supposed to change at all right now
  153.    //(including if ambience_id is the current one)
  154.   if(!ambience_id  ||  ambience_id == ambience_id_prev) return;
  155.  
  156.  
  157.   //fading out causes a track to stop automatically when its volume reaches 0,
  158.    //so it's the most smooth way of stopping a track
  159.   //(this will stop any sound effect that happens to be in this track,
  160.    //whether or not it's an ambience track at the time! this should be
  161.    //taken care of by the "ambience_track = -1", but jsyk yk?)
  162.   if(ambience_track > -1) ambienceFadeout(ambience_track);
  163.  
  164.  
  165.   if(ambience_id != STOPPED){
  166.     s32 new_track = ambiencePlay(ambience_id);
  167.  
  168.     if(new_track == FAILURE){ //all tracks are occupied
  169.       increment_ambience_track(); // =(t+1)%track_count
  170.       sfxStopForced(ambience_track); //forcefully make room for ambient track
  171.       //it should be impossible for it to fail this time (should...)
  172.       ambience_track = ambiencePlay(ambience_id);
  173.  
  174.     } else { //track sucessfully started playing
  175.       ambience_track = new_track;
  176.  
  177.     }
  178.  
  179.   } else {
  180.     ambience_track = -1; //mark ambience as stopped
  181.  
  182.   }
  183.  
  184.  
  185.   ambience_id_prev = ambience_id;
  186.  
  187. }
  188.  
  189.  
  190.  
  191.  
  192.  
  193. #define UPDATE_A true
  194. #define UPDATE_B false
  195. s32 audioManager(void* userdata){
  196.   //libxmp's nearest-neighbor interpolation sounds fugly,
  197.    //so force linear interpolation to be used instead
  198.   gl_snd->musicSetUseNearest(false);
  199.   gl_snd->musicSetVolumeForced(MUS_VOLUME, MUS_VOLUME);
  200.   //this forces the module to loop
  201.   //gl_snd->musicSetCheckLoop(false);
  202.  
  203.  
  204.   //set the master volume for the ambience tracks specifically
  205.   for(u32 i=1; i<(gl_ambience_len+1); ++i){
  206.     gl_ambience[i]->volumeL = AMB_VOLUME;
  207.     gl_ambience[i]->volumeR = AMB_VOLUME;
  208.   }
  209.  
  210.  
  211.  
  212.   while(!gl_audioManager_exit){
  213.     AM_LOOP_START
  214.  
  215.  
  216.     update_music();
  217.  
  218.     update_ambience(UPDATE_A);
  219.     update_ambience(UPDATE_B);
  220.  
  221.  
  222.     AM_LOOP_END
  223.   }
  224.  
  225.  
  226.   return 0;
  227.  
  228. }
  229. /******************************************************************************/
  230. /******************************************************************************/
  231. //"kw32g\src\main.cpp":
  232. #include <globals.hpp>
  233. #include <player.hpp>
  234. #include <tile.hpp>
  235. #include <object.hpp>
  236. #include <save.hpp>
  237.  
  238. #include <stdio.h>
  239. #include <stdlib.h>
  240.  
  241. using namespace kit;
  242.  
  243. /*
  244. might want to eventually refactor how edge transitions occur, as instead of
  245.   teleporting to a fixed point once an edge is crossed, maybe it should be done
  246.   as an offset to the current edge position, or the transition is handled
  247.   within the move function itself at the exact point the edge is crossed
  248. keep track of which scenes are swapped so they can be reswapped
  249. refactor player movement to improve game feel
  250. make object that confuses the player for a certain number of ticks
  251. be able to change footstep sounds based on the tile type
  252. have area only accessible by run-jumping while teleporting
  253. add in cutscene image slideshow things
  254. be able to change scene after cutscene
  255. create player animation frame override
  256. add customizable friction coefficients for tilesets
  257. make sure to not use the result of fstr->fmt as a parameter to another call to fstr->fmt
  258. create vel_m to separate player movement velocity and normal velocity
  259. */
  260.  
  261.  
  262.  
  263.  
  264.  
  265. int gameMain(int argc, char** argv){
  266.   gl_player.sfx_footstep = gl_sfx[1];
  267.   gl_player.sfx_jumping  = gl_sfx[2];
  268.   gl_player.sfx_landing  = gl_sfx[3];
  269.  
  270.  
  271.   attemptReset(true);
  272.  
  273.  
  274.   bool run = true;
  275.   f64 timeStart = time::getUptime();
  276.   while(run){
  277.     gl_frameTimer->setTimer((1.0/60)/TPF);
  278.     resetEnvFlags();
  279.  
  280.  
  281.     clearControlStates();
  282.     if(!handleEvents()) break;
  283.  
  284.     if(!gl_player.dying){
  285.       gl_player.vel.y += GRAVITY;
  286.       gl_player.update();
  287.  
  288.       handleEdgeWrap();
  289.  
  290.     }
  291.  
  292.  
  293.     drawStuff_and_processObjects();
  294.  
  295.  
  296.     DBG_TXT( 0, ".pos        = {%i, %i}", gl_player.pos.x, gl_player.pos.y);
  297.     DBG_TXT( 1, ".vel        = {%6.2f, %6.2f}", gl_player.vel.x, gl_player.vel.y);
  298.     DBG_TXT( 2, ".acc        = {%6.2f, %6.2f}", gl_player.acc.x, gl_player.acc.y);
  299.     DBG_TXT( 3, ".ticksInAir = %u", gl_player.ticksInAir);
  300.     //DBG_TXT( 4, ".runningState  = %6.4f", gl_player.runningState);
  301.     //DBG_TXT( 5, ".scale         = %.2f", gl_player.scale);
  302.     //DBG_TXT( 6, ".facingRight   = %s", boolStr(gl_player.facingRight));
  303.     //DBG_TXT( 7, ".enforceMaxVel = %s", boolStr(gl_player.enforceMaxVel));
  304.     //DBG_TXT( 8, ".confused      = %s", boolStr(gl_player.confused));
  305.     //DBG_TXT( 9, ".first_jmp     = %s", boolStr(gl_player.first_jmp));
  306.     //DBG_TXT(10, ".second_jmp    = %s", boolStr(gl_player.second_jmp));
  307.     //DBG_TXT(11, ".has_dbljmp    = %s", boolStr(gl_player.has_dbljmp));
  308.     DBG_TXT( 5, "tick latency = %.2fms", (time::getUptime()-timeStart)*1000);
  309.     DBG_TXT( 6, "scene id     = %u", gl_scene.scene);
  310.  
  311.  
  312.     if(gl_death_prog < DEATH_PROG_MAX) deathAnim();
  313.  
  314.  
  315.     if(!handleEscExit()) break;
  316.  
  317.  
  318.     gl_win->present(true);
  319.  
  320.     gl_frameTimer->wait();
  321.     timeStart = time::getUptime();
  322.     ++gl_tickCounter;
  323.  
  324.   }
  325.  
  326.  
  327.   return 0;
  328.  
  329. }
  330. /******************************************************************************/
  331. /******************************************************************************/
  332. //"kw32g\src\object.cpp":
  333. #include <object.hpp>
  334. #include <player.hpp>
  335. #include <tile.hpp>
  336. #include <save.hpp>
  337.  
  338. using namespace kit;
  339.  
  340. #define GET_OBJ(_type) _type* obj = (_type*)_obj_a
  341. #define GET_DST(_obj_ptr) { _obj_ptr->x, _obj_ptr->y, _obj_ptr->size.x, _obj_ptr->size.y }
  342.  
  343.  
  344. #define OBJIMG(_index) gl_objImg[_index]
  345.  
  346. #define OBJIMG_LEVER_WALL       OBJIMG( 1) // 2x2, ??x??px
  347. #define OBJIMG_ABILITY_SHRINK   OBJIMG( 2) //24x1, ??x??px, 13 ticks (~9.2fps)
  348. #define OBJIMG_ABILITY_DBLJMP   OBJIMG( 3) //24x1, ??x??px, 13 ticks (~9.2fps)
  349. #define OBJIMG_ABILITY_SPEED    OBJIMG( 4) //24x1, ??x??px, 13 ticks (~9.2fps)
  350. #define OBJIMG_ABILITY_REMOVER  OBJIMG( 5) // 3x1, ??x??px
  351. #define OBJIMG_SIGNPOST_WOOD    OBJIMG( 6) // 1x1, ??x??px
  352. #define OBJIMG_EASTER_EGG       OBJIMG( 7) //12x1, ??x??px, 8 ticks (15 fps)
  353. #define OBJIMG_TELEPORTER_BACK  OBJIMG( 8) //16x1, ??x??px, 8 ticks (15 fps)
  354. #define OBJIMG_TELEPORTER_FRONT OBJIMG( 9) //16x1, ??x??px, 8 ticks (15 fps)
  355. #define OBJIMG_DEATH_BALL       OBJIMG(10) //17x1, 22x22px, 8 ticks (15 fps)
  356.  
  357. #define TXTLINE(_index) gl_text_lines[_index]
  358.  
  359.  
  360.  
  361.  
  362.  
  363. //copy original state of object data to the active scene
  364. void loadObjects(bool forced, u16 scene_id){
  365.   if(!scene_id && !gl_scene.scene)
  366.     throw "gl_scene.scene == 0 (loadScene(>0) before calling loadObjects()!)";
  367.   if(!scene_id) scene_id = gl_scene.scene;
  368.   if(scene_id > gl_scenes_len) throw "scene_id > gl_scenes_len";
  369.  
  370.   SceneDescriptor* scene_current = gl_scenes[scene_id];
  371.  
  372.   Object* objsCache = gl_objsCache[scene_id];
  373.   Object* objs      = scene_current->objs;
  374.   u16     objs_len  = scene_current->objs_len;
  375.  
  376.  
  377.   if(!forced){ //only copy object data whose persistence flag is false
  378.     for(u32 i=0; i<objs_len; ++i){
  379.       if(!objsCache[i].persistent) objsCache[i] = objs[i];
  380.     }
  381.  
  382.   } else { //otherwise, copy all objects in scene
  383.     for(u32 i=0; i<objs_len; ++i){
  384.       objsCache[i] = objs[i];
  385.     }
  386.  
  387.   }
  388.  
  389. }
  390.  
  391.  
  392.  
  393.  
  394. #define CHECK_TYPE_NULL 0
  395. bool processObjects(bool in_front, bool render_only){
  396.   bool scene_changed = false;
  397.  
  398.   Object* objs      = gl_objsCache[gl_scene.scene];
  399.   u16     objs_len  = gl_scenes[gl_scene.scene]->objs_len;
  400.   Object* obj;
  401.  
  402.  
  403.  
  404.   #if CHECK_TYPE_NULL == 1
  405.     #define TYPE_CHECK  && obj->type != 0
  406.   #else
  407.     #define TYPE_CHECK
  408.   #endif
  409.  
  410.   if(!in_front){
  411.     for(u32 i=0; i<objs_len; ++i){
  412.       obj = &objs[i];
  413.       if(!obj->in_front /*&&*/ TYPE_CHECK)
  414.         scene_changed |= obj->update(obj, render_only);
  415.  
  416.     }
  417.  
  418.  
  419.   } else {
  420.     for(u32 i=0; i<objs_len; ++i){
  421.       obj = &objs[i];
  422.       if(obj->in_front /*&&*/ TYPE_CHECK)
  423.         scene_changed |= obj->update(obj, render_only);
  424.  
  425.     }
  426.  
  427.   }
  428.  
  429.   #undef TYPE_CHECK
  430.  
  431.  
  432.  
  433.   if(!render_only) return scene_changed;
  434.   else             return false;
  435.  
  436. }
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443. bool obj_1lever(Object* _obj_a, bool render_only){
  444.   GET_OBJ(_obj_1lever); //obj = _obj_a
  445.  
  446.   shape::rect rect_dst = GET_DST(_obj_a);
  447.   shape::rect rect_src(0,0, 8,24);
  448.   bool scene_changed = false;
  449.  
  450.  
  451.   if(!obj->init){
  452.     _obj_a->persistent = 1; //this object is always persistent
  453.  
  454.     obj->init =  true;
  455.     obj->img  = OBJIMG_LEVER_WALL;
  456.  
  457.  
  458.     if(!obj->sfx_id){ //use default sound effect
  459.       obj->sfx = SFXPTR_ACTIVATE_1;
  460.  
  461.     } else if(obj->sfx_id <= gl_sfx_len){ //use specified sound effect
  462.       obj->sfx = SFXPTR(obj->sfx_id);
  463.  
  464.     } else { //no sound effect found
  465.       obj->sfx = nullptr;
  466.       //tbd: warn about nonexistent sound effect
  467.  
  468.     }
  469.  
  470.  
  471.   }
  472.  
  473.  
  474.  
  475.   //if player is touching the object
  476.   if(rects_overlapping(gl_player.getRect(), rect_dst)){
  477.     rect_src.y = 24; //highlighted
  478.     //if player activates the lever
  479.     if(!render_only && CTRLSTATE_GET(inst.down_p)){
  480.       swapScene(obj->scene_old, obj->scene_new);
  481.       obj->flipped ^= 1;
  482.       scene_changed = true;
  483.       SFXPTR_PLAY(obj->sfx);
  484.     }
  485.  
  486.   }
  487.  
  488.   if(obj->flipped) rect_src.x = 8; //lever points down
  489.  
  490.  
  491.   if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, 0xff00ff);
  492.  
  493.   return scene_changed;
  494.  
  495. }
  496.  
  497.  
  498.  
  499.  
  500.  
  501. bool obj_ability(Object* _obj_a, bool render_only){
  502.   GET_OBJ(_obj_ability); //obj = _obj_a
  503.  
  504.   shape::rect rect_dst = GET_DST(_obj_a);
  505.   shape::rect rect_src(0,0, 24,24);
  506.  
  507.  
  508.   if(!obj->init){
  509.     _obj_a->persistent = 1; //this object is always persistent
  510.  
  511.     obj->init         = true;
  512.     obj->frameCounter = 23; //will roll over to 0 this iteration
  513.  
  514.     //this implementation is quite strange but whatever it works like a charm
  515.     switch(obj->which){
  516.       case 0 : obj->img         = OBJIMG_ABILITY_SHRINK;
  517.                obj->has_ability = &gl_player.has_shrink; break;
  518.  
  519.       case 1 : obj->img         = OBJIMG_ABILITY_DBLJMP;
  520.                obj->has_ability = &gl_player.has_dbljmp; break;
  521.  
  522.       case 2 : obj->img         = OBJIMG_ABILITY_SPEED;
  523.                obj->has_ability = &gl_player.has_speed;  break;
  524.  
  525.       default: obj->img         = gl_tileset_missing;
  526.                obj->has_ability = nullptr;
  527.  
  528.     }
  529.  
  530.   }
  531.  
  532.  
  533.  
  534.   //if player is touching the object (and everything else is valid)
  535.   if(!render_only) //&&
  536.   if(obj->has_ability != nullptr  &&  !(*obj->has_ability)  &&
  537.      rects_overlapping(gl_player.getRect(), rect_dst))
  538.   {
  539.     *obj->has_ability = true;
  540.     SFXPTR_PLAY(SFXPTR_ABILITY_PICKUP);
  541.  
  542.   }
  543.  
  544.  
  545.  
  546.   //pick which frame in the animation to use
  547.   if(!render_only  &&  obj->has_ability != nullptr){
  548.     //increment animation's frame counter every 13 ticks, which makes for ~9.2fps
  549.     if(!(gl_tickCounter%13)) obj->frameCounter = (obj->frameCounter+1)%24;
  550.  
  551.     if(*obj->has_ability) rect_src.y = 24; //otherwise it'll remain 0
  552.  
  553.   }
  554.  
  555.   rect_src.x = 24 * obj->frameCounter;
  556.  
  557.  
  558.   //if the has_ability pointer is invalid, disable magenta transparency, since
  559.    //the 'missing tile' bitmap uses the color magenta
  560.   color::ARGB t_color = (obj->has_ability != nullptr) ? 0xff00ff : 0x80000000;
  561.  
  562.   if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, t_color);
  563.  
  564.   return false;
  565.  
  566. }
  567.  
  568.  
  569.  
  570.  
  571.  
  572. bool obj_ability_remover(Object* _obj_a, bool render_only){
  573.   GET_OBJ(_obj_ability_remover); //obj = _obj_a
  574.  
  575.   shape::rect rect_dst = GET_DST(_obj_a);
  576.   shape::rect rect_src(24*obj->which,0, 24,24);
  577.  
  578.  
  579.   if(!obj->init){
  580.     _obj_a->persistent = 1; //this object is always persistent
  581.  
  582.     obj->init = true;
  583.  
  584.     obj->img = OBJIMG_ABILITY_REMOVER;
  585.     if(!obj->img) obj->img = gl_tileset_missing; //this shouldn't happen ever
  586.  
  587.     switch(obj->which){
  588.       case 0 : obj->has_ability = &gl_player.has_shrink; break;
  589.       case 1 : obj->has_ability = &gl_player.has_dbljmp; break;
  590.       case 2 : obj->has_ability = &gl_player.has_speed;  break;
  591.       default: obj->has_ability = nullptr;
  592.  
  593.     }
  594.  
  595.   }
  596.  
  597.  
  598.  
  599.   //if player is touching the object (and everything else is valid)
  600.   if(!render_only) //&&
  601.   if(obj->has_ability != nullptr  &&  (*obj->has_ability)  &&
  602.      rects_overlapping(gl_player.getRect(), rect_dst))
  603.   {
  604.     *obj->has_ability = false;
  605.     SFXPTR_PLAY(SFXPTR_ABILITY_REMOVED);
  606.  
  607.     if(!obj->dontReset)
  608.     switch(obj->which){
  609.       //(case 0 should only fail if i place this object in a subtile-wide space)
  610.       case 0 : gl_player.setScale(2.0f);       break;
  611.     //case 1 : //(not used)
  612.       case 2 : gl_player.enforceMaxVel = true; break;
  613.       default:;
  614.  
  615.     }
  616.  
  617.   }
  618.  
  619.  
  620.  
  621.   //if the has_ability pointer is invalid, disable magenta transparency, since
  622.    //the 'missing tile' bitmap uses the color magenta
  623.   color::ARGB t_color = (obj->has_ability != nullptr) ? 0xff00ff : 0x80000000;
  624.  
  625.   if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, t_color);
  626.  
  627.   return false;
  628.  
  629. }
  630.  
  631.  
  632.  
  633.  
  634.  
  635. bool obj_generic_sprite(Object* _obj_a, bool render_only){
  636.   GET_OBJ(_obj_generic_sprite); //obj = _obj_a
  637.  
  638.   shape::rect rect_dst = GET_DST(_obj_a);
  639.   shape::rect rect_src(0,0, obj->w,obj->h);
  640.  
  641.  
  642.   if(!obj->init){
  643.     _obj_a->persistent = 1; //this object is always persistent
  644.  
  645.     obj->init         = true;
  646.  
  647.     //will roll over to 0 this iteration
  648.      //(MAX is used here, otherwise it underflows to 255)
  649.     obj->frameCounter = MAX(obj->numFrames,1)-1;
  650.  
  651.     if(obj->which <= gl_objImg_len) obj->img = OBJIMG(obj->which);
  652.     if(!obj->img){
  653.       //if i somehow have more than 65k object images,
  654.        //i have bigger problems to worry about
  655.       obj->which = KIT_U16_MAX;
  656.       obj->img   = gl_tileset_missing;
  657.     }
  658.  
  659.  
  660.     //if w/h are 0, then default the src size to the dst size
  661.     if(!obj->w){
  662.       obj->w = (u8)_obj_a->size.x;
  663.       rect_src.w = obj->w;
  664.     }
  665.  
  666.     if(!obj->h){
  667.       obj->h = (u8)_obj_a->size.y;
  668.       rect_src.h = obj->h;
  669.     }
  670.  
  671.   }
  672.  
  673.  
  674.  
  675.   //pick which frame in the animation to use
  676.   if(!render_only  &&  obj->numFrames > 1){
  677.     //increment animation's frame counter every tick_delay ticks
  678.     if(!(gl_tickCounter%obj->tick_delay))
  679.       obj->frameCounter = (obj->frameCounter+1)%obj->numFrames;
  680.  
  681.     //(which horizontal slot in the spritesheet to use, technically)
  682.     rect_src.x = rect_src.w * obj->frameCounter;
  683.  
  684.   }
  685.  
  686.  
  687.  
  688.   color::ARGB t_color = (obj->which != KIT_U16_MAX) ? 0xff00ff : 0x80000000;
  689.  
  690.   if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, t_color);
  691.  
  692.  
  693.  
  694.   return false;
  695.  
  696. }
  697.  
  698.  
  699.  
  700.  
  701.  
  702. bool obj_msgbox(Object* _obj_a, bool render_only){
  703.   GET_OBJ(_obj_msgbox); //obj = _obj_a
  704.  
  705.   shape::rect rect_collider = GET_DST(_obj_a);
  706.  
  707.   if(!obj->init){
  708.     _obj_a->persistent = 1; //this object is always persistent
  709.     _obj_a->in_front   = 1; //this object is always in front
  710.  
  711.     obj->init = true;
  712.  
  713.     if(obj->which <= gl_text_lines_len) obj->str = TXTLINE(obj->which);
  714.     if(!obj->str) obj->str = TXTLINE(0); // = "<INVALID TEXT ID>"
  715.  
  716.     obj->str_size = get_text_size(obj->str);
  717.  
  718.     //if both pos_x&y are 0, draw text box just above the msgbox collider
  719.     if(!obj->pos_x && !obj->pos_y){
  720.       obj->pos_x  =  _obj_a->x  +   _obj_a->size.x/2;
  721.       obj->pos_y  =  _obj_a->y  -  obj->str_size.y/2 - 10;
  722.  
  723.     } else {
  724.       //otherwise, center the axis that is 0, if any
  725.       if(     !obj->pos_x) obj->pos_x = CANVSIZ_X/2;
  726.       else if(!obj->pos_y) obj->pos_y = CANVSIZ_Y/2;
  727.  
  728.     }
  729.  
  730.   }
  731.  
  732.  
  733.   if(obj->show_always ||
  734.      rects_overlapping(gl_player.getRect(), rect_collider))
  735.   {
  736.     drawTextBox(obj->pos_x, obj->pos_y, obj->str, obj->str_size);
  737.   }
  738.  
  739.  
  740.   return false;
  741.  
  742. }
  743.  
  744.  
  745.  
  746.  
  747.  
  748. bool obj_save_interface(Object* _obj_a, bool render_only){
  749.   GET_OBJ(_obj_save_interface); //obj = _obj_a
  750.  
  751.   shape::rect rect_collider = GET_DST(_obj_a);
  752.  
  753.   if(!obj->init){
  754.     _obj_a->persistent = 1; //this object is always persistent
  755.     _obj_a->in_front   = 1; //this object is always in front
  756.  
  757.     obj->init = true;
  758.     //obj->touching = false; //might not need to set this
  759.     obj->box_height = 0;
  760.  
  761.   }
  762.  
  763.  
  764.  
  765.   if(!render_only)
  766.   if(rects_overlapping(gl_player.getRect(), rect_collider)){
  767.     if((!obj->touching && obj->passive) || CTRLSTATE_GET(inst.down_p)){
  768.       obj->touching = true;
  769.       switch(obj->which){
  770.         case 0 : {
  771.           if(saveRead()){
  772.             SFXPTR_PLAY(SFXPTR_DLELELE);
  773.             return true;
  774.           } else if(!obj->passive){
  775.             SFXPTR_PLAY(SFXPTR_NOPE_1);
  776.           }
  777.  
  778.         } break;
  779.         case 1 : {
  780.           if(!gl_saveRead_called){
  781.             saveWrite();
  782.             SFXPTR_PLAY(SFXPTR_FWSHWSHWSH);
  783.             if(!obj->passive) obj->box_height = rect_collider.h;
  784.           }
  785.  
  786.         } break;
  787.         case 2 : {
  788.           saveWipe();
  789.           SFXPTR_PLAY(SFXPTR_DLELELE);
  790.  
  791.         } break;
  792.         default:
  793.           _printf("WARNING: save interface object has invalid .which member!");
  794.       }
  795.  
  796.     }
  797.  
  798.   } else {
  799.     obj->touching = false;
  800.  
  801.   }
  802.  
  803.  
  804.  
  805.   if(obj->box_height > 0){
  806.     shape::rect rect_visual = rect_collider;
  807.  
  808.     rect_visual.h  = obj->box_height;
  809.     rect_visual.y += rect_collider.h - rect_visual.h;
  810.  
  811.     gl_win->drawRectangles(&rect_visual, 1, 0xffffff);
  812.     drawTextBox(CANVSIZ_X/2, CANVSIZ_Y/2, "SAVING...");
  813.  
  814.     if(!render_only) --obj->box_height;
  815.  
  816.   }
  817.  
  818.  
  819.  
  820.   return false;
  821.  
  822. }
  823.  
  824.  
  825.  
  826.  
  827.  
  828. bool obj_teleporter(Object* _obj_a, bool render_only){
  829.   GET_OBJ(_obj_teleporter); //obj = _obj_a
  830.  
  831.   shape::rect rect_collider = GET_DST(_obj_a);
  832.  
  833.   if(!obj->init){
  834.     _obj_a->persistent = 1; //this object is always persistent
  835.  
  836.     obj->init = true;
  837.  
  838.   }
  839.  
  840.  
  841.  
  842.   if(!render_only)
  843.   if(rects_overlapping(gl_player.getRect(), rect_collider)){
  844.     if((!obj->touching && obj->passive) || CTRLSTATE_GET(inst.down_p)){
  845.       obj->touching = true;
  846.  
  847.       SFXPTR_PLAY(SFXPTR_DLELELE);
  848.  
  849.       gl_player.pos.x = obj->pos_x;
  850.       gl_player.pos.y = obj->pos_y;
  851.       if(obj->scene){
  852.         loadScene(obj->scene);
  853.         return true;
  854.       }
  855.  
  856.     }
  857.  
  858.   } else {
  859.     obj->touching = false;
  860.  
  861.   }
  862.  
  863.  
  864.  
  865.   return false;
  866.  
  867. }
  868.  
  869.  
  870.  
  871.  
  872.  
  873. bool obj_death_zone(Object* _obj_a, bool render_only){
  874.   GET_OBJ(_obj_death_zone); //obj = _obj_a
  875.  
  876.   if(!obj->init){
  877.     _obj_a->persistent = 1; //this object is always persistent
  878.  
  879.     obj->init = true;
  880.  
  881.     obj->collider.x = _obj_a->x;
  882.     obj->collider.y = _obj_a->y;
  883.     obj->collider.w = _obj_a->size.x;
  884.     obj->collider.h = _obj_a->size.y;
  885.  
  886.   }
  887.  
  888.  
  889.  
  890.   if(!render_only && !gl_player.dying &&
  891.      rects_overlapping(gl_player.getRect(), obj->collider))
  892.   {
  893.     gl_player.kill();
  894.   }
  895.  
  896.  
  897.  
  898.   return false;
  899.  
  900. }
  901.  
  902.  
  903.  
  904.  
  905.  
  906. //note: if i add add sfx to this, make sure not to
  907.  //trigger it at the first waypoint, otherwise it
  908.  //would occur the moment the scene loads!
  909. bool obj_death_ball(Object* _obj_a, bool render_only){
  910.   GET_OBJ(_obj_death_ball); //obj = _obj_a
  911.  
  912.   if(!obj->init){
  913.     _obj_a->persistent = 1; //this object is always persistent
  914.  
  915.     obj->init = true;
  916.  
  917.     if(obj->speed==0.0f) obj->speed = 1.0f/120; //a->b in ~1 second
  918.     else if(obj->speed<0.0f) obj->speed = -obj->speed;
  919.  
  920.     if(!obj->a_x) obj->a_x = _obj_a->x;
  921.     if(!obj->a_y) obj->a_y = _obj_a->y;
  922.  
  923.     obj->frameCounter = 16; //will roll over once this hits 17
  924.  
  925.     obj->img = OBJIMG_DEATH_BALL;
  926.  
  927.   }
  928.  
  929.  
  930.  
  931.   s16 a_x = obj->a_x;
  932.   s16 a_y = obj->a_y;
  933.   s16 b_x = obj->b_x;
  934.   s16 b_y = obj->b_y;
  935.   f32 t_value = obj->t_value;
  936.  
  937.   shape::rect rect_dst;
  938.   rect_dst.w = _obj_a->size.x;
  939.   rect_dst.h = _obj_a->size.y;
  940.  
  941.   if(t_value < 1.0f){ //a->b
  942.     rect_dst.x = (s32)LERP(a_x, b_x, t_value     );
  943.     rect_dst.y = (s32)LERP(a_y, b_y, t_value     );
  944.  
  945.   } else { // >= 1.0f; b->a
  946.     rect_dst.x = (s32)LERP(b_x, a_x, t_value-1.0f);
  947.     rect_dst.y = (s32)LERP(b_y, a_y, t_value-1.0f);
  948.  
  949.   }
  950.  
  951.  
  952.  
  953.   if(!render_only){
  954.     shape::rect rect_player = gl_player.getRect();
  955.  
  956.     if(!gl_player.dying &&
  957.        rects_overlapping(rect_player, rect_dst))
  958.     {
  959.       gl_player.kill();
  960.     }
  961.  
  962.     t_value += obj->speed;
  963.     obj->t_value  = fmodf(t_value, 2.0f);
  964.  
  965.  
  966.     if(!(gl_tickCounter%7)){
  967.       obj->frameCounter +=  1;
  968.       obj->frameCounter %= 17;
  969.  
  970.     }
  971.  
  972.   }
  973.  
  974.  
  975.  
  976.   shape::rect rect_src(obj->frameCounter*22, 0, 22, 22);
  977.  
  978.   if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, 0xff00ff);
  979.  
  980.  
  981.   return false;
  982.  
  983. }
  984. /******************************************************************************/
  985. /******************************************************************************/
  986. //"kw32g\src\player.cpp":
  987. #include <player.hpp>
  988. #include <tile.hpp>
  989.  
  990. #include <math.h>
  991.  
  992. using namespace kit;
  993.  
  994.  
  995.  
  996.  
  997.  
  998. bool Player::setScale(f32 scale_new){
  999.   f32 scale_old = scale;
  1000.   scale = MAX(scale_new, 0.2f); //for a minimum of 2x2 pixels
  1001.  
  1002.   shape::rect player_rect = getRect();
  1003.   shape::point delta;
  1004.  
  1005.   //player was probably pushed into the floor if the scale increased,
  1006.    //so attempt to move the player out of any potential subtiles
  1007.   if(subtiles_overlapping(player_rect, &delta))
  1008.     player_rect += delta;
  1009.  
  1010.   //if the previous movement didn't result in the
  1011.    //player entering empty space, return false
  1012.   if(subtiles_overlapping(player_rect, nullptr)){
  1013.     scale = scale_old; //(revert the scale back to what it was originally too)
  1014.     return false;
  1015.  
  1016.   } else { //otherwise, apply those movement changes to pos, and return true
  1017.     pos += delta;
  1018.     return true;
  1019.  
  1020.   }
  1021.  
  1022. }
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028. #define SPRSHEET_ADJUST(_v) ((_v)*(8+1)) //8px +1 for one pixel of spacing
  1029.  
  1030. shape::rect Player::blit(bool only_return_src_rect){
  1031.   shape::rect src(0,0, 8,8);
  1032.   if(confused    ) src.y += SPRSHEET_ADJUST(1);
  1033.   if(!facingRight) src.y += SPRSHEET_ADJUST(2);
  1034.  
  1035.   if(!only_return_src_rect &&
  1036.      (!visible || scale<=0.0f))
  1037.   {
  1038.     return src;
  1039.   }
  1040.  
  1041.   shape::rect dst = getRect();
  1042.  
  1043.  
  1044.  
  1045.   if(MID_AIR){ //mid-air
  1046.     if(fabsf(vel.x) > PLAYER_NEUTRAL){ //going fast horizontally
  1047.       if(vel.y<=0) src.x = SPRSHEET_ADJUST(2); //-Y; back leg extended
  1048.       else         src.x = SPRSHEET_ADJUST(8); //+Y; front leg extended
  1049.     } else { //going slow (or not at all) horizontally
  1050.       if(     vel.y <-PLAYER_NEUTRAL) src.x = SPRSHEET_ADJUST(1); //-Y; back leg down
  1051.       else if(vel.y > PLAYER_NEUTRAL) src.x = SPRSHEET_ADJUST(4); //+Y; front leg down
  1052.       else                            src.x = SPRSHEET_ADJUST(7); //0Y; both legs up
  1053.     }
  1054.  
  1055.   } else { //on the ground
  1056.       if(vel.x < 0  &&  acc.x > 0){ //slowing down while moving left
  1057.         if(fabsf(vel.x) > PLAYER_NEUTRAL){ //going fast horizontally
  1058.           if(facingRight) src.x = SPRSHEET_ADJUST(2); //back leg extended
  1059.           else            src.x = SPRSHEET_ADJUST(8); //front leg extended
  1060.         } else { //going slow (or not at all) horizontally
  1061.           if(facingRight) src.x = SPRSHEET_ADJUST(1); //back leg down
  1062.           else            src.x = SPRSHEET_ADJUST(4); //front leg down
  1063.         }
  1064.  
  1065.       } else if(vel.x > 0  &&  acc.x < 0){ //slowing down while moving right
  1066.         if(fabsf(vel.x) > PLAYER_NEUTRAL){ //going fast horizontally
  1067.           if(facingRight) src.x = SPRSHEET_ADJUST(8); //front leg extended
  1068.           else            src.x = SPRSHEET_ADJUST(2); //back leg extended
  1069.         } else { //going slow (or not at all) horizontally
  1070.           if(facingRight) src.x = SPRSHEET_ADJUST(4); //front leg down
  1071.           else            src.x = SPRSHEET_ADJUST(1); //back leg down
  1072.         }
  1073.  
  1074.       } else if(fabsf(vel.x) > PLAYER_NEUTRAL){ //moving forward
  1075.         src.x = SPRSHEET_ADJUST(1 + RND(runningState)%6);
  1076.  
  1077.       } else if(acc.x < 0){ //standing still while accelerating left
  1078.         if(facingRight) src.x = SPRSHEET_ADJUST(4); //front leg down
  1079.         else            src.x = SPRSHEET_ADJUST(1); //back leg down
  1080.  
  1081.       } else if(acc.x > 0){ //standing still while accelerating right
  1082.         if(facingRight) src.x = SPRSHEET_ADJUST(1); //back leg down
  1083.         else            src.x = SPRSHEET_ADJUST(4); //front leg down
  1084.  
  1085.       } else { //standing still without acceleration
  1086.         src.x = SPRSHEET_ADJUST(0); //technically redundant, but left here for clarity
  1087.  
  1088.       }
  1089.  
  1090.   }
  1091.  
  1092.  
  1093.  
  1094.   //if enforceMaxVel is false, put a kind of highlight effect onto the player
  1095.   if(!enforceMaxVel && !only_return_src_rect){
  1096.     shape::rect highlight_dst = dst;
  1097.     shape::rect highlight_src = src;
  1098.  
  1099.     highlight_dst.x -= 1;
  1100.     highlight_dst.y -= 1;
  1101.     highlight_dst.w += 2;
  1102.     highlight_dst.h += 2;
  1103.  
  1104.     highlight_src.y += SPRSHEET_ADJUST(4);
  1105.  
  1106.     gl_spritesheetPlayer->blitRect(&highlight_dst, &highlight_src, 0xff00ff);
  1107.  
  1108.   }
  1109.  
  1110.  
  1111.  
  1112.   //0xff00ff for magenta as the transparency color
  1113.   if(!only_return_src_rect)
  1114.     gl_spritesheetPlayer->blitRect(&dst, &src, 0xff00ff);
  1115.  
  1116.   return src;
  1117.  
  1118. }
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124. //acc, visible, and confused are not modified here
  1125. void Player::update(){
  1126.   if(dying) return;
  1127.  
  1128.   if(going_left^going_right){
  1129.     if(     going_left ) acc.x = -PLAYER_SPEED;
  1130.     else if(going_right) acc.x =  PLAYER_SPEED;
  1131.     if(confused) acc.x = -acc.x;
  1132.  
  1133.   } else {
  1134.     acc.x = 0.0f;
  1135.  
  1136.   }
  1137.  
  1138.   vel.x += (MID_AIR) ? acc.x*PLAYER_AIR_FRICTION : acc.x;
  1139.   vel.y += acc.y;
  1140.   if(enforceMaxVel){
  1141.     vel.x = CLAMP(vel.x, -VELX_MAX, VELX_MAX);
  1142.     vel.y = CLAMP(vel.y, -VELY_MAX, VELY_MAX);
  1143.   }
  1144.  
  1145.  
  1146.  
  1147.   {
  1148.     shape::rect new_rect = move(vel.x, vel.y);
  1149.  
  1150.     shape::rect collider_ceiling = new_rect;
  1151.     shape::rect collider_floor   = new_rect;
  1152.     shape::rect collider_left    = new_rect;
  1153.     shape::rect collider_right   = new_rect;
  1154.  
  1155.  
  1156.     collider_ceiling.y -= 1;
  1157.     collider_ceiling.h  = 1;
  1158.     collider_floor.y   += collider_floor.h;
  1159.     collider_floor.h    = 1;
  1160.  
  1161.     if(vel.y<0.0f && subtiles_overlapping(collider_ceiling)){
  1162.       vel.y = fabsf(vel.y)/2;
  1163.       ++ticksInAir;
  1164.  
  1165.     } else if(vel.y>0.0f && subtiles_overlapping(collider_floor)){
  1166.       if(sfx_landing){
  1167.         sfx_landing->volL = (fabsf(vel.y)/VELY_MAX)*PLAYER_LANDING_VOLUME;
  1168.         sfx_landing->volR = sfx_landing->volL;
  1169.         play_sfx_landing(ticksInAir);
  1170.       }
  1171.       if(ticksInAir) runningState = 2.5f;
  1172.       ticksInAir = 0;
  1173.       first_jmp  = false;
  1174.       second_jmp = false;
  1175.       vel.y = 0.0f;
  1176.  
  1177.     } else {
  1178.       ++ticksInAir;
  1179.  
  1180.     }
  1181.  
  1182.  
  1183.     collider_left.x  -= 1;
  1184.     collider_left.w   = 1;
  1185.     collider_right.x += collider_right.w;
  1186.     collider_right.w  = 1;
  1187.  
  1188.     if(vel.x<0.0f && subtiles_overlapping(collider_left ) ||
  1189.        vel.x>0.0f && subtiles_overlapping(collider_right)  )
  1190.     {
  1191.       vel.x = 0.0f;
  1192.       runningState = 0.0f;
  1193.     }
  1194.   }
  1195.  
  1196.  
  1197.  
  1198.   //manage horizontal velocity
  1199.   {
  1200.     if(fabsf(vel.x)<0.05f && acc.x==0) vel.x = 0.0f;
  1201.  
  1202.     //if on ground while moving horizontally
  1203.     if(ticksInAir <= 1  &&  vel.x != 0){
  1204.       facingRight = vel.x > 0;
  1205.       if(ticksInAir <= 1  &&  acc.x == 0){
  1206.         vel.x -= (vel.x>0) ?  PLAYER_SPEED*PLAYER_GND_FRICTION
  1207.                            : -PLAYER_SPEED*PLAYER_GND_FRICTION;
  1208.       }
  1209.     }
  1210.   }
  1211.  
  1212.  
  1213.  
  1214.   //handle incrementing run animations
  1215.   {
  1216.     f32 prevRunningState = runningState;
  1217.  
  1218.     if(fabsf(vel.x) > PLAYER_NEUTRAL) runningState += fabsf(vel.x)*PLAYER_RUN_MUL;
  1219.     else                              runningState  = 0.0f;
  1220.     runningState = fmodf(fabsf(runningState), 6.0f);
  1221.  
  1222.     //used to indicate that a foot step sound effect should play
  1223.      //(1.5 instead of 2, since 1.5 would round up to integer state 2,
  1224.      //which is the actual moment that the foot would reach the ground)
  1225.     if(prevRunningState < 1.5f  &&  runningState >= 1.5f  &&  !MID_AIR)
  1226.       if((vel.x < 0.0f) == (acc.x < 0.0f)){
  1227.         play_sfx_footstep();
  1228.       }
  1229.   }
  1230. }
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236. shape::rect Player::move(f32 deltaX, f32 deltaY){
  1237.   rem.x += CLAMP(deltaX, -CANVSIZ_X,CANVSIZ_X);
  1238.   rem.y += CLAMP(deltaY, -CANVSIZ_Y,CANVSIZ_Y);
  1239.  
  1240.   shape::point delta(RND(rem.x), RND(rem.y));
  1241.   if(!delta.x && !delta.y) return getRect();
  1242.  
  1243.   rem.x -= delta.x;
  1244.   rem.y -= delta.y;
  1245.   shape::rect current = getRect();
  1246.   shape::rect end     = current;
  1247.   end += delta;
  1248.   shape::point newpos(current.x, current.y);
  1249.  
  1250.  
  1251.  
  1252.   //do a bresenham line to find the exact point of collision, before setting
  1253.    //pos to that (minus 1 step assuming a collision actually occurred)
  1254.   s32 d_x =  abs(delta.x);
  1255.   s32 d_y = -abs(delta.y);
  1256.   s32 s_x = (delta.x >= 0) ? 1 : -1;
  1257.   s32 s_y = (delta.y >= 0) ? 1 : -1;
  1258.   s32 e_1 = d_x + d_y;
  1259.  
  1260.   while(true){
  1261.     newpos.x = current.x; //(assumes that player isn't colliding
  1262.     newpos.y = current.y;  //with any subtiles initially)
  1263.  
  1264.     if(current.x == end.x  &&  current.y == end.y) break;
  1265.  
  1266.     s32 e_2 = e_1<<1;
  1267.  
  1268.     if(e_2 >= d_y){
  1269.       if(current.x == end.x) break;
  1270.       e_1 += d_y;
  1271.       current.x += s_x;
  1272.     }
  1273.  
  1274.     if(e_2 <= d_x){
  1275.       if(current.y == end.y) break;
  1276.       e_1 += d_x;
  1277.       current.y += s_y;
  1278.     }
  1279.  
  1280.     if(subtiles_overlapping(current)) break;
  1281.  
  1282.   }
  1283.  
  1284.  
  1285.   pos.x = newpos.x + current.w/2;
  1286.   pos.y = newpos.y + current.h/2;
  1287.  
  1288.   return getRect();
  1289.  
  1290. }
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296. void Player::kill(){
  1297.   if(dying) return;
  1298.   SFXPTR_PLAY(SFXPTR_DEATH);
  1299.  
  1300.   visible = false;
  1301.   dying   = true;
  1302.  
  1303.   //this will reset the death animation effect,
  1304.    //which will run now that gl_player.dying is true
  1305.   gl_death_prog = 0.0f;
  1306.  
  1307. }
  1308.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement