예제 #1
0
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)  );
}
예제 #2
0
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];
	}
}
예제 #3
0
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;
    }
    
}
예제 #4
0
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)  );
}
예제 #5
0
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;
    }
}
예제 #6
0
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);
    }
}
예제 #7
0
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;
}
예제 #8
0
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;
    }
}
예제 #9
0
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();
    }

}
예제 #10
0
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);
}
예제 #11
0
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);   
}
예제 #12
0
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();
}
예제 #13
0
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;
}
예제 #14
0
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);
        }
    }
}
예제 #15
0
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;
        }
    }
}
예제 #16
0
파일: array.c 프로젝트: luser-dr00g/inca
array makesolid(array a){
    if (a->type==function || !issolid(a))
        return copy(a);
    return a;
}