[Super-tux-commit] supertux/src/object block.cpp,NONE,1.1 block.h,NONE,1.1 bullet.cpp,NONE,1.1 bulle
Brought to you by:
wkendrick
From: Matze B. <mat...@us...> - 2004-11-20 22:14:50
|
Update of /cvsroot/super-tux/supertux/src/object In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5941/src/object Added Files: block.cpp block.h bullet.cpp bullet.h coin.cpp coin.h fireworks.cpp fireworks.h flower.cpp flower.h growup.cpp growup.h oneup.cpp oneup.h platform.cpp platform.h specialriser.cpp specialriser.h star.cpp star.h Log Message: The BIG COMMIT(tm) This is it, expect a broken supertux I only fixed the most annoying issues so far, lots more are still waiting in the TODO list, but I had to bring this stuff to cvs sometime. Changes: - Completely new collision detection scheme, which collides all objects with each other once per frame, instead of single objects manually testing for collisions - New collision detection routines which support slopes and provide additional info on collisions: penetration depth, hit normal vector - Lots of general cleanup/refactoring - Splitted the monolithic badguy class and reimplemented most of them as single classes with a badguy base class. - Splitted the monolithic Special class into several classes - Rewrote the timer and all timing related stuff to work on float and seconds (not like the mixup before where you had frame_ratio, msecs and secs in different parts of the app) - Support for unisolid tiles - Created a flying platform prototype (doesn't work completely yet) - rename InteractiveObjects to triggers and implemented a new sequence trigger, (only supported sequence is endsequence at the moment) - transformed the bonusblocks and bricks into objects --- NEW FILE: platform.cpp --- #include <config.h> #include "platform.h" #include "video/drawing_context.h" #include "resources.h" #include "player.h" #include "special/sprite_manager.h" #include "utils/lispreader.h" Platform::Platform(LispReader& reader) { sprite = sprite_manager->create("flying_platform"); movement = Vector(0, 1); reader.read_float("x", bbox.p1.x); reader.read_float("y", bbox.p1.y); bbox.set_size(sprite->get_width(), sprite->get_height()); flags |= FLAG_SOLID; state = 0; } Platform::~Platform() { delete sprite; } HitResponse Platform::collision(GameObject& object, const CollisionHit& hit) { #if 0 if(typeid(object) == typeid(Player)) { Player* player = (Player*) &object; //player->movement += movement; } #endif return FORCE_MOVE; } void Platform::action(float elapsed_time) { // just some test code... if(state == 0) { movement = Vector(0, 1); if(bbox.p1.y > 250) state = 1; } if(state == 1) { movement = Vector(0, -1); if(bbox.p1.y < 50) state = 2; } if(state == 2) { movement = Vector(1, 0); if(bbox.p1.x > 800) state = 3; } if(state == 3) { movement = Vector(-1, 0); if(bbox.p1.x < 400) state = 4; } if(state == 4) { movement = Vector(-1, 1); if(bbox.p1.x < 0) state = 0; } } void Platform::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_OBJECTS); } --- NEW FILE: growup.cpp --- #include <config.h> #include <math.h> #include "growup.h" #include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" #include "player.h" #include "app/globals.h" #include "special/sprite_manager.h" GrowUp::GrowUp(const Vector& pos) { bbox.set_pos(pos); bbox.set_size(32, 32); sprite = sprite_manager->create("egg"); physic.enable_gravity(true); physic.set_velocity_x(100); } GrowUp::~GrowUp() { delete sprite; } void GrowUp::action(float elapsed_time) { movement = physic.get_movement(elapsed_time); } HitResponse GrowUp::collision(GameObject& other, const CollisionHit& hit) { if(other.get_flags() & FLAG_SOLID) { if(fabsf(hit.normal.y) > .5) { // roof physic.set_velocity_y(0); } else { // bumped left or right physic.set_velocity_x(-physic.get_velocity_x()); } return CONTINUE; } Player* player = dynamic_cast<Player*>(&other); if(player != 0) { player->grow(); SoundManager::get()->play_sound(IDToSound(SND_EXCELLENT)); remove_me(); return ABORT_MOVE; } return FORCE_MOVE; } void GrowUp::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_OBJECTS); } --- NEW FILE: coin.cpp --- #include <config.h> #include "coin.h" #include "resources.h" #include "video/drawing_context.h" #include "special/sprite_manager.h" #include "player.h" #include "scene.h" Coin::Coin(const Vector& pos) { bbox.set_pos(pos); bbox.set_size(32, 32); sprite = sprite_manager->create("coin"); } Coin::~Coin() { delete sprite; } void Coin::action(float ) { } void Coin::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_TILES); } HitResponse Coin::collision(GameObject& other, const CollisionHit& hit) { Player* player = dynamic_cast<Player*>(&other); if(player == 0) return ABORT_MOVE; player->get_status().incCoins(); remove_me(); return ABORT_MOVE; } --- NEW FILE: flower.h --- #ifndef __FLOWER_H__ #define __FLOWER_H__ #include "special/moving_object.h" #include "special/sprite.h" #include "math/physic.h" using namespace SuperTux; class Flower : public MovingObject { public: enum Type { FIREFLOWER, ICEFLOWER }; Flower(const Vector& pos, Type type); ~Flower(); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); private: Type type; Sprite* sprite; }; #endif --- NEW FILE: star.h --- #ifndef __STAR_H__ #define __STAR_H__ #include "special/moving_object.h" #include "special/sprite.h" #include "math/physic.h" using namespace SuperTux; class Star : public MovingObject { public: Star(const Vector& pos); ~Star(); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); private: Sprite* sprite; Physic physic; }; #endif --- NEW FILE: specialriser.cpp --- #include <config.h> #include <math.h> #include "specialriser.h" #include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" #include "app/globals.h" #include "special/sprite_manager.h" SpecialRiser::SpecialRiser(MovingObject* _child) : child(_child) { offset = 0; } SpecialRiser::~SpecialRiser() { } void SpecialRiser::action(float elapsed_time) { offset += 50 * elapsed_time; if(offset > 32) { Sector::current()->add_object(child); remove_me(); } } void SpecialRiser::draw(DrawingContext& context) { context.push_transform(); context.set_translation( context.get_translation() + Vector(0, -32 + offset)); child->draw(context); context.pop_transform(); } --- NEW FILE: block.cpp --- #include <config.h> #include "block.h" #include "resources.h" #include "player.h" #include "sector.h" #include "special/sprite.h" #include "special/sprite_manager.h" #include "video/drawing_context.h" #include "gameobjs.h" #include "specialriser.h" #include "growup.h" #include "flower.h" #include "oneup.h" #include "star.h" static const float BOUNCY_BRICK_MAX_OFFSET=8; static const float BOUNCY_BRICK_SPEED=90; static const float EPSILON = .0001; Block::Block(const Vector& pos, Sprite* newsprite) : sprite(newsprite), bouncing(false), bounce_dir(0), bounce_offset(0) { bbox.set_pos(pos); bbox.set_size(32, 32); flags |= FLAG_SOLID; original_y = pos.y; } Block::~Block() { delete sprite; } HitResponse Block::collision(GameObject& other, const CollisionHit& hitdata) { if(bouncing) return FORCE_MOVE; // TODO kill badguys when bumping them... Player* player = dynamic_cast<Player*> (&other); if(!player) return ABORT_MOVE; // collided from below? if(hitdata.normal.x == 0 && hitdata.normal.y < 0 && player->get_movement().y < 0) { hit(player); } return ABORT_MOVE; } void Block::action(float elapsed_time) { if(!bouncing) return; float offset = original_y - get_pos().y; if(offset > BOUNCY_BRICK_MAX_OFFSET) { bounce_dir *= -1; movement = Vector(0, bounce_dir * elapsed_time); } else if(offset < -EPSILON) { movement = Vector(0, offset); bounce_dir = 0; bouncing = false; } else { movement = Vector(0, bounce_dir * elapsed_time); } } void Block::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_OBJECTS+1); } void Block::start_bounce() { bouncing = true; bounce_dir = -BOUNCY_BRICK_SPEED; bounce_offset = 0; } //--------------------------------------------------------------------------- BonusBlock::BonusBlock(const Vector& pos, int newdata) : Block(pos, sprite_manager->create("bonusblock")), data(newdata) { sprite->set_action("default"); } void BonusBlock::hit(Player* player) { if(sprite->get_action_name() == "empty") { SoundManager::get()->play_sound(IDToSound(SND_BRICK)); return; } Sector* sector = Sector::current(); switch(data) { case 1: // coin Sector::current()->add_object(new BouncyCoin(get_pos())); player->get_status().incCoins(); break; case 2: // grow/fireflower if(player->size == SMALL) { SpecialRiser* riser = new SpecialRiser( new GrowUp(get_pos() + Vector(0, -32))); sector->add_object(riser); } else { SpecialRiser* riser = new SpecialRiser( new Flower(get_pos() + Vector(0, -32), Flower::FIREFLOWER)); sector->add_object(riser); } SoundManager::get()->play_sound(IDToSound(SND_UPGRADE)); break; case 5: // grow/iceflower if(player->size == SMALL) { SpecialRiser* riser = new SpecialRiser( new GrowUp(get_pos() + Vector(0, -32))); sector->add_object(riser); } else { SpecialRiser* riser = new SpecialRiser( new Flower(get_pos() + Vector(0, -32), Flower::ICEFLOWER)); sector->add_object(riser); } SoundManager::get()->play_sound(IDToSound(SND_UPGRADE)); break; case 3: // star sector->add_object(new Star(get_pos())); break; case 4: // 1up sector->add_object(new OneUp(get_pos())); break; default: assert(false); } start_bounce(); sprite->set_action("empty"); } //--------------------------------------------------------------------------- Brick::Brick(const Vector& pos, int data) : Block(pos, sprite_manager->create("brick")), breakable(false), coin_counter(0) { if(data == 1) coin_counter = 5; else breakable = true; } void Brick::hit(Player* player) { if(sprite->get_action_name() == "empty") return; SoundManager::get()->play_sound(IDToSound(SND_BRICK)); Sector* sector = Sector::current(); if(coin_counter > 0) { sector->add_object(new BouncyCoin(get_pos())); coin_counter--; player->get_status().incCoins(); if(coin_counter == 0) sprite->set_action("empty"); start_bounce(); } else if(breakable) { if(player->size == SMALL) { start_bounce(); return; } sector->add_object( new BrokenBrick(new Sprite(*sprite), get_pos(), Vector(-100, -400))); sector->add_object( new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(0, 16), Vector(-150, -300))); sector->add_object( new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(16, 0), Vector(100, -400))); sector->add_object( new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(16, 16), Vector(150, -300))); remove_me(); } } --- NEW FILE: specialriser.h --- #ifndef __SPECIALRISE_H__ #define __SPECIALRISE_H__ #include "special/moving_object.h" using namespace SuperTux; /** * special object that contains another object and slowly rises it out of a * bonus block. */ class SpecialRiser : public GameObject { public: SpecialRiser(MovingObject* child); ~SpecialRiser(); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); private: float offset; MovingObject* child; }; #endif --- NEW FILE: flower.cpp --- #include <config.h> #include <math.h> #include "flower.h" #include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" #include "player.h" #include "app/globals.h" #include "special/sprite_manager.h" Flower::Flower(const Vector& pos, Type _type) : type(_type) { bbox.set_pos(pos); bbox.set_size(32, 32); if(_type == FIREFLOWER) sprite = sprite_manager->create("fireflower"); else sprite = sprite_manager->create("iceflower"); } Flower::~Flower() { delete sprite; } void Flower::action(float ) { } void Flower::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_OBJECTS); } HitResponse Flower::collision(GameObject& other, const CollisionHit& hit) { Player* player = dynamic_cast<Player*>(&other); if(!player) return ABORT_MOVE; if(type == FIREFLOWER) player->got_power = Player::FIRE_POWER; else player->got_power = Player::ICE_POWER; SoundManager::get()->play_sound(IDToSound(SND_COFFEE)); remove_me(); return ABORT_MOVE; } --- NEW FILE: bullet.cpp --- #include <config.h> #include <math.h> #include "bullet.h" #include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" #include "app/globals.h" #include "special/sprite_manager.h" #include "badguy/badguy.h" static const float BULLET_XM = 300; static const float BULLET_STARTING_YM = 0; Bullet::Bullet(const Vector& pos, float xm, int dir, int kind_) : kind(kind_), life_count(3), sprite(0) { bbox.set_pos(pos); bbox.set_size(4, 4); float speed = dir == RIGHT ? BULLET_XM : -BULLET_XM; physic.set_velocity_x(speed + xm); physic.set_velocity_y(-BULLET_STARTING_YM); if (kind == ICE_BULLET) { life_count = 6; //ice-bullets get "extra lives" for bumping off walls sprite = sprite_manager->create("icebullet"); } else if(kind == FIRE_BULLET) { sprite = sprite_manager->create("firebullet"); } } Bullet::~Bullet() { delete sprite; } void Bullet::action(float elapsed_time) { if(kind == FIRE_BULLET) { // @not completely framerate independant :-/ physic.set_velocity_y(physic.get_velocity_y() - 50 * elapsed_time); } if(physic.get_velocity_y() > 900) physic.set_velocity_y(900); else if(physic.get_velocity_y() < -900) physic.set_velocity_y(-900); float scroll_x = Sector::current()->camera->get_translation().x; float scroll_y = Sector::current()->camera->get_translation().y; if (get_pos().x < scroll_x || get_pos().x > scroll_x + screen->w || // get_pos().y < scroll_y || get_pos().y > scroll_y + screen->h || life_count <= 0) { remove_me(); return; } movement = physic.get_movement(elapsed_time); } void Bullet::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_OBJECTS); } HitResponse Bullet::collision(GameObject& other, const CollisionHit& hit) { if(other.get_flags() & FLAG_SOLID) { if(fabsf(hit.normal.y) > .5) { // roof or floor bump physic.set_velocity_y(-physic.get_velocity_y()); life_count -= 1; } else { // bumped left or right if(kind == FIRE_BULLET) remove_me(); else physic.set_velocity_x(-physic.get_velocity_x()); } return CONTINUE; } BadGuy* badguy = dynamic_cast<BadGuy*> (&other); if(badguy) { badguy->kill_fall(); remove_me(); return FORCE_MOVE; } // TODO kill badguys return FORCE_MOVE; } --- NEW FILE: platform.h --- #ifndef __PLATFORM_H__ #define __PLATFORM_H__ #include "special/moving_object.h" #include "special/sprite.h" using namespace SuperTux; /** * This class is the base class for platforms that tux can stand on */ class Platform : public SuperTux::MovingObject { public: Platform(LispReader& reader); ~Platform(); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); private: int state; Sprite* sprite; }; #endif --- NEW FILE: oneup.cpp --- #include <config.h> #include "oneup.h" #include "resources.h" #include "player.h" #include "scene.h" #include "special/sprite_manager.h" #include "video/drawing_context.h" OneUp::OneUp(const Vector& pos) { bbox.set_pos(pos); bbox.set_size(32, 32); sprite = sprite_manager->create("1up"); physic.set_velocity(100, 400); } OneUp::~OneUp() { delete sprite; } void OneUp::action(float elapsed_time) { movement = physic.get_movement(elapsed_time); } void OneUp::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_OBJECTS); } HitResponse OneUp::collision(GameObject& other, const CollisionHit& hit) { Player* player = dynamic_cast<Player*> (&other); if(player) { player->get_status().incLives(); remove_me(); return ABORT_MOVE; } return FORCE_MOVE; } --- NEW FILE: growup.h --- #ifndef __GROWUP_H__ #define __GROWUP_H__ #include "special/moving_object.h" #include "special/sprite.h" #include "math/physic.h" using namespace SuperTux; class GrowUp : public MovingObject { public: GrowUp(const Vector& pos); ~GrowUp(); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); private: Sprite* sprite; Physic physic; }; #endif --- NEW FILE: block.h --- #ifndef __BOX_H__ #define __BOX_H__ #include "special/moving_object.h" namespace SuperTux { class Sprite; } class Player; using namespace SuperTux; class Block : public MovingObject { public: Block(const Vector& pos, Sprite* sprite); ~Block(); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); protected: virtual void hit(Player* player) = 0; void start_bounce(); Sprite* sprite; bool bouncing; float bounce_dir; float bounce_offset; float original_y; }; class BonusBlock : public Block { public: BonusBlock(const Vector& pos, int data); protected: virtual void hit(Player* player); private: int data; }; class Brick : public Block { public: Brick(const Vector& pos, int data); protected: virtual void hit(Player* player); private: bool breakable; int coin_counter; }; #endif --- NEW FILE: coin.h --- #ifndef __COIN_H__ #define __COIN_H__ #include "special/moving_object.h" namespace SuperTux { class Sprite; } using namespace SuperTux; class Coin : public MovingObject { public: Coin(const Vector& pos); ~Coin(); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); private: Sprite* sprite; }; #endif --- NEW FILE: star.cpp --- #include <config.h> #include "star.h" #include "resources.h" #include "player.h" #include "scene.h" #include "special/sprite_manager.h" #include "video/drawing_context.h" static const float INITIALJUMP = 400; static const float SPEED = 150; static const float JUMPSPEED = 300; Star::Star(const Vector& pos) { bbox.set_pos(pos); bbox.set_size(32, 32); sprite = sprite_manager->create("star"); physic.set_velocity(SPEED, INITIALJUMP); } Star::~Star() { delete sprite; } void Star::action(float elapsed_time) { movement = physic.get_movement(elapsed_time); } void Star::draw(DrawingContext& context) { sprite->draw(context, get_pos(), LAYER_OBJECTS); } HitResponse Star::collision(GameObject& other, const CollisionHit& hit) { if(other.get_flags() & FLAG_SOLID) { if(hit.normal.y < -.5) { // ground physic.set_velocity_y(JUMPSPEED); } else if(hit.normal.y > .5) { // roof physic.set_velocity_y(0); } else { // bumped left or right physic.set_velocity_x(-physic.get_velocity_x()); } return CONTINUE; } Player* player = dynamic_cast<Player*> (&other); if(player) { player->make_invincible(); remove_me(); return ABORT_MOVE; } return FORCE_MOVE; } --- NEW FILE: oneup.h --- #ifndef __ONEUP_H__ #define __ONEUP_H__ #include "special/moving_object.h" #include "special/sprite.h" #include "math/physic.h" using namespace SuperTux; class OneUp : public MovingObject { public: OneUp(const Vector& pos); ~OneUp(); virtual void action(float elapsed_time); virtual void draw(DrawingContext& context); virtual HitResponse collision(GameObject& other, const CollisionHit& hit); private: Sprite* sprite; Physic physic; }; #endif --- NEW FILE: fireworks.h --- #ifndef __FIREWORKS_H__ #define __FIREWORKS_H__ #include "video/drawing_context.h" #include "special/game_object.h" #include "timer.h" class Fireworks : public SuperTux::GameObject { public: Fireworks(); ~Fireworks(); virtual void action(float elapsed_time); virtual void draw(SuperTux::DrawingContext& context); private: Timer2 timer; }; #endif --- NEW FILE: bullet.h --- #ifndef __BULLET_H__ #define __BULLET_H__ #include "special/moving_object.h" #include "math/physic.h" #include "special/sprite.h" using namespace SuperTux; enum BulletsKind { FIRE_BULLET, ICE_BULLET }; class Bullet : public MovingObject { public: Bullet(const Vector& pos, float xm, int dir, int kind); ~Bullet(); void action(float elapsed_time); void draw(DrawingContext& context); HitResponse collision(GameObject& other, const CollisionHit& hit); int kind; private: int life_count; Physic physic; Sprite* sprite; }; #endif --- NEW FILE: fireworks.cpp --- #include <config.h> #include "fireworks.h" #include "resources.h" #include "sector.h" #include "camera.h" #include "app/globals.h" #include "video/drawing_context.h" #include "audio/sound_manager.h" using namespace SuperTux; Fireworks::Fireworks() { timer.start(.2); } Fireworks::~Fireworks() { } void Fireworks::action(float ) { if(timer.check()) { Sector* sector = Sector::current(); Vector pos = sector->camera->get_translation(); pos += Vector(screen->w * ((float) rand() / RAND_MAX), screen->h/2 * ((float) rand() / RAND_MAX)); int red = rand() % 255; int green = rand() % red; sector->add_particles(pos, 0, 360, Vector(140, 140), Vector(0, 0), 45, Color(red, green, 0), 3, 1300, LAYER_FOREGROUND1+1); SoundManager::get()->play_sound(IDToSound(SND_FIREWORKS)); timer.start(((float) rand() / RAND_MAX) + .5); } } void Fireworks::draw(DrawingContext& ) { } |