Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void handleEdgeWrap(){
- if(!gl_scene.scene)
- throw "gl_scene.scene == 0 (loadScene(>0) before calling handleEdgeWrap()!)";
- u16 new_scene_id = 0;
- bool call_loadObjects = false;
- if( gl_player.pos.x < 0 ){ //player went past west side
- gl_player.pos.x = CANVSIZ_X;
- new_scene_id = CURRENT_SCENE_PTR->edge_w;
- call_loadObjects = true;
- } else if(gl_player.pos.x > CANVSIZ_X){ //player went past east side
- gl_player.pos.x = 0;
- new_scene_id = CURRENT_SCENE_PTR->edge_e;
- call_loadObjects = true;
- }/* else if(gl_player.pos.y < 0 ){ //player went past north side
- gl_player.pos.y = CANVSIZ_Y;
- new_scene_id = CURRENT_SCENE_PTR->edge_n;
- call_loadObjects = true;
- } else if(gl_player.pos.y > CANVSIZ_Y){ //player went past south side
- gl_player.pos.y = 0;
- new_scene_id = CURRENT_SCENE_PTR->edge_s;
- call_loadObjects = true;
- }*/ //tbd: uncomment this when i start to use north and south edges
- if(new_scene_id ) loadScene(new_scene_id);
- if(call_loadObjects) loadObjects();
- }
- #define INDICATOR_SPACING 2
- static inline void drawAbilityIndicators(){
- shape::rect dst(INDICATOR_SPACING,INDICATOR_SPACING, 10,10);
- shape::rect src(0,0, 10,10);
- //shrink
- if(gl_player.has_shrink){
- //src.x = 0;
- gl_spritesheetAbilityIndicators->blitRect(&dst, &src, 0xff00ff);
- dst.x += 10+INDICATOR_SPACING;
- }
- //double jump
- if(gl_player.has_dbljmp){
- src.x = 10;
- gl_spritesheetAbilityIndicators->blitRect(&dst, &src, 0xff00ff);
- dst.x += 10+INDICATOR_SPACING;
- }
- //speed
- if(gl_player.has_speed){
- src.x = 20;
- gl_spritesheetAbilityIndicators->blitRect(&dst, &src, 0xff00ff);
- //dst.x += 10+INDICATOR_SPACING;
- }
- }
- void drawStuff_and_processObjects(){
- bool ro_back = false; //r[ender]o[only] objects that are !in_front
- bool ro_frnt = false; //same thing but only ones with in_front set instead
- //I Can't Believe It's Not Assembly!
- /*_clear_gray :*/ gl_win->clear(0x808080);
- _draw_bg : gl_scene.drawBg();
- /*_draw_mg :*/ gl_scene.drawTiles(false);
- /*_proc_obj_bk:*/ if(processObjects(false,ro_back)){ ro_back=true; goto _draw_bg; }
- /*_draw_player:*/ gl_player.blit();
- /*_draw_fg :*/ gl_scene.drawTiles(true);
- /*_proc_obj_fr:*/ if(processObjects(true ,ro_frnt)){ ro_back=ro_frnt=true; goto _draw_bg; }
- /*_draw_ablity:*/ drawAbilityIndicators();
- }
- //unit should be between 0.0f and 1.0f
- color::ARGB unit_to_ryg(f32 unit){
- unit = CLAMP(unit*2, 0.0f, 2.0f);
- u8 red = 255, green = 255;
- #define _RND(_v) ( (u8)( (_v)+0.5f ) )
- if(unit < 1.0f) green = _RND(255.0f*( unit));
- else red = _RND(255.0f*(2.0f-unit));
- #undef _RND
- return color::ARGB(red, green, 0, 0);
- }
- //assumes 8x8 monospaced with 1 pixel of spacing in both x and y
- shape::point get_text_size(const char* str){
- if(!str) throw "nullptr string was passed to get_text_size()";
- shape::point result(0,9);
- s32 current_width = 0;
- for(; *str != 0; ++str){
- if(*str != '\n'){
- current_width += 9;
- } else {
- result.x = MAX(result.x, current_width);
- result.y += 9;
- current_width = 0;
- }
- }
- result.x = MAX(result.x, current_width);
- if(!result.x) result.y = 0;
- return result;
- }
- //x&y determine the CENTER position of the text, not its top-left corner
- //calculates text_size if either text_size.x or .y is 0
- void drawTextBox(s32 x, s32 y, const char* str, shape::point text_size){
- if(!str) throw "nullptr string was passed to drawTextBox()";
- shape::rect box_rect(x,y, 0,0);
- if(!text_size.x || !text_size.y) text_size = get_text_size(str);
- box_rect.w = text_size.x+2;
- box_rect.h = text_size.y+2;
- box_rect.x -= box_rect.w/2;
- box_rect.y -= box_rect.h/2;
- gl_win->drawRectangles(&box_rect, 1, 0x000000);
- gl_win_drawRectEmpty(box_rect, 0x808080);
- gl_text->print(box_rect.x+2, box_rect.y+2, str);
- }
- #include <object.hpp>
- #include <player.hpp>
- #include <tile.hpp>
- using namespace kit;
- #define GET_OBJ(_type) _type* obj = (_type*)_obj_a
- #define GET_DST(_obj_ptr) { _obj_ptr->x, _obj_ptr->y, _obj_ptr->size.x, _obj_ptr->size.y }
- #define OBJIMG(_index) gl_objImg[_index]
- #define OBJIMG_LEVER_WALL OBJIMG(1)
- #define OBJIMG_ABILITY_SHRINK OBJIMG(2)
- #define OBJIMG_ABILITY_DBLJMP OBJIMG(3)
- #define OBJIMG_ABILITY_SPEED OBJIMG(4)
- #define OBJIMG_ABILITY_REMOVER OBJIMG(5)
- #define OBJIMG_SIGNPOST_WOOD OBJIMG(6)
- #define TXTLINE(_index) gl_text_lines[_index]
- //copy original state of object data to the active scene
- void loadObjects(bool forced, u16 scene_id){
- if(!scene_id && !gl_scene.scene)
- throw "gl_scene.scene == 0 (loadScene(>0) before calling loadObjects()!)";
- if(!scene_id) scene_id = gl_scene.scene;
- if(scene_id > gl_scenes_len) throw "scene_id > gl_scenes_len";
- SceneDescriptor* scene_current = gl_scenes[scene_id];
- Object* objsCache = gl_objsCache[scene_id];
- Object* objs = scene_current->objs;
- u16 objs_len = scene_current->objs_len;
- if(!forced){ //only copy object data whose persistence flag is false
- for(u32 i=0; i<objs_len; ++i){
- if(!objsCache[i].persistent) objsCache[i] = objs[i];
- }
- } else { //otherwise, copy all objects in scene
- for(u32 i=0; i<objs_len; ++i){
- objsCache[i] = objs[i];
- }
- }
- }
- #define CHECK_TYPE_NULL 0
- bool processObjects(bool in_front, bool render_only){
- bool scene_changed = false;
- Object* objs = gl_objsCache[gl_scene.scene];
- u16 objs_len = gl_scenes[gl_scene.scene]->objs_len;
- Object* obj;
- #if CHECK_TYPE_NULL == 1
- #define TYPE_CHECK && obj->type != 0
- #else
- #define TYPE_CHECK
- #endif
- if(!in_front){
- for(u32 i=0; i<objs_len; ++i){
- obj = &objs[i];
- if(!obj->in_front /*&&*/ TYPE_CHECK)
- scene_changed |= obj->update(obj, render_only);
- }
- } else {
- for(u32 i=0; i<objs_len; ++i){
- obj = &objs[i];
- if(obj->in_front /*&&*/ TYPE_CHECK)
- scene_changed |= obj->update(obj, render_only);
- }
- }
- #undef TYPE_CHECK
- if(!render_only) return scene_changed;
- else return false;
- }
- //do not use this object in a scene with more than 2 states
- //also, there can in theory be multiple 1lever(s) in a scene,
- //as long as they share the same values of scene_old&new
- struct _obj_1lever { //24B; 8x24px sprite
- u16 scene_old; //2B
- u16 scene_new; //2B
- u16 sfx_id; //2B
- //-END OF INIT DATA-
- bool init; //1B
- bool flipped; //1B
- Bitmap* img; //8B
- SoundEffect* sfx; //8B
- };
- bool obj_1lever(Object* _obj_a, bool render_only){
- GET_OBJ(_obj_1lever); //obj = _obj_a
- shape::rect rect_dst = GET_DST(_obj_a);
- shape::rect rect_src(0,0, 8,24);
- bool scene_changed = false;
- if(!obj->init){
- _obj_a->persistent = 1; //this object is always persistent
- obj->init = true;
- obj->flipped = false;
- obj->img = OBJIMG_LEVER_WALL;
- if(!obj->sfx_id){ //use default sound effect
- obj->sfx = SFXPTR_ACTIVATE_1;
- } else if(obj->sfx_id <= gl_sfx_len){ //use specified sound effect
- obj->sfx = SFXPTR(obj->sfx_id);
- } else { //no sound effect found
- obj->sfx = nullptr;
- //tbd: warn about nonexistent sound effect
- }
- }
- //if player is touching the object
- if(rects_overlapping(gl_player.getRect(), rect_dst)){
- rect_src.y = 24; //highlighted
- //if player activates the lever
- if(!render_only && CTRLSTATE_GET(down_p)){
- swapScene(obj->scene_old, obj->scene_new);
- obj->flipped ^= 1;
- scene_changed = true;
- SFXPTR_PLAY(obj->sfx);
- }
- }
- if(obj->flipped) rect_src.x = 8; //lever points down
- if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, 0xff00ff);
- return scene_changed;
- }
- //0 = shrink
- //1 = double jump
- //2 = speed
- struct _obj_ability { //24B; 24x24px sprite, 24 frames (spritesheet of 24x1)
- u8 which; //1B
- //-END OF INIT DATA-
- bool init; //1B
- u16 frameCounter; //2B
- u32 _padding32; //4B
- Bitmap* img; //8B
- bool* has_ability; //8B; ptr to bool that determines if ability is enabled
- };
- bool obj_ability(Object* _obj_a, bool render_only){
- GET_OBJ(_obj_ability); //obj = _obj_a
- shape::rect rect_dst = GET_DST(_obj_a);
- shape::rect rect_src(0,0, 24,24);
- if(!obj->init){
- _obj_a->persistent = 1; //this object is always persistent
- obj->init = true;
- obj->frameCounter = 23; //will roll over to 0 this iteration
- //this implementation is quite strange but whatever it works like a charm
- switch(obj->which){
- case 0 : obj->img = OBJIMG_ABILITY_SHRINK;
- obj->has_ability = &gl_player.has_shrink; break;
- case 1 : obj->img = OBJIMG_ABILITY_DBLJMP;
- obj->has_ability = &gl_player.has_dbljmp; break;
- case 2 : obj->img = OBJIMG_ABILITY_SPEED;
- obj->has_ability = &gl_player.has_speed; break;
- default: obj->img = gl_tileset_missing;
- obj->has_ability = nullptr;
- }
- }
- //if player is touching the object (and everything else is valid)
- if(!render_only) //&&
- if(obj->has_ability != nullptr && !(*obj->has_ability) &&
- rects_overlapping(gl_player.getRect(), rect_dst))
- {
- *obj->has_ability = true;
- SFXPTR_PLAY(SFXPTR_ABILITY_PICKUP);
- }
- //pick which frame in the animation to use
- if(obj->has_ability != nullptr){
- //increment animation's frame counter every 13 ticks, which makes for ~9.2fps
- if(!(gl_tickCounter%13)) obj->frameCounter = (obj->frameCounter+1)%24;
- rect_src.x = 24 * obj->frameCounter;
- if(*obj->has_ability) rect_src.y = 24; //otherwise it'll remain 0
- }
- //if the has_ability pointer is invalid, disable magenta transparency, since
- //the 'missing tile' bitmap uses the color magenta
- color::ARGB t_color = (obj->has_ability != nullptr) ? 0xff00ff : 0x80000000;
- if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, t_color);
- return false;
- }
- //0 = shrink
- //1 = double jump
- //2 = speed
- struct _obj_ability_remover { //24B; 24x24px sprite, spritesheet of 3x1
- u8 which; //1B
- bool dontReset; //1B; disables resetting player scale back to 2 if .which == 0, etc.
- //-END OF INIT DATA-
- bool init; //1B
- u8 _padding8; //1B
- u32 _padding32; //4B
- Bitmap* img; //8B
- bool* has_ability; //8B; ptr to bool that determines if ability is enabled
- };
- bool obj_ability_remover(Object* _obj_a, bool render_only){
- GET_OBJ(_obj_ability_remover); //obj = _obj_a
- shape::rect rect_dst = GET_DST(_obj_a);
- shape::rect rect_src(24*obj->which,0, 24,24);
- if(!obj->init){
- _obj_a->persistent = 1; //this object is always persistent
- obj->init = true;
- obj->img = OBJIMG_ABILITY_REMOVER;
- if(!obj->img) obj->img = gl_tileset_missing; //this shouldn't happen ever
- switch(obj->which){
- case 0 : obj->has_ability = &gl_player.has_shrink; break;
- case 1 : obj->has_ability = &gl_player.has_dbljmp; break;
- case 2 : obj->has_ability = &gl_player.has_speed; break;
- default: obj->has_ability = nullptr;
- }
- }
- //if player is touching the object (and everything else is valid)
- if(!render_only) //&&
- if(obj->has_ability != nullptr && (*obj->has_ability) &&
- rects_overlapping(gl_player.getRect(), rect_dst))
- {
- *obj->has_ability = false;
- SFXPTR_PLAY(SFXPTR_ABILITY_REMOVED);
- if(!obj->dontReset)
- switch(obj->which){
- //(case 0 should only fail if i place this object in a subtile-wide space)
- case 0 : gl_player.setScale(2.0f); break;
- //case 1 : //(not used)
- case 2 : gl_player.enforceMaxVel = true; break;
- default:;
- }
- }
- //if the has_ability pointer is invalid, disable magenta transparency, since
- //the 'missing tile' bitmap uses the color magenta
- color::ARGB t_color = (obj->has_ability != nullptr) ? 0xff00ff : 0x80000000;
- if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, t_color);
- return false;
- }
- //(not specifying w or h results in the default of _obj_a->size.x/y being used!)
- struct _obj_generic_sprite { //16B
- u16 which; //2B; objimg index
- u8 w,h; //2B; width and height of source sprite (1B each)
- u8 numFrames; //1B; <2 for no animation (static sprite)
- u8 tick_delay; //1B; 'how many ticks per frame?' (ignored if num_frames < 2)
- //-END OF INIT DATA-
- bool init; //1B
- u8 frameCounter; //1B
- Bitmap* img; //8B
- };
- bool obj_generic_sprite(Object* _obj_a, bool render_only){
- GET_OBJ(_obj_generic_sprite); //obj = _obj_a
- shape::rect rect_dst = GET_DST(_obj_a);
- shape::rect rect_src(0,0, obj->w,obj->h);
- if(!obj->init){
- _obj_a->persistent = 1; //this object is always persistent
- obj->init = true;
- obj->frameCounter = obj->numFrames-1; //will roll over to 0 this iteration
- if(obj->which <= gl_objImg_len) obj->img = OBJIMG(obj->which);
- if(!obj->img){
- //if i somehow have more than 65k object images,
- //i have bigger problems to worry about
- obj->which = KIT_U16_MAX;
- obj->img = gl_tileset_missing;
- }
- //if w/h are 0, then default the src size to the dst size
- if(!obj->w){
- obj->w = (u8)_obj_a->size.x;
- rect_src.w = obj->w;
- }
- if(!obj->h){
- obj->h = (u8)_obj_a->size.y;
- rect_src.h = obj->h;
- }
- }
- //pick which frame in the animation to use
- if(obj->numFrames > 1){
- //increment animation's frame counter every tick_delay ticks
- if(!(gl_tickCounter%obj->tick_delay))
- obj->frameCounter = (obj->frameCounter+1)%obj->numFrames;
- //(which horizontal slot in the spritesheet to use, technically)
- rect_src.x = rect_src.w * obj->frameCounter;
- }
- color::ARGB t_color = (obj->which != KIT_U16_MAX) ? 0xff00ff : 0x80000000;
- if(obj->img) obj->img->blitRect(&rect_dst, &rect_src, t_color);
- return false;
- }
- struct _obj_msgbox { //24B
- s16 pos_x, pos_y; //4B (2B each)
- u16 which; //2B; gl_text_lines index
- bool show_always; //1B; always display box, instead of on player collide
- //-END OF INIT DATA-
- bool init; //1B
- shape::point str_size; //8B
- const char* str; //8B
- };
- bool obj_msgbox(Object* _obj_a, bool render_only){
- GET_OBJ(_obj_msgbox); //obj = _obj_a
- shape::rect rect_collider = GET_DST(_obj_a);
- if(!obj->init){
- _obj_a->persistent = 1; //this object is always persistent
- obj->init = true;
- if(obj->which <= gl_text_lines_len) obj->str = TXTLINE(obj->which);
- if(!obj->str) obj->str = TXTLINE(0); // = "<INVALID TEXT ID>"
- obj->str_size = get_text_size(obj->str);
- }
- if(obj->show_always ||
- rects_overlapping(gl_player.getRect(), rect_collider))
- {
- drawTextBox(obj->pos_x, obj->pos_y, obj->str, obj->str_size);
- }
- return false;
- }
- #ifndef TEXT_LINES_DEFINITION
- extern size_t gl_text_lines_len;
- extern const char* gl_text_lines[];
- #else
- size_t gl_text_lines_len;
- const char* gl_text_lines[] = {
- /*0*/ "\
- <INVALID TEXT ID>",
- /*1*/ "\
- this is some pretty cool text! :D",
- //(this must be here in order for the length
- //of this array to be properly calculated!)
- nullptr,
- };
- #endif /* TEXT_LINES_DEFINITION */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement