class DisplayManager;
-class Background : public _GameObject, public Drawable
+class Background : public GameObject, public Drawable
{
public:
Background(DisplayManager& displaymanager);
lispreader.read_float("y", &base.y);
base.width = 0;
base.height = 0;
- base.xm = 0;
- base.ym = 0;
kind = kind_;
base.y = y;
base.width = 0;
base.height = 0;
- base.xm = 0;
- base.ym = 0;
stay_on_platform = false;
kind = kind_;
// hack so that the bomb doesn't hurt until it expldes...
dying = DYING_SQUISHED;
} else if(kind == BAD_FLAME) {
- base.ym = 0; // we misuse base.ym as angle for the flame
+ angle = 0;
physic.enable_gravity(false);
set_sprite(img_flame, img_flame);
} else if(kind == BAD_BOUNCINGSNOWBALL) {
void
BadGuy::write(LispWriter& writer)
{
- writer.startList(badguykind_to_string(kind));
+ writer.start_list(badguykind_to_string(kind));
- writer.writeFloat("x", base.x);
- writer.writeFloat("y", base.y);
- writer.writeBool("stay-on-platform", stay_on_platform);
+ writer.write_float("x", base.x);
+ writer.write_float("y", base.y);
+ writer.write_bool("stay-on-platform", stay_on_platform);
- writer.endList(badguykind_to_string(kind));
+ writer.end_list(badguykind_to_string(kind));
}
void
{
static const float radius = 100;
static const float speed = 0.02;
- base.x = old_base.x + cos(base.ym) * radius;
- base.y = old_base.y + sin(base.ym) * radius;
+ base.x = old_base.x + cos(angle) * radius;
+ base.y = old_base.y + sin(angle) * radius;
- base.ym = fmodf(base.ym + elapsed_time * speed, 2*M_PI);
+ angle = fmodf(angle + elapsed_time * speed, 2*M_PI);
}
void
}
Sprite* sprite = (dir == LEFT) ? sprite_left : sprite_right;
- sprite->draw(base.x, base.y);
+ sprite->draw(viewport.world2screen(Vector(base.x, base.y)));
if (debug_mode)
fillrect(base.x - scroll_x, base.y - scroll_y, base.width, base.height, 75,0,75, 150);
int squishcount; /// number of times this enemy was squiched
Timer timer;
Physic physic;
+ float angle;
Sprite* sprite_left;
Sprite* sprite_right;
void
DisplayManager::remove_drawable(Drawable* drawable)
{
- for(DisplayList::iterator i = displaylist.begin();
- i != displaylist.end(); ) {
+ for(DisplayList::iterator i = displaylist.begin(); i != displaylist.end();) {
if(i->object == drawable)
i = displaylist.erase(i);
else
#include "game_object.h"
-_GameObject::_GameObject()
+GameObject::GameObject()
: wants_to_die(false)
{
}
-_GameObject::~_GameObject()
+GameObject::~GameObject()
{
}
* Most GameObjects will also implement the DrawableObject interface so that
* they can actually be drawn on screen.
*/
-class _GameObject // TODO rename this once the game has been converted
+class GameObject // TODO rename this once the game has been converted
{
public:
- _GameObject();
- virtual ~_GameObject();
+ GameObject();
+ virtual ~GameObject();
/** returns the name of the objecttype, this is mainly usefull for the editor.
* For the coding part you should use C++ RTTI (ie. typeid and dynamic_cast)
}
}
-void
-Trampoline::init(float x, float y)
+Trampoline::Trampoline(DisplayManager& displaymanager, LispReader& reader)
{
- base.x = x;
- base.y = y;
+ displaymanager.add_drawable(this, LAYER_OBJECTS);
+
+ reader.read_float("x", &base.x);
+ reader.read_float("y", &base.y);
base.width = 32;
base.height = 32;
+ power = 7.5;
+ reader.read_float("power", &power);
frame = 0;
mode = M_NORMAL;
}
void
-Trampoline::draw()
+Trampoline::write(LispWriter& writer)
{
- img_trampoline[frame]->draw((int)base.x, (int)base.y);
+ writer.start_list("trampoline");
- frame = 0;
+ writer.write_float("x", base.x);
+ writer.write_float("y", base.y);
+ writer.write_float("power", power);
- if (debug_mode)
- fillrect(base.x - scroll_x, base.y - scroll_y, base.width, base.height, 75, 75, 0, 150);
+ writer.end_list("trampoline");
}
void
-Trampoline::action(double frame_ratio)
+Trampoline::draw(ViewPort& viewport, int )
+{
+ img_trampoline[frame]->draw(viewport.world2screen(Vector(base.x, base.y)));
+ frame = 0;
+}
+
+void
+Trampoline::action(float frame_ratio)
{
// TODO: Remove if we're too far off the screen
}
void
+Trampoline::collision(const MovingObject&, int)
+{
+ // comes later
+}
+
+void
Trampoline::collision(void *p_c_object, int c_object, CollisionType type)
{
Player* pplayer_c = NULL;
#include "collision.h"
#include "game_object.h"
#include "drawable.h"
-
-enum ObjectType { OBJ_NONE, OBJ_BADGUY, OBJ_TRAMPOLINE };
-
-template <class T>
-struct ObjectData
-{
- int x;
- int y;
- ObjectType type;
- T type_specific;
-
- ObjectData(ObjectData* pobject)
- : x((int)pobject->x), y((int)pobject->y), type(pobject->type), type_specific(pobject->type_specific) {};
- ObjectData(int x_, int y_, ObjectType type_, T type_specific_)
- : x(x_), y(y_), type(type_), type_specific(type_specific_) {};
-
- ObjectData()
- : x(0), y(0), type(OBJ_NONE), type_specific() {};
-};
+#include "moving_object.h"
+#include "lispwriter.h"
/* Bounciness of distros: */
#define NO_BOUNCE 0
#define BOUNCE 1
-class BouncyDistro : public _GameObject, public Drawable
+class BouncyDistro : public GameObject, public Drawable
{
public:
BouncyDistro(DisplayManager& displaymanager, const Vector& pos);
class Tile;
-class BrokenBrick : public _GameObject, public Drawable
+class BrokenBrick : public GameObject, public Drawable
{
public:
BrokenBrick(DisplayManager& displaymanager, Tile* tile,
Vector movement;
};
-class BouncyBrick : public _GameObject, public Drawable
+class BouncyBrick : public GameObject, public Drawable
{
public:
BouncyBrick(DisplayManager& displaymanager, const Vector& pos);
int shape;
};
-class FloatingScore : public _GameObject, public Drawable
+class FloatingScore : public GameObject, public Drawable
{
public:
FloatingScore(DisplayManager& displaymanager, const Vector& pos, int s);
Timer timer;
};
-
-/* Trampoline */
-struct TrampolineData
-{
- float power;
-};
-
-class Trampoline : public GameObject
+class Trampoline : public MovingObject, public Drawable, public Serializable
{
- public:
- void init(float x, float y);
- void action(double frame_ratio);
- void draw();
- std::string type() { return "Trampoline"; };
-
- Trampoline(ObjectData<TrampolineData> data)
- {
- power = data.type_specific.power;
-
- init(data.x, data.y);
- };
+public:
+ Trampoline(DisplayManager& displaymanager, LispReader& reader);
+
+ virtual void write(LispWriter& writer);
+ virtual void action(float frame_ratio);
+ virtual void draw(ViewPort& viewport, int layer);
+ virtual std::string type() const
+ { return "Trampoline"; };
+ virtual void collision(const MovingObject& other, int);
void collision(void *p_c_object, int c_object, CollisionType type);
Physic physic;
LispWriter writer(out);
/* Write header: */
- writer.writeComment("SuperTux level made using the built-in leveleditor");
- writer.startList("supertux-level");
-
- writer.writeInt("version", 1);
- writer.writeString("name", name);
- writer.writeString("author", author);
- writer.writeString("music", song_title);
- writer.writeString("background", bkgd_image);
- writer.writeString("particle_system", particle_system);
- writer.writeInt("bkgd_speed", bkgd_speed);
- writer.writeInt("bkgd_red_top", bkgd_top.red);
- writer.writeInt("bkgd_green_top", bkgd_top.green);
- writer.writeInt("bkgd_blue_top", bkgd_top.blue);
- writer.writeInt("bkgd_red_bottom", bkgd_bottom.red);
- writer.writeInt("bkgd_green_bottom", bkgd_bottom.green);
- writer.writeInt("bkgd_blue_bottom", bkgd_bottom.blue);
- writer.writeInt("time", time_left);
- writer.writeInt("width", width);
- writer.writeInt("height", height);
- writer.writeBool("back_scrolling", back_scrolling);
- writer.writeFloat("hor_autoscroll_speed", hor_autoscroll_speed);
- writer.writeFloat("gravity", gravity);
-
- writer.writeIntVector("background-tm", bg_tiles);
- writer.writeIntVector("interactive-tm", ia_tiles);
- writer.writeIntVector("foreground-tm", fg_tiles);
-
- writer.startList("reset-points");
+ writer.write_comment("SuperTux level made using the built-in leveleditor");
+ writer.start_list("supertux-level");
+
+ writer.write_int("version", 1);
+ writer.write_string("name", name);
+ writer.write_string("author", author);
+ writer.write_string("music", song_title);
+ writer.write_string("background", bkgd_image);
+ writer.write_string("particle_system", particle_system);
+ writer.write_int("bkgd_speed", bkgd_speed);
+ writer.write_int("bkgd_red_top", bkgd_top.red);
+ writer.write_int("bkgd_green_top", bkgd_top.green);
+ writer.write_int("bkgd_blue_top", bkgd_top.blue);
+ writer.write_int("bkgd_red_bottom", bkgd_bottom.red);
+ writer.write_int("bkgd_green_bottom", bkgd_bottom.green);
+ writer.write_int("bkgd_blue_bottom", bkgd_bottom.blue);
+ writer.write_int("time", time_left);
+ writer.write_int("width", width);
+ writer.write_int("height", height);
+ writer.write_bool("back_scrolling", back_scrolling);
+ writer.write_float("hor_autoscroll_speed", hor_autoscroll_speed);
+ writer.write_float("gravity", gravity);
+
+ writer.write_int_vector("background-tm", bg_tiles);
+ writer.write_int_vector("interactive-tm", ia_tiles);
+ writer.write_int_vector("foreground-tm", fg_tiles);
+
+ writer.start_list("reset-points");
for(std::vector<ResetPoint>::iterator i = reset_points.begin();
i != reset_points.end(); ++i) {
- writer.startList("point");
- writer.writeInt("x", i->x);
- writer.writeInt("y", i->y);
+ writer.start_list("point");
+ writer.write_int("x", i->x);
+ writer.write_int("y", i->y);
}
- writer.endList("reset-points");
+ writer.end_list("reset-points");
// write objects
- writer.startList("objects");
+ writer.start_list("objects");
// pick all objects that can be written into a levelfile
- for(std::vector<_GameObject*>::iterator it = world->gameobjects.begin();
+ for(std::vector<GameObject*>::iterator it = world->gameobjects.begin();
it != world->gameobjects.end(); ++it) {
Serializable* serializable = dynamic_cast<Serializable*> (*it);
if(serializable)
serializable->write(writer);
}
- writer.endList("objects");
+ writer.end_list("objects");
- writer.endList("supertux-level");
+ writer.end_list("supertux-level");
out.close();
}
bool back_scrolling;
float hor_autoscroll_speed;
- std::vector< ObjectData<TrampolineData> > trampoline_data;
-
/** A collection of points to which Tux can be reset after a lost live */
std::vector<ResetPoint> reset_points;
public:
if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( screen->w - 32, screen->h - 32);
}
+#if 0 // XXX FIXME TODO
if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
{
le_current.obj->draw_on_screen(screen->w - 32, screen->h - 32);
le_current.obj->draw_on_screen(cursor_x,cursor_y);
}
+#endif
if(mouse_select_object && selected_game_object != NULL)
{
if(!TileManager::instance()->get(le_current.tile)->images.empty())
fillrect(cursor_x-pos_x,cursor_y-pos_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
}
+#if 0 // XXX FIXME TODO
if(le_current.IsObject())
{
le_current.obj->move_to(cursor_x, cursor_y);
}
+#endif
/* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
}
/* Draw the Bad guys: */
- for (std::vector<_GameObject*>::iterator it = le_world->gameobjects.begin();
+ for (std::vector<GameObject*>::iterator it = le_world->gameobjects.begin();
it != le_world->gameobjects.end(); ++it)
{
BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
largetux.walk_right->draw( 100 - pos_x, 240 - pos_y);
}
-void le_change_object_properties(_GameObject *pobj)
+void le_change_object_properties(GameObject *pobj)
{
Surface* cap_screen = Surface::CaptureScreen();
Menu* object_properties_menu = new Menu();
cursor_base.width = 32;
cursor_base.height = 32;
- for(std::vector<_GameObject*>::iterator it =
+ for(std::vector<GameObject*>::iterator it =
le_world->gameobjects.begin();
it != le_world->gameobjects.end(); ++it) {
MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
}
void
-LispWriter::writeComment(const std::string& comment)
+LispWriter::write_comment(const std::string& comment)
{
out << "; " << comment << "\n";
}
void
-LispWriter::startList(const std::string& listname)
+LispWriter::start_list(const std::string& listname)
{
indent();
out << '(' << listname << '\n';
}
void
-LispWriter::endList(const std::string& listname)
+LispWriter::end_list(const std::string& listname)
{
if(lists.size() == 0) {
std::cerr << "Trying to close list '" << listname
}
void
-LispWriter::writeInt(const std::string& name, int value)
+LispWriter::write_int(const std::string& name, int value)
{
indent();
out << '(' << name << ' ' << value << ")\n";
}
void
-LispWriter::writeFloat(const std::string& name, float value)
+LispWriter::write_float(const std::string& name, float value)
{
indent();
out << '(' << name << ' ' << value << ")\n";
}
void
-LispWriter::writeString(const std::string& name, const std::string& value)
+LispWriter::write_string(const std::string& name, const std::string& value)
{
indent();
out << '(' << name << " \"" << value << "\")\n";
}
void
-LispWriter::writeBool(const std::string& name, bool value)
+LispWriter::write_bool(const std::string& name, bool value)
{
indent();
out << '(' << name << ' ' << (value ? "#t" : "#f") << ")\n";
}
void
-LispWriter::writeIntVector(const std::string& name,
+LispWriter::write_int_vector(const std::string& name,
const std::vector<int>& value)
{
indent();
}
void
-LispWriter::writeIntVector(const std::string& name,
+LispWriter::write_int_vector(const std::string& name,
const std::vector<unsigned int>& value)
{
indent();
LispWriter(std::ostream& out);
~LispWriter();
- void writeComment(const std::string& comment);
+ void write_comment(const std::string& comment);
- void startList(const std::string& listname);
+ void start_list(const std::string& listname);
- void writeInt(const std::string& name, int value);
- void writeFloat(const std::string& name, float value);
- void writeString(const std::string& name, const std::string& value);
- void writeBool(const std::string& name, bool value);
- void writeIntVector(const std::string& name, const std::vector<int>& value);
- void writeIntVector(const std::string& name, const std::vector<unsigned int>& value);
+ void write_int(const std::string& name, int value);
+ void write_float(const std::string& name, float value);
+ void write_string(const std::string& name, const std::string& value);
+ void write_bool(const std::string& name, bool value);
+ void write_int_vector(const std::string& name, const std::vector<int>& value);
+ void write_int_vector(const std::string& name, const std::vector<unsigned int>& value);
// add more write-functions when needed...
- void endList(const std::string& listname);
+ void end_list(const std::string& listname);
private:
void indent();
MovingObject::MovingObject()
{
+ base.x = base.y = base.width = base.height = 0;
+ old_base = base;
}
MovingObject::~MovingObject()
* Base class for all dynamic/moving game objects. This class contains things
* for handling the bounding boxes and collision feedback.
*/
-class MovingObject : public _GameObject
+class MovingObject : public GameObject
{
public:
MovingObject();
* initialize particles in the constructor and move them in the simulate
* function.
*/
-class ParticleSystem : public _GameObject, public Drawable
+class ParticleSystem : public GameObject, public Drawable
{
public:
ParticleSystem(DisplayManager& displaymanager);
base.x = plevel->start_pos_x;
base.y = plevel->start_pos_y;
- base.xm = 0;
- base.ym = 0;
previous_base = old_base = base;
dir = RIGHT;
old_dir = dir;
{
base.x = 100;
base.y = 170;
- base.xm = 0;
- base.ym = 0;
previous_base = old_base = base;
duck = false;
if (input.fire == DOWN && input.old_fire == UP && got_power != NONE_POWER)
{
holding_something = true;
- World::current()->add_bullet(base.x, base.y + (base.height/2), physic.get_velocity_x(), dir);
+ World::current()->add_bullet(Vector(base.x, base.y + (base.height/2)),
+ physic.get_velocity_x(), dir);
input.old_fire = DOWN;
}
void
Player::draw(ViewPort& viewport, int )
{
- float scroll_x = viewport.get_translation().x;
- float scroll_y = viewport.get_translation().y;
+ Vector pos = viewport.world2screen(Vector(base.x, base.y));
if (!safe_timer.started() || (global_frame_counter % 2) == 0)
{
if (dying == DYING_SQUISHED)
{
- smalltux_gameover->draw(base.x, base.y);
+ smalltux_gameover->draw(pos);
}
else
{
if (duck && size != SMALL)
{
if (dir == RIGHT)
- sprite->duck_right->draw(base.x, base.y);
+ sprite->duck_right->draw(pos);
else
- sprite->duck_left->draw(base.x, base.y);
+ sprite->duck_left->draw(pos);
}
else if (skidding_timer.started())
{
if (dir == RIGHT)
- sprite->skid_right->draw(base.x, base.y);
+ sprite->skid_right->draw(pos);
else
- sprite->skid_left->draw(base.x, base.y);
+ sprite->skid_left->draw(pos);
}
else if (kick_timer.started())
{
if (dir == RIGHT)
- sprite->kick_right->draw(base.x, base.y);
+ sprite->kick_right->draw(pos);
else
- sprite->kick_left->draw(base.x, base.y);
+ sprite->kick_left->draw(pos);
}
else if (physic.get_velocity_y() != 0)
{
if (dir == RIGHT)
- sprite->jump_right->draw(base.x, base.y);
+ sprite->jump_right->draw(pos);
else
- sprite->jump_left->draw(base.x, base.y);
+ sprite->jump_left->draw(pos);
}
else
{
if (fabsf(physic.get_velocity_x()) < 1.0f) // standing
{
if (dir == RIGHT)
- sprite->stand_right->draw( base.x, base.y);
+ sprite->stand_right->draw(pos);
else
- sprite->stand_left->draw( base.x, base.y);
+ sprite->stand_left->draw(pos);
}
else // moving
{
if (dir == RIGHT)
- sprite->walk_right->draw(base.x, base.y);
+ sprite->walk_right->draw(pos);
else
- sprite->walk_left->draw(base.x, base.y);
+ sprite->walk_left->draw(pos);
}
}
if (holding_something && physic.get_velocity_y() == 0)
{
if (dir == RIGHT)
- sprite->grab_right->draw(base.x, base.y);
+ sprite->grab_right->draw(pos);
else
- sprite->grab_left->draw(base.x, base.y);
+ sprite->grab_left->draw(pos);
}
// Draw blinking star overlay
(invincible_timer.get_left() > TUX_INVINCIBLE_TIME_WARNING || global_frame_counter % 3))
{
if (size == SMALL || duck)
- smalltux_star->draw(base.x, base.y);
+ smalltux_star->draw(pos);
else
- largetux_star->draw(base.x, base.y);
+ largetux_star->draw(pos);
}
}
}
#define BULLET_STARTING_YM 0
#define BULLET_XM 6
-void
-Bullet::init(float x, float y, float xm, Direction dir, int kind_)
+Bullet::Bullet(DisplayManager& display_manager, const Vector& pos, float xm,
+ int dir, int kind_)
{
+ display_manager.add_drawable(this, LAYER_OBJECTS);
+
life_count = 3;
base.width = 4;
base.height = 4;
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.height/2;
- base.ym = BULLET_STARTING_YM;
+ base.y = pos.y + base.height/2;
+ physic.set_velocity_y(-BULLET_STARTING_YM);
old_base = base;
kind = kind_;
}
void
-Bullet::remove_me()
+Bullet::action(float elapsed_time)
{
- std::vector<Bullet>& bullets = World::current()->bullets;
- for(std::vector<Bullet>::iterator i = bullets.begin();
- i != bullets.end(); ++i) {
- if( & (*i) == this) {
- bullets.erase(i);
- return;
- }
- }
-
- assert(false);
-}
-
-void
-Bullet::action(double frame_ratio)
-{
- frame_ratio *= 0.5f;
+ elapsed_time *= 0.5f;
float old_y = base.y;
- base.x = base.x + base.xm * frame_ratio;
- base.y = base.y + base.ym * frame_ratio;
-
+ physic.apply(elapsed_time, base.x, base.y);
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;
+ physic.set_velocity_y(-physic.get_velocity_y());
life_count -= 1;
}
if(kind == FIRE_BULLET)
- base.ym = base.ym + 0.5 * frame_ratio;
- else if(kind == ICE_BULLET)
- base.ym = 0;
+ // @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);
if (base.x < scroll_x ||
base.x > scroll_x + screen->w ||
{
remove_me();
}
-
}
void
-Bullet::draw()
+Bullet::draw(ViewPort& viewport, int )
{
- if (base.x >= scroll_x - base.width &&
- base.x <= scroll_x + screen->w)
- {
- if(kind == FIRE_BULLET)
- img_firebullet->draw(base.x, base.y);
- else if(kind == ICE_BULLET)
- img_icebullet->draw(base.x, base.y);
- }
+ if(kind == FIRE_BULLET)
+ img_firebullet->draw(viewport.world2screen(Vector(base.x, base.y)));
+ else if(kind == ICE_BULLET)
+ img_icebullet->draw(viewport.world2screen(Vector(base.x, base.y)));
+}
+
+void
+Bullet::collision(const MovingObject& , int)
+{
+ // later
}
void
}
}
-void
-Upgrade::init(float x_, float y_, Direction dir_, UpgradeKind kind_)
+//---------------------------------------------------------------------------
+
+Upgrade::Upgrade(DisplayManager& display_manager, const Vector& pos,
+ Direction dir_, UpgradeKind kind_)
{
+ display_manager.add_drawable(this, LAYER_OBJECTS);
+
kind = kind_;
dir = dir_;
base.width = 32;
base.height = 0;
- base.x = x_;
- base.y = y_;
+ base.x = pos.x;
+ base.y = pos.y;
old_base = base;
physic.reset();
}
}
-void
-Upgrade::remove_me()
+Upgrade::~Upgrade()
{
- std::vector<Upgrade>& upgrades = World::current()->upgrades;
- for(std::vector<Upgrade>::iterator i = upgrades.begin();
- i != upgrades.end(); ++i) {
- if( & (*i) == this) {
- upgrades.erase(i);
- return;
- }
- }
-
- assert(false);
}
void
-Upgrade::action(double frame_ratio)
+Upgrade::action(float elapsed_time)
{
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;
}
/* Move around? */
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if(kind == UPGRADE_GROWUP) {
collision_swept_object_map(&old_base, &base);
}
}
void
-Upgrade::draw()
+Upgrade::draw(ViewPort& viewport, int)
{
SDL_Rect dest;
{
/* Rising up... */
- dest.x = (int)(base.x);
- dest.y = (int)(base.y + 32 - base.height);
+ dest.x = (int)(base.x - viewport.get_translation().x);
+ dest.y = (int)(base.y + 32 - base.height - viewport.get_translation().y);
dest.w = 32;
dest.h = (int)base.height;
{
if (kind == UPGRADE_GROWUP)
{
- img_growup->draw(
- base.x, base.y);
+ img_growup->draw(viewport.world2screen(Vector(base.x, base.y)));
}
else if (kind == UPGRADE_ICEFLOWER)
{
- img_iceflower->draw(
- base.x, base.y);
+ img_iceflower->draw(viewport.world2screen(Vector(base.x, base.y)));
}
else if (kind == UPGRADE_FIREFLOWER)
{
- img_fireflower->draw(
- base.x, base.y);
+ img_fireflower->draw(viewport.world2screen(Vector(base.x, base.y)));
}
else if (kind == UPGRADE_HERRING)
{
- img_star->draw(
- base.x, base.y);
+ img_star->draw(viewport.world2screen(Vector(base.x, base.y)));
}
else if (kind == UPGRADE_1UP)
{
- img_1up->draw( base.x, base.y);
+ img_1up->draw(viewport.world2screen(Vector(base.x, base.y)));
}
}
}
}
void
+Upgrade::collision(const MovingObject& , int)
+{
+ // later
+}
+
+void
Upgrade::collision(void* p_c_object, int c_object, CollisionType type)
{
Player* pplayer = NULL;
void load_special_gfx();
void free_special_gfx();
-class Upgrade : public GameObject
+class Upgrade : public MovingObject, public Drawable
{
public:
UpgradeKind kind;
Direction dir;
Physic physic;
- void init(float x, float y, Direction dir, UpgradeKind kind);
- void action(double frame_ratio);
- void draw();
- void collision(void* p_c_object, int c_object, CollisionType type);
- std::string type() { return "Upgrade"; };
+ Upgrade(DisplayManager& display_manager, const Vector& pos, Direction dir,
+ UpgradeKind kind);
+ virtual ~Upgrade();
- ~Upgrade() {};
+ virtual void action(float frame_ratio);
+ virtual void draw(ViewPort& viewport, int layer);
-private:
- /** removes the Upgrade from the global upgrade list. Note that after this
- * call the class doesn't exist anymore! So don't use any member variables
- * anymore then
- */
- void remove_me();
+ virtual void collision(const MovingObject& other, int);
+ void collision(void* p_c_object, int c_object, CollisionType type);
+ virtual std::string type() const
+ { return "Upgrade"; };
+
+private:
void bump(Player* player);
};
ICE_BULLET
};
-class Bullet : public GameObject
+class Bullet : public MovingObject, public Drawable
{
- public:
- int life_count;
- base_type base;
- base_type old_base;
-
- int kind;
+public:
+ Bullet(DisplayManager& manager, const Vector& pos, float xm, int dir,
+ int kind);
- void init(float x, float y, float xm, Direction dir, int kind_);
- void action(double frame_ratio);
- void draw();
+ virtual void action(float frame_ratio);
+ virtual void draw(ViewPort& viewport, int layer);
void collision(int c_object);
- std::string type() { return "Bullet"; };
+ virtual void collision(const MovingObject& other_object, int type);
+ virtual std::string type() const
+ { return "Bullet"; };
+
+ int kind;
+
private:
- /** removes the Upgrade from the global upgrade list. Note that after this
- * call the class doesn't exist anymore! So don't use any member variables
- * anymore then
- */
- void remove_me();
+ int life_count;
+ Physic physic;
};
#endif /*SUPERTUX_SPECIAL_H*/
unsigned int frame = get_current_frame();
if (frame < surfaces.size())
- surfaces[frame]->draw(x - x_hotspot - scroll_x, y - y_hotspot - scroll_y);
+ surfaces[frame]->draw(x - x_hotspot, y - y_hotspot);
}
void
unsigned int frame = get_current_frame();
if (frame < surfaces.size())
- surfaces[frame]->draw_part(sx, sy, x - x_hotspot - scroll_x, y - y_hotspot - scroll_y , w, h);
+ surfaces[frame]->draw_part(sx, sy, x - x_hotspot, y - y_hotspot, w, h);
}
void
#include <vector>
#include "lispreader.h"
#include "texture.h"
+#include "vector.h"
class Sprite
{
void draw_part(float sx, float sy, float x, float y, float w, float h);
int get_current_frame() const;
+ void draw(const Vector& pos)
+ { draw(pos.x, pos.y); }
+
std::string get_name() const { return name; }
int get_width() const;
int get_height() const;
/**
* This class is reponsible for drawing the level tiles
*/
-class TileMap : public _GameObject, public Drawable
+class TileMap : public GameObject, public Drawable
{
public:
TileMap(DisplayManager& manager, Level* level);
{
float x;
float y;
- float xm;
- float ym;
float width;
float height;
};
-
-/* Base class for all dynamic game object. */
-class GameObject
-{
-
-public:
- GameObject() {};
- virtual ~GameObject() {};
- virtual void action(double frame_ratio) = 0;
- virtual void draw() = 0;
- virtual std::string type() = 0;
- /* Draw ignoring the scroll_x value. FIXME: Hack? Should be discussed. @tobgle*/
- void draw_on_screen(float x = -1, float y = -1)
- {
- base_type btmp = base;
- if(x != -1 || y != -1)
- {
- btmp = base;
- if(x != -1)
- base.x = x;
- if(y != -1)
- base.y = y;
- }
- float tmp = scroll_x;
- scroll_x = 0; draw();
- scroll_x = tmp;
- base = btmp;
- };
-
- void move_to(float x, float y) { base.x = x; base.y = y; };
-
- base_type base;
- base_type old_base;
-};
-
struct string_list_type
{
int num_items;
// add tilemap
gameobjects.push_back(new TileMap(displaymanager, get_level()));
- activate_objects();
get_level()->load_song();
apply_bonuses();
set_defaults();
get_level()->load_gfx();
- activate_objects();
activate_particle_systems();
Background* bg = new Background(displaymanager);
if(level->img_bkgd) {
for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
delete *i;
- for (std::vector<_GameObject*>::iterator i = gameobjects.begin();
+ for (std::vector<GameObject*>::iterator i = gameobjects.begin();
i != gameobjects.end(); ++i) {
Drawable* drawable = dynamic_cast<Drawable*> (*i);
if(drawable)
}
void
-World::add_object(_GameObject* object)
+World::add_object(GameObject* object)
{
// XXX hack for now until new collision code is ready
BadGuy* badguy = dynamic_cast<BadGuy*> (object);
if(badguy)
bad_guys.push_back(badguy);
+ Bullet* bullet = dynamic_cast<Bullet*> (object);
+ if(bullet)
+ bullets.push_back(bullet);
+ Upgrade* upgrade = dynamic_cast<Upgrade*> (object);
+ if(upgrade)
+ upgrades.push_back(upgrade);
+ Trampoline* trampoline = dynamic_cast<Trampoline*> (object);
+ if(trampoline)
+ trampolines.push_back(trampoline);
gameobjects.push_back(object);
}
{
while(!lisp_nil_p(cur)) {
lisp_object_t* data = lisp_car(cur);
- std::string object_type = "";
+ std::string object_type = lisp_symbol(lisp_car(data));
LispReader reader(lisp_cdr(data));
- reader.read_string("type", &object_type);
- if(object_type == "badguy" || object_type == "")
- {
- BadGuyKind kind = badguykind_from_string(
- lisp_symbol(lisp_car(data)));
+ if(object_type == "trampoline") {
+ add_object(new Trampoline(displaymanager, reader));
+ } else {
+ BadGuyKind kind = badguykind_from_string(object_type);
add_object(new BadGuy(displaymanager, kind, reader));
}
- // TODO add parsing code for trampolines
-
+
cur = lisp_cdr(cur);
}
}
void
-World::activate_objects()
-{
- for (std::vector< ObjectData<TrampolineData> >::iterator i = level->trampoline_data.begin();
- i != level->trampoline_data.end();
- ++i)
- {
- add_object<Trampoline, ObjectData<TrampolineData> >(*i);
- }
-}
-
-void
World::activate_particle_systems()
{
if (level->particle_system == "clouds")
/* Draw objects */
displaymanager.get_viewport().set_translation(Vector(scroll_x, scroll_y));
displaymanager.draw();
-
- for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
- (*i)->draw();
-
- for (unsigned int i = 0; i < bullets.size(); ++i)
- bullets[i].draw();
-
- for (unsigned int i = 0; i < upgrades.size(); ++i)
- upgrades[i].draw();
}
void
tux->check_bounds(level->back_scrolling, (bool)level->hor_autoscroll_speed);
scrolling(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 (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
- (*i)->action(frame_ratio);
-
/* update objects (don't use iterators here, because the list might change
* during the iteration)
*/
collision_handler();
/** cleanup marked objects */
- for(std::vector<_GameObject*>::iterator i = gameobjects.begin();
+ for(std::vector<GameObject*>::iterator i = gameobjects.begin();
i != gameobjects.end(); /* nothing */) {
if((*i)->is_valid() == false) {
Drawable* drawable = dynamic_cast<Drawable*> (*i);
displaymanager.remove_drawable(drawable);
BadGuy* badguy = dynamic_cast<BadGuy*> (*i);
if(badguy) {
- std::remove(bad_guys.begin(), bad_guys.end(), badguy);
- }
+ bad_guys.erase(std::remove(bad_guys.begin(), bad_guys.end(), badguy),
+ bad_guys.end());
+ }
+ Bullet* bullet = dynamic_cast<Bullet*> (*i);
+ if(bullet) {
+ bullets.erase(
+ std::remove(bullets.begin(), bullets.end(), bullet),
+ bullets.end());
+ }
+ Upgrade* upgrade = dynamic_cast<Upgrade*> (*i);
+ if(upgrade) {
+ upgrades.erase(
+ std::remove(upgrades.begin(), upgrades.end(), upgrade),
+ upgrades.end());
+ }
+ Trampoline* trampoline = dynamic_cast<Trampoline*> (*i);
+ if(trampoline) {
+ trampolines.erase(
+ std::remove(trampolines.begin(), trampolines.end(), trampoline),
+ trampolines.end());
+ }
delete *i;
i = gameobjects.erase(i);
if((*j)->dying != DYING_NOT)
continue;
- if(rectcollision(bullets[i].base, (*j)->base))
+ if(rectcollision(bullets[i]->base, (*j)->base))
{
// We have detected a collision and now call the
// collision functions of the collided objects.
- // collide with bad_guy first, since bullet_collision will
- // delete the bullet
- (*j)->collision(&bullets[i], CO_BULLET);
- bullets[i].collision(CO_BADGUY);
+ (*j)->collision(&bullets[i], CO_BULLET, COLLISION_NORMAL);
+ bullets[i]->collision(CO_BADGUY);
break; // bullet is invalid now, so break
}
}
// 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);
}
}
return badguy;
}
-template<class T, class U>
-T*
-World::add_object(U data)
-{
- T* tobject = new T(data);
-
- if (data.type == OBJ_TRAMPOLINE)
- trampolines.push_back(tobject);
-
- return tobject;
-}
-
void
-World::add_upgrade(float x, float y, Direction dir, UpgradeKind kind)
+World::add_upgrade(const Vector& pos, Direction dir, UpgradeKind kind)
{
- Upgrade new_upgrade;
- new_upgrade.init(x,y,dir,kind);
- upgrades.push_back(new_upgrade);
+ add_object(new Upgrade(displaymanager, pos, dir, kind));
}
void
-World::add_bullet(float x, float y, float xm, Direction dir)
+World::add_bullet(const Vector& pos, float xm, Direction dir)
{
if(tux->got_power == Player::FIRE_POWER)
{
return;
}
- Bullet new_bullet;
+ Bullet* new_bullet = 0;
if(tux->got_power == Player::FIRE_POWER)
- new_bullet.init(x,y,xm,dir, FIRE_BULLET);
+ new_bullet = new Bullet(displaymanager, pos, xm, dir, FIRE_BULLET);
else if(tux->got_power == Player::ICE_POWER)
- new_bullet.init(x,y,xm,dir, ICE_BULLET);
- bullets.push_back(new_bullet);
+ new_bullet = new Bullet(displaymanager, pos, xm, dir, ICE_BULLET);
+ else
+ st_abort("wrong bullet type.", "");
+ add_object(new_bullet);
play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER);
}
case 2: // Add a fire flower upgrade!
if (tux->size == SMALL) /* Tux is small, add mints! */
- add_upgrade(posx, posy, col_side, UPGRADE_GROWUP);
+ add_upgrade(Vector(posx, posy), col_side, UPGRADE_GROWUP);
else /* Tux is big, add a fireflower: */
- add_upgrade(posx, posy, col_side, UPGRADE_FIREFLOWER);
+ add_upgrade(Vector(posx, posy), col_side, UPGRADE_FIREFLOWER);
play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
break;
case 5: // Add an ice flower upgrade!
if (tux->size == SMALL) /* Tux is small, add mints! */
- add_upgrade(posx, posy, col_side, UPGRADE_GROWUP);
+ add_upgrade(Vector(posx, posy), col_side, UPGRADE_GROWUP);
else /* Tux is big, add an iceflower: */
- add_upgrade(posx, posy, col_side, UPGRADE_ICEFLOWER);
+ add_upgrade(Vector(posx, posy), col_side, UPGRADE_ICEFLOWER);
play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
break;
case 3: // Add a golden herring
- add_upgrade(posx, posy, col_side, UPGRADE_HERRING);
+ add_upgrade(Vector(posx, posy), col_side, UPGRADE_HERRING);
break;
case 4: // Add a 1up extra
- add_upgrade(posx, posy, col_side, UPGRADE_1UP);
+ add_upgrade(Vector(posx, posy), col_side, UPGRADE_1UP);
break;
default:
break;
// Upgrades:
for (unsigned int i = 0; i < upgrades.size(); i++)
{
- if (upgrades[i].base.height == 32 &&
- upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
- upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
+ if (upgrades[i]->base.height == 32 &&
+ 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);
}
}
}
public:
BadGuys bad_guys;
- std::vector<Upgrade> upgrades;
- std::vector<Bullet> bullets;
- std::vector<_GameObject*> gameobjects;
+ std::vector<Upgrade*> upgrades;
+ std::vector<Bullet*> bullets;
+ std::vector<GameObject*> gameobjects;
DisplayManager displaymanager;
Level* get_level() { return level; }
Player* get_tux() { return tux; }
- void add_object(_GameObject* object);
+ void add_object(GameObject* object);
void set_defaults();
void parse_objects(lisp_object_t* cur);
void activate_particle_systems();
- void activate_objects();
void add_score(const Vector& pos, int s);
void add_bouncy_distro(const Vector& pos);
void add_bouncy_brick(const Vector& pos);
BadGuy* add_bad_guy(float x, float y, BadGuyKind kind);
- template <class T, class U> T* add_object(U data);
- void add_upgrade(float x, float y, Direction dir, UpgradeKind kind);
- void add_bullet(float x, float y, float xm, Direction dir);
+ void add_upgrade(const Vector& pos, Direction dir, UpgradeKind kind);
+ void add_bullet(const Vector& pos, float xm, Direction dir);
/** Try to grab the coin at the given coordinates */
void trygrabdistro(float x, float y, int bounciness);