X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fspecial.cpp;h=8d698151dffe119ae68f8a1fcc9d96c70d30111d;hb=e4db6eb50cd6bcba607858b5e6c4c5d53531ed1f;hp=787537fce01a58bcd9ee8ea7cb5b4e5cb85b13bd;hpb=2398b134147461d9b4e096f1c15dbf889c0f2d41;p=supertux.git diff --git a/src/special.cpp b/src/special.cpp index 787537fce..8d698151d 100644 --- a/src/special.cpp +++ b/src/special.cpp @@ -1,242 +1,320 @@ +// $Id$ // -// C Implementation: special +// SuperTux - A Jump'n Run +// Copyright (C) 2003 Tobias Glaesser // -// Description: -// -// -// Author: Tobias Glaesser & Bill Kendrick, (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. // +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include +#include #include "SDL.h" + #include "defines.h" #include "special.h" +#include "camera.h" #include "gameloop.h" -#include "screen.h" -#include "sound.h" +#include "video/screen.h" #include "scene.h" -#include "globals.h" +#include "app/globals.h" #include "player.h" +#include "sector.h" +#include "special/sprite_manager.h" #include "resources.h" -texture_type img_bullet; -texture_type img_golden_herring; -bitmask* bm_bullet; +Sprite* img_firebullet; +Sprite* img_icebullet; +Sprite* img_star; +Sprite* img_growup; +Sprite* img_iceflower; +Sprite* img_fireflower; +Sprite* img_1up; -void create_special_bitmasks() -{ - bm_bullet = bitmask_create_SDL(img_bullet.sdl_surface); -} +#define GROWUP_SPEED 1.0f -void -Bullet::init(float x, float y, float xm, int dir) +#define BULLET_STARTING_YM 0 +#define BULLET_XM 6 + +Bullet::Bullet(const Vector& pos, float xm, int dir, int kind_) { + life_count = 3; base.width = 4; base.height = 4; + + if (kind == ICE_BULLET) + life_count = 6; //ice-bullets get "extra lives" for bumping off walls if (dir == RIGHT) { - base.x = x + 32; - base.xm = BULLET_XM + xm; + base.x = pos.x + 32; + physic.set_velocity_x(BULLET_XM + xm); } else { - base.x = x; - base.xm = -BULLET_XM + xm; + base.x = pos.x; + physic.set_velocity_x(-BULLET_XM + xm); } - base.y = y; - base.ym = BULLET_STARTING_YM; + base.y = pos.y; + physic.set_velocity_y(-BULLET_STARTING_YM); old_base = base; + kind = kind_; } void -Bullet::action(double frame_ratio) +Bullet::action(float elapsed_time) { - base.x = base.x + base.xm * frame_ratio; - base.y = base.y + base.ym * frame_ratio; + elapsed_time *= 0.5f; + + float old_y = base.y; + physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity); collision_swept_object_map(&old_base,&base); - if (issolid(base.x, base.y + 4) || issolid(base.x, base.y)) + if (issolid(base.x+2, base.y + 4) || issolid(base.x+2, base.y)) { - base.ym = -base.ym; - base.y = (int)(base.y / 32) * 32; + base.y = old_y; + physic.set_velocity_y(-physic.get_velocity_y()); + life_count -= 1; } - base.ym = base.ym + GRAVITY; - + if(kind == FIRE_BULLET) + // @not framerate independant :-/ + physic.set_velocity_y(physic.get_velocity_y() - 0.5 * elapsed_time); + if(physic.get_velocity_y() > 9) + physic.set_velocity_y(9); + else if(physic.get_velocity_y() < -9) + physic.set_velocity_y(-9); + + float scroll_x = + Sector::current()->camera->get_translation().x; + float scroll_y = + Sector::current()->camera->get_translation().y; if (base.x < scroll_x || base.x > scroll_x + screen->w || - base.y < 0 || - base.y > screen->h || - issolid(base.x + 4, base.y + 2) || - issolid(base.x, base.y + 2)) +// base.y < scroll_y || + base.y > scroll_y + screen->h || + life_count <= 0) { - World::current()->bullets.erase(static_cast::iterator>(this)); + remove_me(); } - + if (issolid(base.x + 4, base.y + 2) || + issolid(base.x, base.y + 2)) + { + if (kind == FIRE_BULLET) + remove_me(); + else if (kind == ICE_BULLET) + { + physic.set_velocity_x(-physic.get_velocity_x()); + //physic.set_velocity_y(-physic.get_velocity_y()); + } + } } void -Bullet::draw() +Bullet::draw(DrawingContext& context) { - if (base.x >= scroll_x - base.width && - base.x <= scroll_x + screen->w) - { - texture_draw(&img_bullet, base.x - scroll_x, base.y, 255, - NO_UPDATE); - } + Sprite* sprite = kind == FIRE_BULLET ? img_firebullet : img_icebullet; + + sprite->draw(context, Vector(base.x, base.y), LAYER_OBJECTS); +} + +void +Bullet::collision(const MovingObject& , int) +{ + // later } void Bullet::collision(int c_object) { if(c_object == CO_BADGUY) { - std::vector::iterator i; - - for(i = World::current()->bullets.begin(); i != World::current()->bullets.end(); ++i) - { - if(&(*i) == this) - { - World::current()->bullets.erase(i); - return; - } - } + remove_me(); } } -void -Upgrade::init(float x_, float y_, int dir_, int kind_) +//--------------------------------------------------------------------------- + +Upgrade::Upgrade(const Vector& pos, Direction dir_, UpgradeKind kind_) { - base.width = 32; - base.height = 0; kind = kind_; - base.x = x_; - base.y = y_; - - if(dir_ == LEFT) - base.xm = -2; - else - base.xm = 2; + dir = dir_; - base.ym = -2; + base.width = 32; base.height = 0; + base.x = pos.x; + base.y = pos.y; old_base = base; + + physic.reset(); + physic.enable_gravity(false); + + if(kind == UPGRADE_1UP || kind == UPGRADE_STAR) { + physic.set_velocity(dir == LEFT ? -1 : 1, 4); + physic.enable_gravity(true); + base.height = 32; + } else if (kind == UPGRADE_ICEFLOWER || kind == UPGRADE_FIREFLOWER) { + // nothing + } else if (kind == UPGRADE_GROWUP) { + physic.set_velocity(dir == LEFT ? -GROWUP_SPEED : GROWUP_SPEED, 0); + } else { + physic.set_velocity(dir == LEFT ? -2 : 2, 0); + } +} + +Upgrade::~Upgrade() +{ } void -Upgrade::action(double frame_ratio) +Upgrade::action(float elapsed_time) { - if (base.height < 32) - { + if (kind == UPGRADE_ICEFLOWER || kind == UPGRADE_FIREFLOWER + || kind == UPGRADE_GROWUP) { + if (base.height < 32) { /* Rise up! */ - - base.height = base.height + 0.7 * frame_ratio; + base.height = base.height + 0.7 * elapsed_time; if(base.height > 32) base.height = 32; + + return; } - else + } + + /* Away from the screen? Kill it! */ + float scroll_x = + Sector::current()->camera->get_translation().x; + float scroll_y = + Sector::current()->camera->get_translation().y; + + if(base.x < scroll_x - X_OFFSCREEN_DISTANCE || + base.x > scroll_x + screen->w + X_OFFSCREEN_DISTANCE || + base.y < scroll_y - Y_OFFSCREEN_DISTANCE || + base.y > scroll_y + screen->h + Y_OFFSCREEN_DISTANCE) { - /* Move around? */ + remove_me(); + return; + } - if (kind == UPGRADE_MINTS || - kind == UPGRADE_HERRING) - { - base.x = base.x + base.xm * frame_ratio; - base.y = base.y + base.ym * frame_ratio; - - collision_swept_object_map(&old_base,&base); - - /* Off the screen? Kill it! */ - - if (base.x < scroll_x - base.width) - World::current()->upgrades.erase(static_cast::iterator>(this)); - if (base.y > screen->h) - World::current()->upgrades.erase(static_cast::iterator>(this)); - - if (issolid(base.x + 1, base.y + 32.) || - issolid(base.x + 31., base.y + 32.)) - { - if (base.ym > 0) - { - if (kind == UPGRADE_MINTS) - { - base.ym = 0; - } - else if (kind == UPGRADE_HERRING) - { - base.ym = -8; - } - - base.y = (int)(base.y / 32) * 32; - } - } - else - base.ym = base.ym + GRAVITY * frame_ratio; - - if (issolid(base.x - 1, (int) base.y)) - { - if(base.xm < 0) - base.xm = -base.xm; - } - else if (issolid(base.x + base.width, (int) base.y)) - { - if(base.xm > 0) - base.xm = -base.xm; - } + /* Move around? */ + physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity); + if(kind == UPGRADE_GROWUP || kind == UPGRADE_STAR) { + collision_swept_object_map(&old_base, &base); + } + + // fall down? + if(kind == UPGRADE_GROWUP || kind == UPGRADE_STAR) { + // 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_STAR) { + 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_STAR) { + 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() +Upgrade::draw(DrawingContext& context) { - SDL_Rect dest; - if (base.height < 32) - { - /* Rising up... */ - - dest.x = (int)(base.x - scroll_x); - dest.y = (int)(base.y + 32 - base.height); - dest.w = 32; - dest.h = (int)base.height; - - if (kind == UPGRADE_MINTS) - texture_draw_part(&img_mints,0,0,dest.x,dest.y,dest.w,dest.h); - else if (kind == UPGRADE_COFFEE) - texture_draw_part(&img_coffee,0,0,dest.x,dest.y,dest.w,dest.h); - else if (kind == UPGRADE_HERRING) - texture_draw_part(&img_golden_herring,0,0,dest.x,dest.y,dest.w,dest.h); - } + Sprite* sprite; + switch(kind) { + case UPGRADE_GROWUP: sprite = img_growup; break; + case UPGRADE_ICEFLOWER: sprite = img_iceflower; break; + case UPGRADE_FIREFLOWER: sprite = img_fireflower; break; + case UPGRADE_STAR: sprite = img_star; break; + case UPGRADE_1UP: sprite = img_1up; break; + default: + assert(!"wrong type in Powerup::draw()"); + sprite = NULL; // added by neoneurone, g++ likes this ! + } + + if(base.height < 32) // still raising up? + sprite->draw(context, Vector(base.x, base.y + (32 - base.height)), + LAYER_TILES - 10); else - { - if (kind == UPGRADE_MINTS) - { - texture_draw(&img_mints, - base.x - scroll_x, base.y); - } - else if (kind == UPGRADE_COFFEE) - { - texture_draw(&img_coffee, - base.x - scroll_x, base.y); - } - else if (kind == UPGRADE_HERRING) - { - texture_draw(&img_golden_herring, - base.x - scroll_x, base.y); - } - } + sprite->draw(context, Vector(base.x, base.y), LAYER_OBJECTS); +} + +void +Upgrade::bump(Player* player) +{ + // these can't be bumped + if(kind != UPGRADE_GROWUP) + return; + + SoundManager::get()->play_sound(IDToSound(SND_BUMP_UPGRADE), Vector(base.x, base.y), Sector::current()->player->get_pos()); + + // determine new direction + Direction old_dir = dir; + if (player->base.x + player->base.width/2 > base.x + base.width/2) + dir = LEFT; + else + dir = RIGHT; + + // do a little jump and change direction (if necessary) + if (dir != old_dir) + physic.set_velocity(-physic.get_velocity_x(), 3); + else + physic.set_velocity_y(3); + + physic.enable_gravity(true); +} + +void +Upgrade::collision(const MovingObject& , int) +{ + // later } void -Upgrade::collision(void* p_c_object, int c_object) +Upgrade::collision(void* p_c_object, int c_object, CollisionType type) { Player* pplayer = NULL; + if(type == COLLISION_BUMP) { + if(c_object == CO_PLAYER) + pplayer = (Player*) p_c_object; + bump(pplayer); + return; + } + switch (c_object) { case CO_PLAYER: @@ -245,40 +323,63 @@ Upgrade::collision(void* p_c_object, int c_object) /* p_c_object is CO_PLAYER, so assign it to pplayer */ pplayer = (Player*) p_c_object; - World::current()->upgrades.erase(static_cast::iterator>(this)); - /* Affect the player: */ - if (kind == UPGRADE_MINTS) + if (kind == UPGRADE_GROWUP) { - play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER); - pplayer->size = BIG; - pplayer->base.height = 64; - pplayer->base.y -= 32; - if(collision_object_map(&pplayer->base)) - { - pplayer->base.height = 32; - pplayer->base.y += 32; - pplayer->duck = true; - } + SoundManager::get()->play_sound(IDToSound(SND_EXCELLENT)); + pplayer->grow(true); } - else if (kind == UPGRADE_COFFEE) + else if (kind == UPGRADE_FIREFLOWER) { - play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER); - pplayer->got_coffee = true; + SoundManager::get()->play_sound(IDToSound(SND_COFFEE)); + pplayer->grow(true); + pplayer->got_power = pplayer->FIRE_POWER; } - else if (kind == UPGRADE_HERRING) + else if (kind == UPGRADE_ICEFLOWER) { - play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER); - timer_start(&pplayer->invincible_timer,TUX_INVINCIBLE_TIME); - /* play the herring song ^^ */ - if (get_current_music() != HURRYUP_MUSIC) - { - set_current_music(HERRING_MUSIC); - play_current_music(); - } + SoundManager::get()->play_sound(IDToSound(SND_COFFEE)); + pplayer->grow(true); + pplayer->got_power = pplayer->ICE_POWER; } - break; + else if (kind == UPGRADE_FIREFLOWER) + { + SoundManager::get()->play_sound(IDToSound(SND_COFFEE)); + pplayer->grow(true); + pplayer->got_power = pplayer->FIRE_POWER; + } + else if (kind == UPGRADE_STAR) + { + SoundManager::get()->play_sound(IDToSound(SND_HERRING)); + pplayer->invincible_timer.start(TUX_INVINCIBLE_TIME); + Sector::current()->play_music(HERRING_MUSIC); + } + else if (kind == UPGRADE_1UP) + { + if(player_status.lives < MAX_LIVES) { + player_status.lives++; + SoundManager::get()->play_sound(IDToSound(SND_LIFEUP)); + } + } + + remove_me(); + return; } } +void load_special_gfx() +{ + img_growup = sprite_manager->load("egg"); + img_iceflower = sprite_manager->load("iceflower"); + img_fireflower = sprite_manager->load("fireflower"); + img_star = sprite_manager->load("star"); + img_1up = sprite_manager->load("1up"); + + img_firebullet = sprite_manager->load("firebullet"); + img_icebullet = sprite_manager->load("icebullet"); +} + +void free_special_gfx() +{ +} +