bool Player::on_ground() { return ( issolid(base.x + base.width / 2, base.y + base.height) || issolid(base.x + 1, base.y + base.height) || issolid(base.x + base.width - 1, base.y + base.height) ); }
void move( float pos[3], float vel[3], map_s *map ) { // xy int attempts = 3; while ( attempts-- ) { int nx = (int)(pos[0]+vel[0]); int ny = (int)(pos[1]+vel[1]); if ( issolid( map, nx, ny, (int)(pos[2] + 1.f) ) ) { if ( nx != (int)pos[0] ) vel[0] = 0.f; if ( ny != (int)pos[1] ) vel[1] = 0.f; } else { break; } } pos[0] += vel[0]; pos[1] += vel[1]; if ( issolid( map, (int)pos[0], (int)pos[1], (int)pos[2] ) ) { pos[2] += 1.f; } if ( !issolid( map, (int)pos[0], (int)pos[1], (int)(pos[2] + vel[2]) ) ) { pos[2] += vel[2]; } }
void Player::check_bounds(bool back_scrolling, bool hor_autoscroll) { /* Keep tux in bounds: */ if (base.x < 0) { // Lock Tux to the size of the level, so that he doesn't fall of // on the left side base.x = 0; } /* Keep in-bounds, vertically: */ if (base.y > screen->h) { kill(KILL); } if(base.x < scroll_x && (!back_scrolling || hor_autoscroll)) // can happen if back scrolling is disabled base.x = scroll_x; if(hor_autoscroll) { if(base.x == scroll_x) if((issolid(base.x+32, base.y) || (size != SMALL && !duck && issolid(base.x+32, base.y+32))) && (dying == DYING_NOT)) kill(KILL); if(base.x + base.width > scroll_x + screen->w) base.x = scroll_x + screen->w - base.width; } }
bool Player::under_solid() { return ( issolid(base.x + base.width / 2, base.y) || issolid(base.x + 1, base.y) || issolid(base.x + base.width - 1, base.y) ); }
void BadGuy::action_bouncingsnowball(double frame_ratio) { static const float JUMPV = 4.5; fall(); // jump when on ground if(dying == DYING_NOT && issolid(base.x, base.y+32)) { physic.set_velocity_y(JUMPV); physic.enable_gravity(true); } else { mode = NORMAL; } // check for right/left collisions check_horizontal_bump(); physic.apply(frame_ratio, base.x, base.y); if(dying == DYING_NOT) collision_swept_object_map(&old_base, &base); // Handle dying timer: if (dying == DYING_SQUISHED && !timer.check()) { /* Remove it if time's up: */ remove_me(); return; } }
void BadGuy::fall() { /* Fall if we get off the ground: */ if (dying != DYING_FALLING) { if (!issolid(base.x+base.width/2, base.y + base.height)) { // not solid below us? enable gravity physic.enable_gravity(true); } else { /* Land: */ if (physic.get_velocity_y() < 0) { base.y = int((base.y + base.height)/32) * 32 - base.height; physic.set_velocity_y(0); } // no gravity anymore please physic.enable_gravity(false); if (stay_on_platform && mode == NORMAL) { if (!issolid(base.x + ((dir == LEFT) ? 0 : base.width), base.y + base.height)) { if (dir == LEFT) { dir = RIGHT; physic.set_velocity_x(fabsf(physic.get_velocity_x())); } else { dir = LEFT; physic.set_velocity_x(-fabsf(physic.get_velocity_x())); } } } } } else { physic.enable_gravity(true); } }
void Player::handle_vertical_input() { // Press jump key if(input.up == DOWN && can_jump) { if (on_ground()) { // jump higher if we are running if (fabs(physic.get_velocity_x()) > MAX_WALK_XM) physic.set_velocity_y(5.8); else physic.set_velocity_y(5.2); --base.y; jumping = true; can_jump = false; if (size == SMALL) play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER); else play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER); } } // Let go of jump key else if(input.up == UP && jumping) { jumping = false; if(physic.get_velocity_y() > 0) { physic.set_velocity_y(0); } } if ( (issolid(base.x + base.width / 2, base.y + base.height + 64) || issolid(base.x + 1, base.y + base.height + 64) || issolid(base.x + base.width - 1, base.y + base.height + 64)) && jumping == false && can_jump == false && input.up == DOWN && input.old_up == UP) { can_jump = true; } input.old_up = input.up; }
void BadGuy::check_horizontal_bump(bool checkcliff) { float halfheight = base.height / 2; if (dir == LEFT && issolid( base.x, (int) base.y + halfheight)) { dir = RIGHT; physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } if (dir == RIGHT && issolid( base.x + base.width, (int)base.y + halfheight)) { dir = LEFT; physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } // don't check for cliffs when we're falling if(!checkcliff) return; if(!issolid(base.x + base.width/2, base.y + base.height)) return; if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + halfheight)) { dir = RIGHT; physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } if(dir == RIGHT && !issolid(base.x + base.width, (int) base.y + base.height + halfheight)) { dir = LEFT; physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y()); return; } }
void Bullet::action(double frame_ratio) { frame_ratio *= 0.5f; float old_y = base.y; base.x = base.x + base.xm * frame_ratio; base.y = base.y + base.ym * frame_ratio; collision_swept_object_map(&old_base,&base); if (issolid(base.x, base.y + 4) || issolid(base.x, base.y)) { base.y = old_y; base.ym = -base.ym; if (base.ym > 9) base.ym = 9; else if (base.ym < -9) base.ym = -9; life_count -= 1; } base.ym = base.ym + 0.5 * frame_ratio; if (base.x < scroll_x || base.x > scroll_x + screen->w || base.y > screen->h || issolid(base.x + 4, base.y + 2) || issolid(base.x, base.y + 2) || life_count <= 0) { remove_me(); } }
void BadGuy::action_jumpy(double frame_ratio) { const float vy = physic.get_velocity_y(); // XXX: These tests *should* use location from ground, not velocity if (fabsf(vy) > 5.6f) set_sprite(img_jumpy_left_down, img_jumpy_left_down); else if (fabsf(vy) > 5.3f) set_sprite(img_jumpy_left_middle, img_jumpy_left_middle); else set_sprite(img_jumpy_left_up, img_jumpy_left_up); Player& tux = *World::current()->get_tux(); static const float JUMPV = 6; fall(); // jump when on ground if(dying == DYING_NOT && issolid(base.x, base.y+32)) { physic.set_velocity_y(JUMPV); physic.enable_gravity(true); mode = JUMPY_JUMP; } else if(mode == JUMPY_JUMP) { mode = NORMAL; } // set direction based on tux if(tux.base.x > base.x) dir = RIGHT; else dir = LEFT; // move physic.apply(frame_ratio, base.x, base.y); if(dying == DYING_NOT) collision_swept_object_map(&old_base, &base); }
void BadGuy::action_spiky(double frame_ratio) { if (dying == DYING_NOT) check_horizontal_bump(); fall(); #if 0 // jump when we're about to fall if (physic.get_velocity_y() == 0 && !issolid(base.x+base.width/2, base.y + base.height)) { physic.enable_gravity(true); physic.set_velocity_y(2); } #endif physic.apply(frame_ratio, base.x, base.y); if (dying != DYING_FALLING) collision_swept_object_map(&old_base,&base); }
void BadGuy::action_stalactite(double frame_ratio) { Player& tux = *World::current()->get_tux(); static const int SHAKETIME = 800; static const int RANGE = 40; if(mode == NORMAL) { // start shaking when tux is below the stalactite and at least 40 pixels // near if(tux.base.x + 32 > base.x - RANGE && tux.base.x < base.x + 32 + RANGE && tux.base.y + tux.base.height > base.y) { timer.start(SHAKETIME); mode = STALACTITE_SHAKING; } } if(mode == STALACTITE_SHAKING) { base.x = old_base.x + (rand() % 6) - 3; // TODO this could be done nicer... if(!timer.check()) { mode = STALACTITE_FALL; } } else if(mode == STALACTITE_FALL) { fall(); /* Destroy if we collides with land */ if(issolid(base.x+base.width/2, base.y+base.height)) { timer.start(2000); dying = DYING_SQUISHED; mode = FLAT; set_sprite(img_stalactite_broken, img_stalactite_broken); } } else if(mode == FLAT) { fall(); } // move physic.apply(frame_ratio, base.x, base.y); if(dying == DYING_SQUISHED && !timer.check()) remove_me(); }
bool IntersectRay(HitInfo_s &hi, float f[3], float d[3], float maxT, map_s *map, unsigned int mask ) { // Set up 3D DDA for ray float NextCrossingT[3], DeltaT[3]; int Step[3], Pos[3], OOB[3]; for (int axis = 0; axis < 3; ++axis) { // Compute current voxel for axis Pos[axis] = (int)(f[axis]); if (d[axis] >= 0) { // Handle ray with positive direction for voxel stepping NextCrossingT[axis] = ((Pos[axis]+1.f) - f[axis]) / d[axis]; DeltaT[axis] = 1.f / d[axis]; Step[axis] = 1; OOB[axis] = map->dim[axis]; } else { // Handle ray with negative direction for voxel stepping NextCrossingT[axis] = ((Pos[axis], axis) - f[axis]) / d[axis]; DeltaT[axis] = -1.f / d[axis]; Step[axis] = -1; OOB[axis] = -1; } } for (;;) { int index = Pos[0] * map->dim[1] + Pos[1]; #if 0 entitystate_s *cur = map->entities[index]; while ( cur ) { if ( cur->collisionMask & mask ) { if ( (Pos[2] >= cur->pos[2]) && (Pos[2] <= (cur->pos[2]+cur->collisionHeight) ) ) { hi.es = cur; hi.loc[0] = Pos[0]; hi.loc[1] = Pos[1]; hi.loc[2] = Pos[2]; return true; } } cur = cur->voxelNext; } #endif if ( issolid( map, Pos[0], Pos[1], Pos[2] ) ) { hi.loc[0] = Pos[0]; hi.loc[1] = Pos[1]; hi.loc[2] = Pos[2]; hi.es = NULL; return true; } // Find _stepAxis_ for stepping to next voxel int bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) + ((NextCrossingT[0] < NextCrossingT[2]) << 1) + ((NextCrossingT[1] < NextCrossingT[2])); const int cmpToAxis[8] = { 2, 1, 2, 1, 2, 2, 0, 0 }; int stepAxis = cmpToAxis[bits]; if (maxT < NextCrossingT[stepAxis]) break; Pos[stepAxis] += Step[stepAxis]; if (Pos[stepAxis] == OOB[stepAxis]) break; NextCrossingT[stepAxis] += DeltaT[stepAxis]; } return false; }
void Upgrade::action(double frame_ratio) { if (kind == UPGRADE_ICEFLOWER || kind == UPGRADE_GROWUP) { if (base.height < 32) { /* Rise up! */ base.height = base.height + 0.7 * frame_ratio; if(base.height > 32) base.height = 32; return; } } /* Away from the screen? Kill it! */ if(base.x < scroll_x - OFFSCREEN_DISTANCE) { remove_me(); return; } #ifndef RES320X240 if(base.y > screen->h) { #else if(base.y > 640) { #endif remove_me(); return; } /* Move around? */ physic.apply(frame_ratio, base.x, base.y); if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) { collision_swept_object_map(&old_base, &base); } // fall down? if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) { // falling? if(physic.get_velocity_y() != 0) { if(issolid(base.x, base.y + base.height)) { base.y = int(base.y / 32) * 32; old_base = base; if(kind == UPGRADE_GROWUP) { physic.enable_gravity(false); physic.set_velocity(dir == LEFT ? -GROWUP_SPEED : GROWUP_SPEED, 0); } else if(kind == UPGRADE_HERRING) { physic.set_velocity(dir == LEFT ? -2 : 2, 3); } } } else { if((physic.get_velocity_x() < 0 && !issolid(base.x+base.width, base.y + base.height)) || (physic.get_velocity_x() > 0 && !issolid(base.x, base.y + base.height))) { physic.enable_gravity(true); } } } // horizontal bounce? if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) { if ( (physic.get_velocity_x() < 0 && issolid(base.x, (int) base.y + base.height/2)) || (physic.get_velocity_x() > 0 && issolid(base.x + base.width, (int) base.y + base.height/2))) { physic.set_velocity(-physic.get_velocity_x(),physic.get_velocity_y()); dir = dir == LEFT ? RIGHT : LEFT; } } } void Upgrade::draw() { SDL_Rect dest; if (base.height < 32) { /* Rising up... */ #ifndef RES320X240 dest.x = (int)(base.x - scroll_x); #else dest.x = (int)(base.x - scroll_x)/2; #endif dest.y = (int)(base.y + 32 - base.height); dest.w = 32; dest.h = (int)base.height; if (kind == UPGRADE_GROWUP) img_growup->draw_part(0,0,dest.x,dest.y,dest.w,dest.h); else if (kind == UPGRADE_ICEFLOWER) img_iceflower->draw_part(0,0,dest.x,dest.y,dest.w,dest.h); else if (kind == UPGRADE_HERRING) img_star->draw_part(0,0,dest.x,dest.y,dest.w,dest.h); else if (kind == UPGRADE_1UP) img_1up->draw_part( 0, 0, dest.x, dest.y, dest.w, dest.h); } else { if (kind == UPGRADE_GROWUP) { img_growup->draw( base.x - scroll_x, base.y); } else if (kind == UPGRADE_ICEFLOWER) { img_iceflower->draw( base.x - scroll_x, base.y); } else if (kind == UPGRADE_HERRING) { img_star->draw( base.x - scroll_x, base.y); } else if (kind == UPGRADE_1UP) { img_1up->draw( base.x - scroll_x, base.y); } } }
void Upgrade::action(double frame_ratio) { if (kind == UPGRADE_ICEFLOWER || kind == UPGRADE_GROWUP) { if (base.height < 32) { /* Rise up! */ base.height = base.height + 0.7 * frame_ratio; if(base.height > 32) base.height = 32; return; } } /* Away from the screen? Kill it! */ if(base.x < scroll_x - OFFSCREEN_DISTANCE) { remove_me(); return; } if(base.y > screen->h) { remove_me(); return; } /* Move around? */ physic.apply(frame_ratio, base.x, base.y); if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) { collision_swept_object_map(&old_base, &base); } // fall down? if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) { // falling? if(physic.get_velocity_y() != 0) { if(issolid(base.x, base.y + base.height)) { base.y = int(base.y / 32) * 32; old_base = base; if(kind == UPGRADE_GROWUP) { physic.enable_gravity(false); physic.set_velocity(dir == LEFT ? -GROWUP_SPEED : GROWUP_SPEED, 0); } else if(kind == UPGRADE_HERRING) { physic.set_velocity(dir == LEFT ? -2 : 2, 3); } } } else { if((physic.get_velocity_x() < 0 && !issolid(base.x+base.width, base.y + base.height)) || (physic.get_velocity_x() > 0 && !issolid(base.x, base.y + base.height))) { physic.enable_gravity(true); } } } // horizontal bounce? if(kind == UPGRADE_GROWUP || kind == UPGRADE_HERRING) { if ( (physic.get_velocity_x() < 0 && issolid(base.x, (int) base.y + base.height/2)) || (physic.get_velocity_x() > 0 && issolid(base.x + base.width, (int) base.y + base.height/2))) { physic.set_velocity(-physic.get_velocity_x(),physic.get_velocity_y()); dir = dir == LEFT ? RIGHT : LEFT; } } }
array makesolid(array a){ if (a->type==function || !issolid(a)) return copy(a); return a; }