game_object.h \
display_manager.h \
display_manager.cpp \
+drawable.h \
background.h \
background.cpp \
tilemap.h \
-tilemap.cpp
+tilemap.cpp \
+moving_object.h \
+moving_object.cpp
# EOF #
global_frame_counter = 0;
game_pause = false;
+ fps_fps = 0;
fps_timer.init(true);
frame_timer.init(true);
{
char str[60];
- sprintf(str, "%d", player_status.score);
+ snprintf(str, 60, "%d", player_status.score);
white_text->draw("SCORE", 0, 0, 1);
gold_text->draw(str, 96, 0, 1);
}
-/* Object Manager */
-//---------------------------------------------------------------------------
-
-ObjectManager::ObjectManager()
-{
- std::string filename = datadir + "/images/tilesets/supertux.stbg";
- load_badguys(filename);
-}
-
-ObjectManager::~ObjectManager()
-{
- for(std::vector<BadGuy*>::iterator i = badguys.begin(); i != badguys.end(); ++i) {
- delete *i;
- }
-}
-
-void ObjectManager::load_badguys(std::string filename)
-{
- (void) filename;
-/*
- lisp_object_t* root_obj = lisp_read_from_file(filename);
-
- if (!root_obj)
- st_abort("Couldn't load file", filename);
-
- if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-badguys") == 0)
- {
- lisp_object_t* cur = lisp_cdr(root_obj);
-
- while(!lisp_nil_p(cur))
- {
- lisp_object_t* element = lisp_car(cur);
-
- if (strcmp(lisp_symbol(lisp_car(element)), "badguy") == 0)
- {
-
-
- Tile* tile = new Tile;
- tile->id = -1;
- tile->solid = false;
- tile->brick = false;
- tile->ice = false;
- tile->water = false;
- tile->fullbox = false;
- tile->distro = false;
- tile->goal = false;
- tile->data = 0;
- tile->next_tile = 0;
- tile->anim_speed = 25;
-
- LispReader reader(lisp_cdr(element));
- assert(reader.read_int("id", &tile->id));
- reader.read_bool("solid", &tile->solid);
- reader.read_bool("brick", &tile->brick);
- reader.read_bool("ice", &tile->ice);
- reader.read_bool("water", &tile->water);
- reader.read_bool("fullbox", &tile->fullbox);
- reader.read_bool("distro", &tile->distro);
- reader.read_bool("goal", &tile->goal);
- reader.read_int("data", &tile->data);
- reader.read_int("anim-speed", &tile->anim_speed);
- reader.read_int("next-tile", &tile->next_tile);
- reader.read_string_vector("images", &tile->filenames);
- reader.read_string_vector("editor-images", &tile->editor_filenames);
-
- for(std::vector<std::string>::iterator it = tile->
- filenames.begin();
- it != tile->filenames.end();
- ++it)
- {
- Surface* cur_image;
- tile->images.push_back(cur_image);
- tile->images[tile->images.size()-1] = new Surface(
- datadir + "/images/tilesets/" + (*it),
- USE_ALPHA);
- }
- for(std::vector<std::string>::iterator it = tile->editor_filenames.begin();
- it != tile->editor_filenames.end();
- ++it)
- {
- Surface* cur_image;
- tile->editor_images.push_back(cur_image);
- tile->editor_images[tile->editor_images.size()-1] = new Surface(
- datadir + "/images/tilesets/" + (*it),
- USE_ALPHA);
- }
-
- if (tile->id + tileset_id >= int(tiles.size())
- )
- tiles.resize(tile->id + tileset_id+1);
-
- tiles[tile->id + tileset_id] = tile;
- }
- else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
- {
- LispReader reader(lisp_cdr(element));
- std::string filename;
- reader.read_string("file", &filename);
- filename = datadir + "/images/tilesets/" + filename;
- load_tileset(filename);
- }
- else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
- {
- TileGroup new_;
- LispReader reader(lisp_cdr(element));
- reader.read_string("name", &new_.name);
- reader.read_int_vector("tiles", &new_.tiles);
- if(!tilegroups_)
- tilegroups_ = new std::set<TileGroup>;
- tilegroups_->insert(new_).first;
- }
- else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
- {
- LispReader reader(lisp_cdr(element));
- reader.read_int("id", &tileset_id);
- tileset_id *= 1000;
- }
- else
- {
- puts("Unhandled symbol");
- }
-
- cur = lisp_cdr(cur);
- }
- }
- else
- {
- assert(0);
- }
-
- lisp_free(root_obj);
-*/
-}
-
-void ObjectManager::draw_bg()
-{
-/*
- for (unsigned int i = 0; i < bouncy_bricks.size(); ++i)
- bouncy_bricks[i]->draw();
-
- for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
- (*i)->draw();
-
- for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
- (*i)->draw();
-*/
-}
-
-void ObjectManager::draw_fg()
-{
-/*
- for (unsigned int i = 0; i < bullets.size(); ++i)
- bullets[i].draw();
-
- for (unsigned int i = 0; i < floating_scores.size(); ++i)
- floating_scores[i]->draw();
-
- for (unsigned int i = 0; i < upgrades.size(); ++i)
- upgrades[i].draw();
-
- for (unsigned int i = 0; i < bouncy_distros.size(); ++i)
- bouncy_distros[i]->draw();
-
- for (unsigned int i = 0; i < broken_bricks.size(); ++i)
- broken_bricks[i]->draw();
-*/
-}
-
-void ObjectManager::actions()
-{
-/*
- for (unsigned int i = 0; i < bouncy_distros.size(); i++)
- bouncy_distros[i]->action(frame_ratio);
-
- for (unsigned int i = 0; i < broken_bricks.size(); i++)
- broken_bricks[i]->action(frame_ratio);
-
- // Handle all kinds of game objects
- for (unsigned int i = 0; i < bouncy_bricks.size(); i++)
- bouncy_bricks[i]->action(frame_ratio);
-
- for (unsigned int i = 0; i < floating_scores.size(); i++)
- floating_scores[i]->action(frame_ratio);
-
- for (unsigned int i = 0; i < bullets.size(); ++i)
- bullets[i].action(frame_ratio);
-
- for (unsigned int i = 0; i < upgrades.size(); i++)
- upgrades[i].action(frame_ratio);
-
- for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
- (*i)->action(frame_ratio);
-
- for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
- (*i)->action(frame_ratio);
-*/
-}
-
-/* EOF */
-
void load_object_gfx();
-
-class ObjectManager
-{
- private:
- ObjectManager();
- ~ObjectManager();
-
- static ObjectManager* instance_;
-
- // XXX Objects will have to be split up into two categories:
- // - Drawn before tux
- // - Drawn after tux
- // Eventually Player should be a part of ObjectManager
-
- std::vector<BadGuy*> badguys;
- std::vector<Trampoline> trampolines;
- std::vector<BouncyDistro> bouncy_distros;
- std::vector<BrokenBrick> broken_bricks;
- std::vector<BouncyBrick> bouncy_bricks;
- //std::vector<Upgrade> upgrades;
- //std::vector<Bullet> bullets;
-
- void load_badguys(std::string filename);
-
- public:
- static ObjectManager* instance() { return instance_ ? instance_ : instance_ = new ObjectManager(); }
- static void destroy_instance() { delete instance_; instance_ = 0; }
-
- void draw_bg();
- void draw_fg();
- void actions();
-
-/* Object* get(unsigned int id) {
- if(id < badguys.size())
- {
- return badguys[id];
- }
- else
- {
- // Never return 0, but return the 0th tile instead so that
- // user code doesn't have to check for NULL pointers all over
- // the place
- return badguys[0];
- }
- }
-*/
-};
-
#endif
/* Local Variables: */
--- /dev/null
+#include "moving_object.h"
+
+MovingObject::MovingObject()
+{
+}
+
+MovingObject::~MovingObject()
+{
+}
+
--- /dev/null
+#ifndef __MOVING_OBJECT_H__
+#define __MOVING_OBJECT_H__
+
+#include "type.h"
+#include "game_object.h"
+#include "vector.h"
+//#include "rectangle.h"
+
+/**
+ * Base class for all dynamic/moving game objects. This class contains things
+ * for handling the bounding boxes and collision feedback.
+ */
+class MovingObject : public _GameObject
+{
+public:
+ MovingObject();
+ virtual ~MovingObject();
+
+ /** this function is called when the object collided with any other object
+ */
+ virtual void collision(const MovingObject& other_object,
+ int collision_type) = 0;
+
+ base_type base;
+ base_type old_base;
+
+protected:
+#if 0 // this will be used in my collision detection rewrite later
+ /// the current position of the object
+ Vector pos;
+ /// the position we want to move until next frame
+ Vector new_pos;
+ /// the bounding box relative to the current position
+ Rectangle bounding_box;
+#endif
+};
+
+#endif
+
pplayer_input->old_up = UP;
}
+Player::Player(DisplayManager& display_manager)
+{
+ display_manager.add_drawable(this, LAYER_OBJECTS);
+ init();
+}
+
+Player::~Player()
+{
+}
+
void
Player::init()
{
}
void
-Player::action(double frame_ratio)
+Player::action(float elapsed_time)
{
bool jumped_in_solid = false;
if(dying == DYING_NOT)
handle_input();
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if(dying == DYING_NOT)
{
if(!duck && on_ground() && old_base.x == base.x && old_base.y == base.y
&& collision_object_map(base))
{
- base.x += frame_ratio * WALK_SPEED * (dir ? 1: -1);
+ base.x += elapsed_time * WALK_SPEED * (dir ? 1: -1);
previous_base = old_base = base;
}
}
void
-Player::draw()
+Player::draw(ViewPort& viewport, int )
{
+ float scroll_x = viewport.get_translation().x;
+ float scroll_y = viewport.get_translation().y;
+
if (!safe_timer.started() || (global_frame_counter % 2) == 0)
{
if (dying == DYING_SQUISHED)
}
void
+Player::collision(const MovingObject& other, int collision_type)
+{
+ (void) other;
+ (void) collision_type;
+ // will be implemented later
+}
+
+void
Player::collision(void* p_c_object, int c_object)
{
BadGuy* pbad_c = NULL;
#include "texture.h"
#include "collision.h"
#include "sound.h"
+#include "moving_object.h"
+#include "drawable.h"
#include "physic.h"
/* Times: */
extern PlayerSprite firetux;
extern PlayerSprite icetux;
-class Player : public GameObject
+class Player : public MovingObject, public Drawable
{
public:
enum HurtMode { KILL, SHRINK };
Physic physic;
public:
+ Player(DisplayManager& display_manager);
+ virtual ~Player();
+
void init();
int key_event(SDLKey key, int state);
void level_begin();
- void action(double frame_ratio);
void handle_input();
void grabdistros();
- void draw();
+
+ virtual void action(float elapsed_time);
+ virtual void draw(ViewPort& viewport, int layer);
+ virtual void collision(const MovingObject& other_object,
+ int collision_type);
+ virtual std::string type() const
+ { return "Player"; }
+
void collision(void* p_c_object, int c_object);
void kill(HurtMode mode);
void is_dying();
bool under_solid();
void grow();
- std::string type() { return "Player";};
-
private:
void handle_horizontal_input();
void handle_vertical_input();
current_ = this;
level = new Level(filename);
- tux.init();
+
+ tux = new Player(displaymanager);
+ gameobjects.push_back(tux);
set_defaults();
current_ = this;
level = new Level(subset, level_nr);
- tux.init();
+ tux->init();
set_defaults();
void
World::apply_bonuses()
{
+#if 0
// Apply bonuses from former levels
switch (player_status.bonus)
{
break;
case PlayerStatus::FLOWER_BONUS:
- tux.got_power = tux.FIRE_POWER; // FIXME: add ice power to here
+ tux->got_power = tux.FIRE_POWER; // FIXME: add ice power to here
// fall through
case PlayerStatus::GROWUP_BONUS:
// FIXME: Move this to Player class
- tux.size = BIG;
- tux.base.height = 64;
- tux.base.y -= 32;
+ tux->size = BIG;
+ tux->base.height = 64;
+ tux->base.y -= 32;
break;
}
+#endif
}
World::~World()
for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
(*i)->draw();
- tux.draw();
-
for (unsigned int i = 0; i < bullets.size(); ++i)
bullets[i].draw();
void
World::action(double frame_ratio)
{
- tux.action(frame_ratio);
- tux.check_bounds(level->back_scrolling, (bool)level->hor_autoscroll_speed);
+ tux->check_bounds(level->back_scrolling, (bool)level->hor_autoscroll_speed);
scrolling(frame_ratio);
for (unsigned int i = 0; i < bullets.size(); ++i)
for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
(*i)->action(frame_ratio);
- /* update objects */
- for(std::vector<_GameObject*>::iterator i = gameobjects.begin();
- i != gameobjects.end(); ++i)
- (*i)->action(frame_ratio);
+ /* update objects (don't use iterators here, because the list might change
+ * during the iteration)
+ */
+ for(size_t i = 0; i < gameobjects.size(); ++i)
+ gameobjects[i]->action(frame_ratio);
/* Handle all possible collisions. */
collision_handler();
{
/* Y-axis scrolling */
- float tux_pos_y = tux.base.y + (tux.base.height/2);
+ float tux_pos_y = tux->base.y + (tux->base.height/2);
- if(level->height > VISIBLE_TILES_Y-1 && !tux.dying)
+ if(level->height > VISIBLE_TILES_Y-1 && !tux->dying)
{
if (scroll_y < tux_pos_y - (screen->h - Y_SPACE))
scroll_y = tux_pos_y - (screen->h - Y_SPACE);
/* Horizontal backscrolling */
- float tux_pos_x = tux.base.x + (tux.base.width/2);
+ float tux_pos_x = tux->base.x + (tux->base.width/2);
- if(tux.old_dir != tux.dir && level->back_scrolling)
+ if(tux->old_dir != tux->dir && level->back_scrolling)
scrolling_timer.start(CHANGE_DIR_SCROLL_SPEED);
bool right = false;
bool left = false;
- if (tux.physic.get_velocity_x() > 0)
+ if (tux->physic.get_velocity_x() > 0)
right = true;
- else if (tux.physic.get_velocity_x() < 0)
+ else if (tux->physic.get_velocity_x() < 0)
left = true;
else
{
- if (tux.dir == RIGHT)
+ if (tux->dir == RIGHT)
right = true;
else
left = true;
else
final_scroll_x = tux_pos_x - X_SPACE;
- if((tux.physic.get_velocity_x() > 0 && tux.dir == RIGHT) || (tux.physic.get_velocity_x() < 0 && tux.dir == LEFT))
+ if((tux->physic.get_velocity_x() > 0 && tux->dir == RIGHT)
+ || (tux->physic.get_velocity_x() < 0 && tux->dir == LEFT))
{
constant1 = 1.0;
constant2 = .4;
if(left) number *= -1.;
scroll_x += number
- + constant1 * tux.physic.get_velocity_x() * frame_ratio
- + constant2 * tux.physic.get_acceleration_x() * frame_ratio * frame_ratio;
+ + constant1 * tux->physic.get_velocity_x() * frame_ratio
+ + constant2 * tux->physic.get_acceleration_x() * frame_ratio * frame_ratio;
if ((right && final_scroll_x - scroll_x < 0) || (left && final_scroll_x - scroll_x > 0))
scroll_x = final_scroll_x;
}
}
- if(tux.dying != DYING_NOT) return;
+ if(tux->dying != DYING_NOT) return;
// CO_BADGUY & CO_PLAYER check
for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
if((*i)->dying != DYING_NOT)
continue;
- if(rectcollision_offset((*i)->base, tux.base, 0, 0))
+ if(rectcollision_offset((*i)->base, tux->base, 0, 0))
{
// We have detected a collision and now call the collision
// functions of the collided objects.
- if (tux.previous_base.y < tux.base.y &&
- tux.previous_base.y + tux.previous_base.height
+ if (tux->previous_base.y < tux->base.y &&
+ tux->previous_base.y + tux->previous_base.height
< (*i)->base.y + (*i)->base.height/2
- && !tux.invincible_timer.started())
+ && !tux->invincible_timer.started())
{
- (*i)->collision(&tux, CO_PLAYER, COLLISION_SQUISH);
+ (*i)->collision(tux, CO_PLAYER, COLLISION_SQUISH);
}
else
{
- tux.collision(*i, CO_BADGUY);
- (*i)->collision(&tux, CO_PLAYER, COLLISION_NORMAL);
+ tux->collision(*i, CO_BADGUY);
+ (*i)->collision(tux, CO_PLAYER, COLLISION_NORMAL);
}
}
}
// CO_UPGRADE & CO_PLAYER check
for(unsigned int i = 0; i < upgrades.size(); ++i)
{
- if(rectcollision(upgrades[i].base, tux.base))
+ if(rectcollision(upgrades[i].base, tux->base))
{
// We have detected a collision and now call the collision
// functions of the collided objects.
- upgrades[i].collision(&tux, CO_PLAYER, COLLISION_NORMAL);
+ upgrades[i].collision(tux, CO_PLAYER, COLLISION_NORMAL);
}
}
// CO_TRAMPOLINE & (CO_PLAYER or CO_BADGUY)
for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
{
- if (rectcollision((*i)->base, tux.base))
+ if (rectcollision((*i)->base, tux->base))
{
- if (tux.previous_base.y < tux.base.y &&
- tux.previous_base.y + tux.previous_base.height
+ if (tux->previous_base.y < tux->base.y &&
+ tux->previous_base.y + tux->previous_base.height
< (*i)->base.y + (*i)->base.height/2)
{
- (*i)->collision(&tux, CO_PLAYER, COLLISION_SQUISH);
+ (*i)->collision(tux, CO_PLAYER, COLLISION_SQUISH);
}
- else if (tux.previous_base.y <= tux.base.y)
+ else if (tux->previous_base.y <= tux->base.y)
{
- tux.collision(*i, CO_TRAMPOLINE);
- (*i)->collision(&tux, CO_PLAYER, COLLISION_NORMAL);
+ tux->collision(*i, CO_TRAMPOLINE);
+ (*i)->collision(tux, CO_PLAYER, COLLISION_NORMAL);
}
}
}
void
World::add_bullet(float x, float y, float xm, Direction dir)
{
- if(tux.got_power == tux.FIRE_POWER)
+ if(tux->got_power == Player::FIRE_POWER)
{
if(bullets.size() > MAX_FIRE_BULLETS-1)
return;
}
- else if(tux.got_power == tux.ICE_POWER)
+ else if(tux->got_power == Player::ICE_POWER)
{
if(bullets.size() > MAX_ICE_BULLETS-1)
return;
}
Bullet new_bullet;
- if(tux.got_power == tux.FIRE_POWER)
+ if(tux->got_power == Player::FIRE_POWER)
new_bullet.init(x,y,xm,dir, FIRE_BULLET);
- else if(tux.got_power == tux.ICE_POWER)
+ else if(tux->got_power == Player::ICE_POWER)
new_bullet.init(x,y,xm,dir, ICE_BULLET);
bullets.push_back(new_bullet);
break;
case 2: // Add a fire flower upgrade!
- if (tux.size == SMALL) /* Tux is small, add mints! */
+ if (tux->size == SMALL) /* Tux is small, add mints! */
add_upgrade(posx, posy, col_side, UPGRADE_GROWUP);
else /* Tux is big, add a fireflower: */
add_upgrade(posx, posy, col_side, UPGRADE_FIREFLOWER);
break;
case 5: // Add an ice flower upgrade!
- if (tux.size == SMALL) /* Tux is small, add mints! */
+ if (tux->size == SMALL) /* Tux is small, add mints! */
add_upgrade(posx, posy, col_side, UPGRADE_GROWUP);
else /* Tux is big, add an iceflower: */
add_upgrade(posx, posy, col_side, UPGRADE_ICEFLOWER);
if ((*i)->base.x >= x - 32 && (*i)->base.x <= x + 32 &&
(*i)->base.y >= y - 16 && (*i)->base.y <= y + 16)
{
- (*i)->collision(&tux, CO_PLAYER, COLLISION_BUMP);
+ (*i)->collision(tux, CO_PLAYER, COLLISION_BUMP);
}
}
upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
{
- upgrades[i].collision(&tux, CO_PLAYER, COLLISION_BUMP);
+ upgrades[i].collision(tux, CO_PLAYER, COLLISION_BUMP);
}
}
}
typedef std::list<Trampoline*> Trampolines;
Trampolines trampolines;
Level* level;
- Player tux;
+ Player* tux;
Timer scrolling_timer;
~World();
Level* get_level() { return level; }
- Player* get_tux() { return &tux; }
+ Player* get_tux() { return tux; }
void set_defaults();