Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <player.hpp>
- #include <tile.hpp>
- #include <math.h>
- using namespace kit;
- bool Player::setScale(kit::f32 scale_new){
- kit::f32 scale_old = scale;
- scale = MAX(scale_new, 0.2f); //for a minimum of 2x2 pixels
- kit::shape::rect player_rect = getRect();
- kit::shape::point delta;
- //player was probably pushed into the floor if the scale increased,
- //so attempt to move the player out of any potential subtiles
- if(subtiles_overlapping(player_rect, &delta))
- player_rect += delta;
- //if the previous movement didn't result in the
- //player entering empty space, return false
- if(subtiles_overlapping(player_rect, nullptr)){
- scale = scale_old; //(revert the scale back to what it was originally too)
- return false;
- } else { //otherwise, apply those movement changes to pos, and return true
- pos += delta;
- return true;
- }
- }
- #define SPRSHEET_ADJUST(_v) ((_v)*(8+1)) //8px +1 for one pixel of spacing
- void Player::blit(){
- if(!visible || scale<=0.0f) return;
- shape::rect dst = getRect();
- shape::rect src(0,0, 8,8);
- if(confused ) src.y += SPRSHEET_ADJUST(1);
- if(!facingRight) src.y += SPRSHEET_ADJUST(2);
- if(MID_AIR){ //mid-air
- if(fabsf(vel.x) > PLAYER_NEUTRAL){ //going fast horizontally
- if(vel.y<=0) src.x = SPRSHEET_ADJUST(2); //-Y; back leg extended
- else src.x = SPRSHEET_ADJUST(8); //+Y; front leg extended
- } else { //going slow (or not at all) horizontally
- if( vel.y <-PLAYER_NEUTRAL) src.x = SPRSHEET_ADJUST(1); //-Y; back leg down
- else if(vel.y > PLAYER_NEUTRAL) src.x = SPRSHEET_ADJUST(4); //+Y; front leg down
- else src.x = SPRSHEET_ADJUST(7); //0Y; both legs up
- }
- } else { //on the ground
- if(vel.x < 0 && acc.x > 0){ //slowing down while moving left
- if(fabsf(vel.x) > PLAYER_NEUTRAL){ //going fast horizontally
- if(facingRight) src.x = SPRSHEET_ADJUST(2); //back leg extended
- else src.x = SPRSHEET_ADJUST(8); //front leg extended
- } else { //going slow (or not at all) horizontally
- if(facingRight) src.x = SPRSHEET_ADJUST(1); //back leg down
- else src.x = SPRSHEET_ADJUST(4); //front leg down
- }
- } else if(vel.x > 0 && acc.x < 0){ //slowing down while moving right
- if(fabsf(vel.x) > PLAYER_NEUTRAL){ //going fast horizontally
- if(facingRight) src.x = SPRSHEET_ADJUST(8); //front leg extended
- else src.x = SPRSHEET_ADJUST(2); //back leg extended
- } else { //going slow (or not at all) horizontally
- if(facingRight) src.x = SPRSHEET_ADJUST(4); //front leg down
- else src.x = SPRSHEET_ADJUST(1); //back leg down
- }
- } else if(fabsf(vel.x) > PLAYER_NEUTRAL){ //moving forward
- src.x = SPRSHEET_ADJUST(1 + RND(runningState)%6);
- } else if(acc.x < 0){ //standing still while accelerating left
- if(facingRight) src.x = SPRSHEET_ADJUST(4); //front leg down
- else src.x = SPRSHEET_ADJUST(1); //back leg down
- } else if(acc.x > 0){ //standing still while accelerating right
- if(facingRight) src.x = SPRSHEET_ADJUST(1); //back leg down
- else src.x = SPRSHEET_ADJUST(4); //front leg down
- } else { //standing still without acceleration
- src.x = SPRSHEET_ADJUST(0); //technically redundant, but left here for clarity
- }
- }
- //0xff00ff for magenta as the transparency color
- gl_spritesheetPlayer->blitRect(&dst, &src, 0xff00ff);
- }
- //acc, visible, and confused are not modified here
- void Player::update(){
- vel.x += (MID_AIR) ? acc.x*PLAYER_AIR_FRICTION : acc.x;
- vel.y += acc.y;
- if(enforceMaxVel){
- vel.x = CLAMP(vel.x, -VELX_MAX, VELX_MAX);
- vel.y = CLAMP(vel.y, -VELY_MAX, VELY_MAX);
- }
- {
- //tbd: remove collision_type, CollisionEnum, and by extension move's
- //return if it turns out that it's unnecessary
- //#define collision_type(_type) ((collision&(_type))!=0)
- /*CollisionEnum collision =*/ move(vel.x, vel.y);
- //(maybe even have move return the player's new rect,
- //so getRect() doesn't need to be called below VV)
- shape::rect collider_ceiling = getRect();
- shape::rect collider_floor = collider_ceiling;
- shape::rect collider_left = collider_ceiling;
- shape::rect collider_right = collider_ceiling;
- collider_ceiling.y -= 1;
- collider_ceiling.h = 1;
- collider_floor.y += collider_floor.h;
- collider_floor.h = 1;
- if(vel.y<0.0f && subtiles_overlapping(collider_ceiling)){
- vel.y = fabsf(vel.y)/2;
- ++ticksInAir;
- } else if(vel.y>0.0f && subtiles_overlapping(collider_floor)){
- play_sfx_landing(ticksInAir);
- if(ticksInAir) runningState = 2.5f;
- ticksInAir = 0;
- jumped = false;
- vel.y = 0.0f;
- } else {
- ++ticksInAir;
- }
- collider_left.x -= 1;
- collider_left.w = 1;
- collider_right.x += collider_right.w;
- collider_right.w = 1;
- if(vel.x<0.0f && subtiles_overlapping(collider_left ) ||
- vel.x>0.0f && subtiles_overlapping(collider_right) )
- {
- vel.x = 0.0f;
- runningState = 0.0f;
- }
- gl_win->clear(0x7f7f7f); //should be redundant
- gl_scene.drawBg();
- gl_scene.drawTiles(false);
- gl_player.blit();
- gl_scene.drawTiles(true);
- //gl_win_drawRectEmpty(collider_ceiling, 0x00ffff);
- //gl_win_drawRectEmpty(collider_floor, 0xff00ff);
- //gl_win_drawRectEmpty(collider_left, 0xffff00);
- //gl_win_drawRectEmpty(collider_right, 0xffffff);
- }
- //manage horizontal velocity
- {
- if(fabsf(vel.x)<0.05f && acc.x==0) vel.x = 0.0f;
- //if on ground while moving horizontally
- if(ticksInAir <= 1 && vel.x != 0){
- facingRight = vel.x > 0;
- if(ticksInAir <= 1 && acc.x == 0){
- vel.x -= (vel.x>0) ? PLAYER_SPEED*PLAYER_GND_FRICTION
- : -PLAYER_SPEED*PLAYER_GND_FRICTION;
- }
- }
- }
- //handle incrementing run animations
- {
- f32 prevRunningState = runningState;
- if(fabsf(vel.x) > PLAYER_NEUTRAL) runningState += fabsf(vel.x)*PLAYER_RUN_MUL;
- else runningState = 0.0f;
- runningState = fmodf(fabsf(runningState), 6.0f);
- //used to indicate that a foot step sound effect should play
- //(1.5 instead of 2, since 1.5 would round up to integer state 2,
- //which is the actual moment that the foot would reach the ground)
- if(prevRunningState < 1.5f && runningState >= 1.5f && !MID_AIR)
- play_sfx_footstep();
- }
- }
- CollisionEnum Player::move(f32 deltaX, f32 deltaY){
- rem.x += CLAMP(deltaX, -CANVSIZ_X,CANVSIZ_X);
- rem.y += CLAMP(deltaY, -CANVSIZ_Y,CANVSIZ_Y);
- shape::point delta(RND(rem.x), RND(rem.y));
- if(!delta.x && !delta.y) return COLLISION_NONE;
- rem.x -= delta.x;
- rem.y -= delta.y;
- shape::rect current = getRect();
- shape::rect end = current;
- end += delta;
- shape::point newpos(current.x, current.y);
- //do a bresenham line to find the exact point of collision, before setting
- //pos to that (minus 1 step assuming a collision actually occurred)
- s32 d_x = abs(delta.x);
- s32 d_y = -abs(delta.y);
- s32 s_x = (delta.x >= 0) ? 1 : -1;
- s32 s_y = (delta.y >= 0) ? 1 : -1;
- s32 e_1 = d_x + d_y;
- while(true){
- newpos.x = current.x; //(assumes that player isn't colliding
- newpos.y = current.y; //with any subtiles initially)
- if(current.x == end.x && current.y == end.y) break;
- s32 e_2 = e_1<<1;
- if(e_2 >= d_y){
- if(current.x == end.x) break;
- e_1 += d_y;
- current.x += s_x;
- }
- if(e_2 <= d_x){
- if(current.y == end.y) break;
- e_1 += d_x;
- current.y += s_y;
- }
- if(subtiles_overlapping(current, &delta)) break;
- }
- pos.x = newpos.x + current.w/2;
- pos.y = newpos.y + current.h/2;
- s32 collision_result;
- collision_result = (delta.x<0) << 3 | (delta.x!=0) << 2;
- collision_result |= (delta.y<0) << 1 | (delta.y!=0) << 0;
- return (CollisionEnum)collision_result;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement