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;
- shape::fpoint curve_point(0.75f, 0.05f);
- f32 hvel_speed = .15;
- #define INTERP_FPOINT(_a, _b, _t) \
- shape::fpoint( LERP((_a).x,(_b).x,(_t)), LERP((_a).y,(_b).y,(_t)) )
- shape::fpoint movement_bezier(f32 t){
- shape::fpoint p_b = curve_point;
- shape::fpoint p_a(0.0f , 0.0f );
- shape::fpoint p_c(1.0f-p_b.x, 1.0f-p_b.y);
- shape::fpoint p_d(1.0f , 1.0f );
- shape::fpoint p_ab = INTERP_FPOINT(p_a, p_b, t);
- shape::fpoint p_bc = INTERP_FPOINT(p_b, p_c, t);
- shape::fpoint p_cd = INTERP_FPOINT(p_c, p_d, t);
- shape::fpoint p_abc = INTERP_FPOINT(p_ab, p_bc, t);
- shape::fpoint p_bcd = INTERP_FPOINT(p_bc, p_cd, t);
- shape::fpoint p_abcd = INTERP_FPOINT(p_abc, p_bcd, t);
- return p_abcd;
- }
- static f32 _get_movement_mul(f32 v, bool accelerating){
- //gl_player.enforceMaxVel = false;
- f32 v_old = v;
- v = fabsf(v);
- //do a bezier curve thing
- if(gl_player.enforceMaxVel){
- v = MIN(v, 1.0f); //now v is 0.0f -> 1.0f
- v = movement_bezier(v).y;
- }
- return v * ((v_old<0.0f) ? -1.0f : 1.0f );
- }
- //assumes n >= 0
- static inline void _put_closer_to_0(f32& v, f32 n){
- if( v < 0) v += n;
- else if(v > 0) v -= n;
- }
- bool Player::setScale(f32 scale_new){
- f32 scale_old = scale;
- scale = MAX(scale_new, 0.2f); //for a minimum of 2x2 pixels
- shape::rect player_rect = getRect();
- 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
- shape::rect Player::blit(bool only_return_src_rect){
- shape::rect src(0,0, 8,8);
- if(confused ) src.y += SPRSHEET_ADJUST(1);
- if(!facingRight) src.y += SPRSHEET_ADJUST(2);
- if(!only_return_src_rect &&
- (!visible || scale<=0.0f))
- {
- return src;
- }
- shape::rect dst = getRect();
- shape::fpoint rvel = get_rvel();
- if(MID_AIR){ //mid-air
- if(fabsf(rvel.x) > PLAYER_NEUTRAL){ //going fast horizontally
- if(rvel.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( rvel.y <-PLAYER_NEUTRAL) src.x = SPRSHEET_ADJUST(1); //-Y; back leg down
- else if(rvel.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(rvel.x < 0 && hacc > 0){ //slowing down while moving left
- if(fabsf(rvel.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(rvel.x > 0 && hacc < 0){ //slowing down while moving right
- if(fabsf(rvel.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(rvel.x) > PLAYER_NEUTRAL){ //moving forward
- src.x = SPRSHEET_ADJUST(1 + RND(runningState)%6);
- } else if(hacc < 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(hacc > 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
- }
- }
- //if enforceMaxVel is false, put a kind of highlight effect onto the player
- if(!enforceMaxVel && !only_return_src_rect){
- shape::rect highlight_dst = dst;
- shape::rect highlight_src = src;
- highlight_dst.x -= 1;
- highlight_dst.y -= 1;
- highlight_dst.w += 2;
- highlight_dst.h += 2;
- highlight_src.y += SPRSHEET_ADJUST(4);
- gl_spritesheetPlayer->blitRect(&highlight_dst, &highlight_src, 0xff00ff);
- }
- //0xff00ff for magenta as the transparency color
- if(!only_return_src_rect)
- gl_spritesheetPlayer->blitRect(&dst, &src, 0xff00ff);
- return src;
- }
- //visible, and confused are not modified here
- void Player::update(){
- if(dying) return;
- bool accelerating = going_left^going_right;
- if(accelerating){
- if( going_left ) hacc = -1;
- else if(going_right) hacc = 1;
- if(confused) hacc = -hacc;
- f32 acc_x = hvel_speed*hacc;
- if(enforceMaxVel)
- hvel += (MID_AIR) ? acc_x*PLAYER_AIR_FRICTION : acc_x;
- else
- hvel += (MID_AIR) ? acc_x*PLAYER_AIR_FRICTION*0.1f : acc_x*0.1f;
- } else { //decelerate
- if(enforceMaxVel)
- _put_closer_to_0(hvel, hvel_speed);
- if(fabsf(hvel) < PLAYER_NEUTRAL){
- hacc = 0;
- hvel = 0.0f;
- runningState = 0.0f;
- }
- }
- if(enforceMaxVel){
- hvel = CLAMP( hvel, -1.0f, 1.0f);
- vel.y = CLAMP(vel.y, -PLAYER_VELY_MAX, PLAYER_VELY_MAX);
- }
- _hvel = _get_movement_mul(hvel, accelerating) * PLAYER_VELX_MAX;
- shape::fpoint rvel = get_rvel();
- shape::rect new_rect = getRect();
- shape::rect collider_ceiling, collider_floor;
- shape::rect collider_left = new_rect;
- shape::rect collider_right = new_rect;
- collider_left.x -= 1;
- collider_left.w = 1;
- collider_right.x += collider_right.w;
- collider_right.w = 1;
- //touching a wall
- if((rvel.x<0.0f && subtiles_overlapping(collider_left )) ||
- (rvel.x>0.0f && subtiles_overlapping(collider_right)) )
- {
- _hvel = hvel = 0.0f;
- runningState = 0.0f;
- rvel = get_rvel();
- }
- //update position
- {
- new_rect = move(rvel.x, rvel.y);
- collider_ceiling = new_rect;
- collider_floor = new_rect;
- collider_left = new_rect;
- collider_right = new_rect;
- collider_ceiling.y -= 1;
- collider_ceiling.h = 1;
- collider_floor.y += collider_floor.h;
- collider_floor.h = 1;
- //touching the ceiling
- if(vel.y<0.0f && subtiles_overlapping(collider_ceiling)){
- vel.y = fabsf(vel.y)/2;
- ++ticksInAir;
- //touching the floor
- } else if(vel.y>0.0f && subtiles_overlapping(collider_floor)){
- if(sfx_landing){
- sfx_landing->volL = (fabsf(vel.y)/PLAYER_VELY_MAX)*PLAYER_LANDING_VOLUME;
- sfx_landing->volR = sfx_landing->volL;
- play_sfx_landing(ticksInAir);
- }
- if(ticksInAir) runningState = 2.5f;
- ticksInAir = 0;
- first_jmp = false;
- second_jmp = false;
- vel.y = 0.0f;
- //mid-air
- } else {
- ++ticksInAir;
- }
- collider_left.x -= 1;
- collider_left.w = 1;
- collider_right.x += collider_right.w;
- collider_right.w = 1;
- //touching a wall
- if( rvel.x<0.0f && subtiles_overlapping(collider_left)){
- hvel = vel.x = 0.0f;
- runningState = 0.0f;
- } else if(rvel.x>0.0f && subtiles_overlapping(collider_right)){
- hvel = vel.x = 0.0f;
- runningState = 0.0f;
- }
- }
- //manage horizontal velocity
- {
- if(fabsf(hvel)<PLAYER_NEUTRAL && !hacc){
- hvel = 0.0f;
- runningState = 0.0f;
- }
- //if on ground while moving horizontally (referring to rvel.x)
- if(ticksInAir <= 1 && fabsf(rvel.x) > 0.0f){
- facingRight = rvel.x >= 0.0f;
- vel.x *= PLAYER_GND_FRICTION;
- if(fabsf(vel.x)<PLAYER_NEUTRAL) vel.x = 0.0f;
- }
- }
- //handle incrementing run animations
- {
- f32 prevRunningState = runningState;
- if(fabsf(_hvel) >= PLAYER_NEUTRAL) runningState += fabsf(_hvel)*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)
- if((_hvel < 0.0f) == (hacc < 0)){
- play_sfx_footstep();
- }
- }
- }
- shape::rect 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 getRect();
- 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)) break;
- }
- pos.x = newpos.x + current.w/2;
- pos.y = newpos.y + current.h/2;
- return getRect();
- }
- void Player::kill(){
- if(dying) return;
- SFXPTR_PLAY(SFXPTR_DEATH);
- visible = false;
- dying = true;
- //this will reset the death animation effect,
- //which will run now that gl_player.dying is true
- gl_death_prog = 0.0f;
- }
- #define MCSIZE 96
- #define INTERP_FPOINT(_a, _b, _t) \
- shape::fpoint( LERP((_a).x,(_b).x,(_t)), LERP((_a).y,(_b).y,(_t)) )
- shape::fpoint movement_bezier(f32 t);
- extern shape::fpoint curve_point;
- extern f32 hvel_speed;
- //whatever
- static inline shape::point mcCoord(shape::fpoint& fpnt, shape::rect& rct){
- shape::point pnt((s32)( fpnt.x *(rct.w-1) ),
- (s32)( (1.0f-fpnt.y)*(rct.h-1) ));
- pnt.x += rct.x;
- pnt.y += rct.y;
- return pnt;
- }
- //whatever
- void drawMovementCurve(shape::rect rect = {CANVSIZ_X-MCSIZE, CANVSIZ_Y-MCSIZE,
- MCSIZE, MCSIZE})
- {
- shape::fpoint cBL((f32)(rect.x ), (f32)(rect.y+rect.h));
- shape::fpoint cTR((f32)(rect.x+rect.w), (f32)(rect.y ));
- shape::fpoint hvel0 = movement_bezier(fabsf(gl_player.hvel));
- shape::fpoint hvel1(hvel0.x, 0.0f);
- shape::point hvel[2];
- hvel[0] = mcCoord(hvel0, rect);
- hvel[1] = mcCoord(hvel1, rect);
- //black background
- gl_win->drawRectangles(&rect, 1, 0x000000);
- shape::point bcurve[4];
- bcurve[0] = mcCoord(shape::fpoint(0.0f,0.0f), rect);
- bcurve[1] = mcCoord(curve_point, rect);
- bcurve[2] = mcCoord(shape::fpoint(1.0f-curve_point.x, 1.0f-curve_point.y), rect);
- bcurve[3] = mcCoord(shape::fpoint(1.0f,1.0f), rect);
- shape::rect bpoint = { bcurve[1].x-2, bcurve[1].y-2 };
- bpoint.w = bpoint.h = 4;
- //curve settings
- gl_win->drawLines(bcurve, 4, 0x008E4E);
- gl_win->drawRectangles(&bpoint, 1, 0x008E4E);
- //hvel line
- gl_win->drawLines(hvel, 2, 0xDB3D42);
- //the actual curve
- shape::point p[2] = { {0,0}, {rect.x, rect.y+rect.h-1} };
- for(f32 t=0.0f; t<1.0f; t+=(3.0f/MCSIZE)){
- shape::fpoint p1 = movement_bezier(t);
- p[0] = p[1];
- p[1] = mcCoord(p1, rect);
- gl_win->drawLines(p, 2, 0x006FAF);
- }
- p[0] = p[1];
- p[1] = shape::point(rect.x+rect.w-1, rect.y);
- gl_win->drawLines(p, 2, 0x006FAF);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement