diff --git a/data/test.gif b/data/test.gif index 1b7a97e..6efac00 100644 Binary files a/data/test.gif and b/data/test.gif differ diff --git a/source/actor.cpp b/source/actor.cpp index d63699b..03eeb56 100644 --- a/source/actor.cpp +++ b/source/actor.cpp @@ -4,6 +4,12 @@ namespace actor { + uint8_t anims[2][4] = { + {0, 1, 0, 2}, + {0, 1, 2, 3} + }; + static uint8_t anim_frame=0; + actor_t *first = nullptr; actor_t *dirty = nullptr; @@ -19,6 +25,7 @@ namespace actor act->size = s; act->bmp_rect = r; act->bmp_offset = o; + act->below = act->above = nullptr; act->prev = act->next = nullptr; return act; } @@ -36,6 +43,44 @@ namespace actor return check_2d_collision(obj1, obj2) && (obj1->pos.z==obj2->pos.z+obj2->size.z); } + actor_t *any_above_me(actor_t *act) + { + actor_t *other = first; + while (other) + { + if (is_above(other, act)) return other; + other = other->next; + if (other == act) other = other->next; + } + other = dirty; + while (other) + { + if (is_above(other, act)) return other; + other = other->next; + if (other == act) other = other->next; + } + return nullptr; + } + + actor_t *any_below_me(actor_t *act) + { + actor_t *other = first; + while (other) + { + if (is_above(act, other)) return other; + other = other->next; + if (other == act) other = other->next; + } + other = dirty; + while (other) + { + if (is_above(act, other)) return other; + other = other->next; + if (other == act) other = other->next; + } + return nullptr; + } + void setDirty(actor_t *act, const bool force) { if (act->prev==nullptr && act != first && !force) return; @@ -51,6 +96,8 @@ namespace actor void reorder() { + anim_frame=(anim_frame+1)%4; + while (dirty) { //const int z_index = dirty->pos.x + dirty->pos.y + dirty->pos.z; @@ -60,7 +107,8 @@ namespace actor while (true) { //const int z_index2 = current->pos.x + current->pos.y + current->pos.z; - if ((dirty->pos.z < current->pos.z+current->size.z) && (current->pos.x+current->size.x+current->pos.y > dirty->pos.x+dirty->size.x+dirty->pos.y)) + //if ((dirty->pos.z < current->pos.z+current->size.z) && (current->pos.x+current->size.x+current->pos.y > dirty->pos.x+dirty->size.x+dirty->pos.y)) + if (current->pos.x+current->pos.y>dirty->pos.y+dirty->pos.x || current->pos.z>dirty->pos.z) { dirty->prev = current->prev; current->prev = dirty; @@ -99,12 +147,28 @@ namespace actor void updateUserInput(actor_t *act) { bool moving = false; - if (input::keyDown(SDL_SCANCODE_LEFT) && act->pos.x>0) { act->push |= PUSH_XN; moving = true; } - if (input::keyDown(SDL_SCANCODE_RIGHT) && act->pos.x<56) { act->push |= PUSH_XP; moving = true; } - if (input::keyDown(SDL_SCANCODE_UP) && act->pos.y>0) { act->push |= PUSH_YN; moving = true; } - if (input::keyDown(SDL_SCANCODE_DOWN) && act->pos.y<56) { act->push |= PUSH_YP; moving = true; } + if (input::keyDown(SDL_SCANCODE_LEFT) && act->pos.x>0) { act->push |= PUSH_XN; act->orient=PUSH_XN; moving = true; } + if (input::keyDown(SDL_SCANCODE_RIGHT) && act->pos.x<56) { act->push |= PUSH_XP; act->orient=PUSH_XP; moving = true; } + if (input::keyDown(SDL_SCANCODE_UP) && act->pos.y>0) { act->push |= PUSH_YN; act->orient=PUSH_YN; moving = true; } + if (input::keyDown(SDL_SCANCODE_DOWN) && act->pos.y<56) { act->push |= PUSH_YP; act->orient=PUSH_YP; moving = true; } + if (input::keyDown(SDL_SCANCODE_SPACE) && act->react_mask==0 && (act->pos.z==0 || act->below)) { act->react_mask=1; act->react_push=0; act->flags &= uint8_t(~FLAG_GRAVITY); } if (input::keyDown(SDL_SCANCODE_Z) && act->pos.z>0) { act->push |= PUSH_ZN; moving = true; } if (input::keyDown(SDL_SCANCODE_A) && act->pos.z<56) { act->push |= PUSH_ZP; moving = true; } + + if (act->react_mask) + { + if (act->react_push<8) + { + act->pos.z++; + act->react_push++; + } + else + { + act->react_mask=0; + act->flags |= FLAG_GRAVITY; + } + } + if (moving) { act->flags |= FLAG_ANIMATED; @@ -164,22 +228,26 @@ namespace actor // TODO break; } + act->orient = act->mov_push; } void updatePushable(actor_t *act) { if (act->push & PUSH_ZP) { - act->pos.z++; - actor::actor_t *other = actor::get_collision(act); - if (other && other->flags & FLAG_PUSHABLE) - other->push |= PUSH_ZP; - if (act->pos.z>56) + if (act->pos.z>=56) { - act->pos.z--; if (act->flags & FLAG_MOVING) changeMoving(act); } else { + actor_t *now = act; + do { + actor::actor_t *other = actor::any_above_me(now); + now->pos.z++; + //if (other) other->pos.z++; + now = other; + } while (now); + actor::setDirty(act); } } @@ -195,6 +263,7 @@ namespace actor } else { + if (act->above && act->above->flags & FLAG_PUSHABLE) act->above->push |= PUSH_XN; actor::setDirty(act); } } @@ -210,6 +279,7 @@ namespace actor } else { + if (act->above && act->above->flags & FLAG_PUSHABLE) act->above->push |= PUSH_XP; actor::setDirty(act); } } @@ -225,6 +295,7 @@ namespace actor } else { + if (act->above && act->above->flags & FLAG_PUSHABLE) act->above->push |= PUSH_YN; actor::setDirty(act); } } @@ -240,6 +311,7 @@ namespace actor } else { + if (act->above && act->above->flags & FLAG_PUSHABLE) act->above->push |= PUSH_YP; actor::setDirty(act); } } @@ -249,7 +321,7 @@ namespace actor actor::actor_t *other = actor::get_collision(act); if (act->pos.z<0 || other) { - if (other && other->flags & FLAG_PUSHABLE) other->push |= PUSH_ZN; + //if (other && other->flags & FLAG_PUSHABLE) other->push |= PUSH_ZN; act->pos.z++; if (act->flags & FLAG_MOVING) changeMoving(act); } @@ -276,6 +348,25 @@ namespace actor } } + void updateGravity(actor_t *act) + { + if (act->pos.z == 0) return; + if (act->below) + { + if (is_above(act, act->below)) return; + act->below->above = nullptr; + act->below = nullptr; + } + actor_t *below = any_below_me(act); + if (below) + { + act->below = below; + below->above = act; + return; + } + act->pos.z--; + } + void update(actor_t *act, const bool update_all) { actor_t *next = act->next; @@ -284,6 +375,7 @@ namespace actor if (act->flags & FLAG_MOVING) updateMoving(act); //if (act->flags & FLAG_PUSHABLE) updatePushable(act); + if (act->flags & FLAG_GRAVITY) updateGravity(act); if (act->flags & FLAG_REACTIVE) updateReactive(act); act->push = PUSH_NONE; @@ -291,12 +383,34 @@ namespace actor if (update_all && next) update(next); } + void print(int x, int y, int num) + { + int digits=0; + int n = num; + while (n>0) {n=n/10;digits++;} + x=x+digits*4; + while (num>0) + { + draw::draw(x,y,5,7,(num%10)*5,120); + num=num/10; + x=x-4; + } + } + void draw(actor_t *act, const bool draw_all) { if (!act) return; const int x = 148-act->bmp_offset.x + act->pos.x*2 - act->pos.y*2; const int y = 91-act->bmp_offset.y + act->pos.x + act->pos.y - act->pos.z*2; - draw::draw(x, y, act->bmp_rect.w, act->bmp_rect.h, act->bmp_rect.x, act->bmp_rect.y); + + const bool flip = ( (act->flags & FLAG_ORIENTABLE) && (act->orient==PUSH_XN || act->orient==PUSH_YP) ) ? DRAW_FLIP_HORIZONTAL : DRAW_FLIP_NONE; + const int oo = ( (act->flags & FLAG_ORIENTABLE) && (act->orient==PUSH_XN || act->orient==PUSH_YN) ) ? act->bmp_rect.h : 0; + + const int ao = (act->flags & FLAG_ANIMATED) ? anims[act->anim_cycle][anim_frame]*act->bmp_rect.w : 0; + + draw::draw(x, y, act->bmp_rect.w, act->bmp_rect.h, act->bmp_rect.x+ao, act->bmp_rect.y+oo, flip); + print(x,y,act->pos.x+act->pos.y); + print(x+10,y,act->pos.z); if (draw_all && act->next) draw(act->next); } diff --git a/source/actor.h b/source/actor.h index 92c0468..2c29ce6 100644 --- a/source/actor.h +++ b/source/actor.h @@ -9,6 +9,7 @@ #define FLAG_ANIMATED 16 #define FLAG_ORIENTABLE 32 #define FLAG_DEADLY 64 +#define FLAG_GRAVITY 128 #define PUSH_NONE 0 #define PUSH_XP 1 @@ -42,6 +43,9 @@ namespace actor vec3_t pos; vec3_t size; + uint8_t orient; + uint8_t anim_cycle; + uint8_t flags; uint8_t push; @@ -51,6 +55,9 @@ namespace actor uint8_t movement; uint8_t mov_push; + actor_t *below; + actor_t *above; + actor_t *prev; actor_t *next; }; diff --git a/source/main.cpp b/source/main.cpp index 8c7c761..fb9ff29 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -15,48 +15,29 @@ void game::init() draw::loadPalette("test.gif"); game::setUpdateTicks(64); - box = actor::create({16,16,0}, {8,8,8}, {32,0,32,32}, {0,32}); + box = actor::create({16,16,0}, {8,8,4}, {64,0,32,24}, {0,24}); box->flags = FLAG_MOVING;// | FLAG_PUSHABLE; - box->movement = MOV_Z; - box->mov_push = PUSH_ZP; + box->movement = MOV_X; + box->mov_push = PUSH_XP; actor::setDirty(box, true); box = actor::create({32,32,16}, {8,8,8}, {32,0,32,32}, {0,32}); - box->flags = FLAG_PUSHABLE; + box->flags = FLAG_PUSHABLE | FLAG_GRAVITY; box->movement = MOV_CW; box->mov_push = PUSH_XN; actor::setDirty(box, true); - box = actor::create({16,16,16}, {8,8,8}, {32,0,32,32}, {0,32}); - box->flags = FLAG_HERO | FLAG_PUSHABLE; + box = actor::create({16,16,8}, {8,8,8}, {0,32,20,32}, {-6,38}); + box->flags = FLAG_HERO | FLAG_PUSHABLE | FLAG_GRAVITY | FLAG_ORIENTABLE | FLAG_ANIMATED; actor::setDirty(box, true); actor::reorder(); } int sx=1, sy=0; + bool game::loop() { - /*if (input::keyDown(SDL_SCANCODE_LEFT) && box->pos.x>0) { - box->pos.x--; - actor::actor_t *other = actor::get_collision(box); - if (other) - { - other->push |= 1; - box->pos.x++; - } - else - { - actor::setDirty(box); - } - } - - if (input::keyDown(SDL_SCANCODE_RIGHT) && box->pos.x<42) { box->pos.x++; actor::setDirty(box); } - if (input::keyDown(SDL_SCANCODE_UP) && box->pos.y>0) { box->pos.y--; actor::setDirty(box); } - if (input::keyDown(SDL_SCANCODE_DOWN) && box->pos.y<42) { box->pos.y++; actor::setDirty(box); } - if (input::keyDown(SDL_SCANCODE_Z) && box->pos.z>0) { box->pos.z--; actor::setDirty(box); } - if (input::keyDown(SDL_SCANCODE_A) && box->pos.z<42) { box->pos.z++; actor::setDirty(box); }*/ - actor::update(actor::getFirst()); actor::reorder();