vector<vector>. You can access a tile like this now tiles[y * width + x] is the tile at place x,y
-introduced new Serializable interface that is implemented by all objects that
are able to save themselfes to disk
-added new lispwriter class
-changed level laoding/save code to use new serializable/lispwriter stuff
SVN-Revision: 1282
bin_PROGRAMS = supertux
supertux_SOURCES = \
+lispwriter.h \
+lispwriter.cpp \
badguy.cpp \
badguy.h \
bitmask.cpp \
tilemap.h \
tilemap.cpp \
moving_object.h \
-moving_object.cpp
+moving_object.cpp
# EOF #
#include "resources.h"
#include "sprite_manager.h"
#include "gameloop.h"
+#include "display_manager.h"
+#include "lispwriter.h"
Sprite* img_mriceblock_flat_left;
Sprite* img_mriceblock_flat_right;
}
}
-BadGuy::BadGuy(float x, float y, BadGuyKind kind_, bool stay_on_platform_)
+BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_,
+ LispReader& lispreader)
: removable(false), squishcount(0)
{
- base.x = x;
- base.y = y;
+ display_manager.add_drawable(this, LAYER_OBJECTS);
+
+ base.x = 0;
+ base.y = 0;
+ lispreader.read_float("x", &base.x);
+ lispreader.read_float("y", &base.y);
+ base.width = 0;
+ base.height = 0;
+ base.xm = 0;
+ base.ym = 0;
+
+ kind = kind_;
+
+ stay_on_platform = false;
+ lispreader.read_bool("stay-on-platform", &stay_on_platform);
+
+ init();
+}
+
+BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_,
+ float x, float y)
+{
+ display_manager.add_drawable(this, LAYER_OBJECTS);
+
+ base.x = x;
+ base.y = y;
base.width = 0;
base.height = 0;
base.xm = 0;
base.ym = 0;
+ stay_on_platform = false;
+
+ kind = kind_;
+
+ init();
+}
+
+BadGuy::~BadGuy()
+{
+}
- stay_on_platform = stay_on_platform_;
+void
+BadGuy::init()
+{
mode = NORMAL;
dying = DYING_NOT;
- kind = kind_;
old_base = base;
dir = LEFT;
seen = false;
}
void
-BadGuy::action_mriceblock(double frame_ratio)
+BadGuy::write(LispWriter& writer)
+{
+ writer.startList(badguykind_to_string(kind));
+
+ writer.writeFloat("x", base.x);
+ writer.writeFloat("y", base.y);
+ writer.writeBool("stay-on-platform", stay_on_platform);
+
+ writer.endList(badguykind_to_string(kind));
+}
+
+void
+BadGuy::action_mriceblock(double elapsed_time)
{
Player& tux = *World::current()->get_tux();
if (mode != HELD)
{
// move
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
}
}
void
-BadGuy::remove_me()
-{
- removable = true;
-}
-
-void
-BadGuy::action_jumpy(double frame_ratio)
+BadGuy::action_jumpy(double elapsed_time)
{
if(frozen_timer.check())
{
dir = LEFT;
// move
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if(dying == DYING_NOT)
collision_swept_object_map(&old_base, &base);
}
void
-BadGuy::action_mrbomb(double frame_ratio)
+BadGuy::action_mrbomb(double elapsed_time)
{
if(frozen_timer.check())
{
fall();
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
}
void
-BadGuy::action_bomb(double frame_ratio)
+BadGuy::action_bomb(double elapsed_time)
{
static const int TICKINGTIME = 1000;
static const int EXPLODETIME = 1000;
}
// move
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
collision_swept_object_map(&old_base,&base);
}
void
-BadGuy::action_stalactite(double frame_ratio)
+BadGuy::action_stalactite(double elapsed_time)
{
Player& tux = *World::current()->get_tux();
}
// move
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if(dying == DYING_SQUISHED && !timer.check())
remove_me();
}
void
-BadGuy::action_flame(double frame_ratio)
+BadGuy::action_flame(double elapsed_time)
{
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.ym = fmodf(base.ym + frame_ratio * speed, 2*M_PI);
+ base.ym = fmodf(base.ym + elapsed_time * speed, 2*M_PI);
}
void
-BadGuy::action_fish(double frame_ratio)
+BadGuy::action_fish(double elapsed_time)
{
if(frozen_timer.check())
{
physic.enable_gravity(true);
}
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if(dying == DYING_NOT)
collision_swept_object_map(&old_base, &base);
}
void
-BadGuy::action_bouncingsnowball(double frame_ratio)
+BadGuy::action_bouncingsnowball(double elapsed_time)
{
static const float JUMPV = 4.5;
// check for right/left collisions
check_horizontal_bump();
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if(dying == DYING_NOT)
collision_swept_object_map(&old_base, &base);
}
void
-BadGuy::action_flyingsnowball(double frame_ratio)
+BadGuy::action_flyingsnowball(double elapsed_time)
{
static const float FLYINGSPEED = 1;
static const int DIRCHANGETIME = 1000;
if(dying != DYING_NOT)
physic.enable_gravity(true);
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if(dying == DYING_NOT || dying == DYING_SQUISHED)
collision_swept_object_map(&old_base, &base);
}
void
-BadGuy::action_spiky(double frame_ratio)
+BadGuy::action_spiky(double elapsed_time)
{
if(frozen_timer.check())
{
}
#endif
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
}
void
-BadGuy::action_snowball(double frame_ratio)
+BadGuy::action_snowball(double elapsed_time)
{
if (dying == DYING_NOT)
check_horizontal_bump();
fall();
- physic.apply(frame_ratio, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
}
void
-BadGuy::action(double frame_ratio)
+BadGuy::action(float elapsed_time)
{
// Remove if it's far off the screen:
if (base.x < scroll_x - OFFSCREEN_DISTANCE)
switch (kind)
{
case BAD_MRICEBLOCK:
- action_mriceblock(frame_ratio);
+ action_mriceblock(elapsed_time);
break;
case BAD_JUMPY:
- action_jumpy(frame_ratio);
+ action_jumpy(elapsed_time);
break;
case BAD_MRBOMB:
- action_mrbomb(frame_ratio);
+ action_mrbomb(elapsed_time);
break;
case BAD_BOMB:
- action_bomb(frame_ratio);
+ action_bomb(elapsed_time);
break;
case BAD_STALACTITE:
- action_stalactite(frame_ratio);
+ action_stalactite(elapsed_time);
break;
case BAD_FLAME:
- action_flame(frame_ratio);
+ action_flame(elapsed_time);
break;
case BAD_FISH:
- action_fish(frame_ratio);
+ action_fish(elapsed_time);
break;
case BAD_BOUNCINGSNOWBALL:
- action_bouncingsnowball(frame_ratio);
+ action_bouncingsnowball(elapsed_time);
break;
case BAD_FLYINGSNOWBALL:
- action_flyingsnowball(frame_ratio);
+ action_flyingsnowball(elapsed_time);
break;
case BAD_SPIKY:
- action_spiky(frame_ratio);
+ action_spiky(elapsed_time);
break;
case BAD_SNOWBALL:
- action_snowball(frame_ratio);
+ action_snowball(elapsed_time);
break;
default:
break;
}
void
-BadGuy::draw()
+BadGuy::draw(ViewPort& viewport, int)
{
+ float scroll_x = viewport.get_translation().x;
+ float scroll_y = viewport.get_translation().y;
+
// Don't try to draw stuff that is outside of the screen
if(base.x <= scroll_x - base.width || base.x >= scroll_x + screen->w)
return;
if(kind == BAD_MRBOMB) {
// mrbomb transforms into a bomb now
- World::current()->add_bad_guy(base.x, base.y, BAD_BOMB);
+ explode();
make_player_jump(player);
World::current()->add_score(Vector(base.x, base.y),
50 * player_status.score_multiplier);
play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
player_status.score_multiplier++;
- remove_me();
return;
} else if (kind == BAD_MRICEBLOCK) {
play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
}
-void BadGuy::explode(BadGuy *badguy)
+void
+BadGuy::explode()
+{
+ World::current()->add_bad_guy(base.x, base.y, BAD_BOMB);
+ remove_me();
+}
+
+void
+BadGuy::collision(const MovingObject&, int)
{
-World::current()->add_bad_guy(badguy->base.x, badguy->base.y, BAD_BOMB);
-badguy->remove_me();
+ // later
}
void
if (pbad_c->kind == BAD_MRBOMB)
{
// mrbomb transforms into a bomb now
- explode(pbad_c);
+ pbad_c->explode();
return;
}
else if (pbad_c->kind != BAD_MRBOMB)
if (pbad_c->kind == BAD_MRBOMB)
{
// mrbomb transforms into a bomb now
- explode(pbad_c);
+ pbad_c->explode();
return;
}
else
#include "physic.h"
#include "collision.h"
#include "sprite.h"
+#include "moving_object.h"
+#include "drawable.h"
+#include "serializable.h"
/* Bad guy kinds: */
enum BadGuyKind {
class Player;
/* Badguy type: */
-class BadGuy : public GameObject
+class BadGuy : public MovingObject, public Drawable, public Serializable
{
public:
/* Enemy modes: */
int animation_offset;
public:
- BadGuy(float x, float y, BadGuyKind kind, bool stay_on_platform);
+ BadGuy(DisplayManager& display_manager, BadGuyKind kind, float x, float y);
+ BadGuy(DisplayManager& display_manager, BadGuyKind kind, LispReader& reader);
+ virtual ~BadGuy();
- void action(double frame_ratio);
- void draw();
- std::string type() { return "BadGuy"; };
+ virtual void write(LispWriter& writer);
- void explode(BadGuy* badguy);
+ virtual void action(float frame_ratio);
+ virtual void draw(ViewPort& viewport, int layer);
+ virtual void collision(const MovingObject& other, int type);
+ virtual std::string type() const
+ { return "BadGuy"; };
void collision(void* p_c_object, int c_object,
CollisionType type = COLLISION_NORMAL);
*/
void kill_me(int score);
- /** remove ourself from the list of badguys. WARNING! This function will
- * invalidate all members. So don't do anything else with member after calling
- * this.
- */
- void remove_me();
- bool is_removable() const { return removable; }
-
private:
+ void init();
+
void action_mriceblock(double frame_ratio);
void action_jumpy(double frame_ratio);
void action_bomb(double frame_ratio);
/** let the player jump a bit (used when you hit a badguy) */
void make_player_jump(Player* player);
+ void explode();
+
/** check if we're running left or right in a wall and eventually change
* direction
*/
void set_sprite(Sprite* left, Sprite* right);
};
-struct BadGuyData
-{
- BadGuyKind kind;
- int x;
- int y;
- bool stay_on_platform;
-
- BadGuyData(BadGuy* pbadguy) : kind(pbadguy->kind), x((int)pbadguy->base.x), y((int)pbadguy->base.y), stay_on_platform(pbadguy->stay_on_platform) {};
- BadGuyData(BadGuyKind kind_, int x_, int y_, bool stay_on_platform_)
- : kind(kind_), x(x_), y(y_), stay_on_platform(stay_on_platform_) {}
-
- BadGuyData()
- : kind(BAD_SNOWBALL), x(0), y(0), stay_on_platform(false) {}
-};
-
#endif /*SUPERTUX_BADGUY_H*/
/* Local Variables: */
#include "screen.h"
#include "globals.h"
#include "button.h"
+#include "viewport.h"
Timer Button::popup_timer;
tag = -1;
state = BUTTON_NONE;
show_info = false;
- game_object = NULL;
+ drawable = NULL;
}
void Button::add_icon(std::string icon_file, int mw, int mh)
for(std::vector<Surface*>::iterator it = icon.begin(); it != icon.end(); ++it)
(*it)->draw(rect.x,rect.y);
- if(game_object != NULL)
+ if(drawable)
{
- game_object->draw_on_screen(rect.x,rect.y);
+ ViewPort viewport;
+ viewport.set_translation(Vector(rect.x, rect.y));
+ drawable->draw(viewport, 0);
}
if(show_info)
for(std::vector<Surface*>::iterator it = icon.begin(); it != icon.end(); ++it)
delete (*it);
icon.clear();
- delete game_object;
+ delete drawable;
}
void Button::event(SDL_Event &event)
#include <vector>
#include "texture.h"
+#include "drawable.h"
enum ButtonState {
BUTTON_NONE = -1,
void add_icon(std::string icon_file, int mw, int mh);
SDL_Rect get_pos() { return rect; }
int get_tag(){return tag; }
- void set_game_object(GameObject* game_object_) { game_object = game_object_; }
- GameObject* get_game_object() { return game_object; };
+ void set_drawable(Drawable* newdrawable)
+ { drawable = newdrawable; }
private:
static Timer popup_timer;
- GameObject* game_object;
+ Drawable* drawable;
std::vector<Surface*> icon;
std::string info;
SDLKey shortcut;
#include <stdio.h>
#include <string.h>
#include <iostream>
+#include <fstream>
#include "globals.h"
#include "setup.h"
#include "screen.h"
#include "resources.h"
#include "music_manager.h"
#include "gameobjs.h"
+#include "world.h"
+#include "lispwriter.h"
using namespace std;
new_subset.description = "No description so far.";
new_subset.save();
new_lev.init_defaults();
- new_lev.save(subset_name, 1);
+ new_lev.save(subset_name, 1, 0);
}
void LevelSubset::parse (lisp_object_t* cursor)
init_defaults();
}
-Level::Level(const std::string& subset, int level)
- : img_bkgd(0)
-{
- if(load(subset, level) < 0)
- st_abort("Couldn't load level from subset", subset.c_str());
-}
-
-Level::Level(const std::string& filename)
- : img_bkgd(0)
-{
- if(load(filename) < 0)
- st_abort("Couldn't load level " , filename.c_str());
-}
-
Level::~Level()
{
delete img_bkgd;
author = "UnNamed";
song_title = "Mortimers_chipdisko.mod";
bkgd_image = "arctis.png";
- width = 21;
- height = 19;
+ width = 0;
+ height = 0;
start_pos_x = 100;
start_pos_y = 170;
time_left = 100;
bkgd_bottom.green = 255;
bkgd_bottom.blue = 255;
- bg_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
- ia_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
- fg_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
-
- for(int i = 0; i < height; ++i)
- {
- ia_tiles[i].resize(width+1, 0);
- ia_tiles[i][width] = (unsigned int) '\0';
-
- for(int y = 0; y < width; ++y)
- ia_tiles[i][y] = 0;
-
- bg_tiles[i].resize(width+1, 0);
- bg_tiles[i][width] = (unsigned int) '\0';
- for(int y = 0; y < width; ++y)
- bg_tiles[i][y] = 0;
-
- fg_tiles[i].resize(width+1, 0);
- fg_tiles[i][width] = (unsigned int) '\0';
- for(int y = 0; y < width; ++y)
- fg_tiles[i][y] = 0;
- }
+ resize(21, 19);
}
int
-Level::load(const std::string& subset, int level)
+Level::load(const std::string& subset, int level, World* world)
{
char filename[1024];
if(!faccessible(filename))
snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), subset.c_str(), level);
- return load(filename);
+ return load(filename, world);
}
int
-Level::load(const std::string& filename)
+Level::load(const std::string& filename, World* world)
{
lisp_object_t* root_obj = lisp_read_from_file(filename);
if (!root_obj)
return -1;
}
- vector<int> ia_tm;
- vector<int> bg_tm;
- vector<int> fg_tm;
-
int version = 0;
if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-level") == 0)
{
particle_system = "";
reader.read_string("particle_system", &particle_system);
- reader.read_int_vector("background-tm", &bg_tm);
+ reader.read_int_vector("background-tm", &bg_tiles);
+ if(int(bg_tiles.size()) != width * height)
+ st_abort("Wrong size of backgroundtilemap", "");
- if (!reader.read_int_vector("interactive-tm", &ia_tm))
- reader.read_int_vector("tilemap", &ia_tm);
+ if (!reader.read_int_vector("interactive-tm", &ia_tiles))
+ reader.read_int_vector("tilemap", &ia_tiles);
+ if(int(ia_tiles.size()) != width * height)
+ st_abort("Wrong size of interactivetilemap", "");
- reader.read_int_vector("foreground-tm", &fg_tm);
+ reader.read_int_vector("foreground-tm", &fg_tiles);
+ if(int(fg_tiles.size()) != width * height)
+ st_abort("Wrong size of foregroundtilemap", "");
{ // Read ResetPoints
lisp_object_t* cur = 0;
lisp_object_t* cur = 0;
if (reader.read_lisp("objects", &cur))
{
- while (!lisp_nil_p(cur))
- {
- lisp_object_t* data = lisp_car(cur);
- std::string object_type = "";
-
- LispReader reader(lisp_cdr(data));
- reader.read_string("type", &object_type);
-
- if (object_type == "badguy" || object_type == "")
- {
- BadGuyData bg_data;
- bg_data.kind = badguykind_from_string(lisp_symbol(lisp_car(data)));
- reader.read_int("x", &bg_data.x);
- reader.read_int("y", &bg_data.y);
- reader.read_bool("stay-on-platform", &bg_data.stay_on_platform);
-
- badguy_data.push_back(bg_data);
- }
- else
- {
- if (strcmp(lisp_symbol(lisp_car(data)),"trampoline") == 0)
- {
- ObjectData<TrampolineData> _trampoline_data;
-
- _trampoline_data.type = OBJ_TRAMPOLINE;
- reader.read_int("x", &_trampoline_data.x);
- reader.read_int("y", &_trampoline_data.y);
- reader.read_float("power", &_trampoline_data.type_specific.power);
-
- trampoline_data.push_back(_trampoline_data);
- }
- }
-
- cur = lisp_cdr(cur);
- }
+ if(world)
+ world->parse_objects(cur);
}
}
+#if 0 // TODO fix this or remove it
// Convert old levels to the new tile numbers
if (version == 0)
{
}
}
}
- }
-
- bg_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
- ia_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
- fg_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
-
- for(int i = 0; i < height; ++i)
- {
- ia_tiles[i].resize(width + 1, 0);
- bg_tiles[i].resize(width + 1, 0);
- fg_tiles[i].resize(width + 1, 0);
- }
-
- int i = 0;
- int j = 0;
- for(vector<int>::iterator it = ia_tm.begin(); it != ia_tm.end(); ++it, ++i)
- {
- ia_tiles[j][i] = (*it);
- if(i == width - 1)
- {
- i = -1;
- ++j;
- }
- }
-
- i = j = 0;
- for(vector<int>::iterator it = bg_tm.begin(); it != bg_tm.end(); ++it, ++i)
- {
-
- bg_tiles[j][i] = (*it);
- if(i == width - 1)
- {
- i = -1;
- ++j;
- }
- }
-
- i = j = 0;
- for(vector<int>::iterator it = fg_tm.begin(); it != fg_tm.end(); ++it, ++i)
- {
-
- fg_tiles[j][i] = (*it);
- if(i == width - 1)
- {
- i = -1;
- ++j;
- }
+#endif
}
lisp_free(root_obj);
/* Save data for level: */
void
-Level::save(const std::string& subset, int level)
+Level::save(const std::string& subset, int level, World* world)
{
char filename[1024];
char str[80];
snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(),
subset.c_str(), level);
- FILE * fi = fopen(filename, "w");
- if (fi == NULL)
- {
- perror(filename);
- st_shutdown();
- exit(-1);
- }
-
+ std::ofstream out(filename);
+ if(!out.good()) {
+ st_abort("Couldn't write file.", filename);
+ }
+ LispWriter writer(out);
/* Write header: */
- fprintf(fi,";SuperTux level made using the built-in leveleditor\n");
- fprintf(fi,"(supertux-level\n");
-
- fprintf(fi," (version %d)\n", 1);
- fprintf(fi," (name \"%s\")\n", name.c_str());
- fprintf(fi," (author \"%s\")\n", author.c_str());
- fprintf(fi," (music \"%s\")\n", song_title.c_str());
- fprintf(fi," (background \"%s\")\n", bkgd_image.c_str());
- fprintf(fi," (particle_system \"%s\")\n", particle_system.c_str());
- fprintf(fi," (bkgd_speed %d)\n", bkgd_speed);
- fprintf(fi," (bkgd_red_top %d)\n", bkgd_top.red);
- fprintf(fi," (bkgd_green_top %d)\n", bkgd_top.green);
- fprintf(fi," (bkgd_blue_top %d)\n", bkgd_top.blue);
- fprintf(fi," (bkgd_red_bottom %d)\n", bkgd_bottom.red);
- fprintf(fi," (bkgd_green_bottom %d)\n", bkgd_bottom.green);
- fprintf(fi," (bkgd_blue_bottom %d)\n", bkgd_bottom.blue);
- fprintf(fi," (time %d)\n", time_left);
- fprintf(fi," (width %d)\n", width);
- fprintf(fi," (height %d)\n", height);
- if(back_scrolling)
- fprintf(fi," (back_scrolling #t)\n");
- else
- fprintf(fi," (back_scrolling #f)\n");
- fprintf(fi," (hor_autoscroll_speed %2.1f)\n", hor_autoscroll_speed);
- fprintf(fi," (gravity %2.1f)\n", gravity);
- fprintf(fi," (background-tm ");
-
- for(int y = 0; y < height; ++y)
- {
- for(int i = 0; i < width; ++i)
- fprintf(fi," %d ", bg_tiles[y][i]);
- fprintf(fi,"\n");
- }
-
- fprintf( fi,")\n");
- fprintf(fi," (interactive-tm ");
-
- for(int y = 0; y < height; ++y)
- {
- for(int i = 0; i < width; ++i)
- fprintf(fi," %d ", ia_tiles[y][i]);
- fprintf(fi,"\n");
- }
-
- fprintf( fi,")\n");
- fprintf(fi," (foreground-tm ");
-
- for(int y = 0; y < height; ++y)
- {
- for(int i = 0; i < width; ++i)
- fprintf(fi," %d ", fg_tiles[y][i]);
- fprintf(fi,"\n");
- }
-
- fprintf( fi,")\n");
-
- fprintf( fi,"(reset-points\n");
+ 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");
for(std::vector<ResetPoint>::iterator i = reset_points.begin();
- i != reset_points.end(); ++i)
- fprintf( fi,"(point (x %d) (y %d))\n",i->x, i->y);
- fprintf( fi,")\n");
-
- fprintf( fi,"(objects\n");
-
- for(std::vector<BadGuyData>::iterator it = badguy_data.begin();
- it != badguy_data.end();
- ++it)
- fprintf( fi," (%s (x %d) (y %d) (stay-on-platform %s))\n",
- badguykind_to_string((*it).kind).c_str(),(*it).x,(*it).y,
- it->stay_on_platform ? "#t" : "#f");
-
- fprintf( fi,")\n");
-
- fprintf( fi,")\n");
+ i != reset_points.end(); ++i) {
+ writer.startList("point");
+ writer.writeInt("x", i->x);
+ writer.writeInt("y", i->y);
+ }
+ writer.endList("reset-points");
+
+ // write objects
+ writer.startList("objects");
+ // pick all objects that can be written into a levelfile
+ 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");
- fclose(fi);
+ writer.endList("supertux-level");
+ out.close();
}
-
/* Unload data for this level: */
-
void
Level::cleanup()
{
- for(int i=0; i < 15; ++i)
- {
- bg_tiles[i].clear();
- ia_tiles[i].clear();
- fg_tiles[i].clear();
- }
+ bg_tiles.clear();
+ ia_tiles.clear();
+ fg_tiles.clear();
reset_points.clear();
name = "";
author = "";
song_title = "";
bkgd_image = "";
-
- badguy_data.clear();
}
void
/* Change the size of a level */
void
-Level::change_width (int new_width)
+Level::resize(int new_width, int new_height)
{
- if(new_width < 21)
- new_width = 21;
+ // first: resize height
+ ia_tiles.resize(new_height * width, 0);
+ bg_tiles.resize(new_height * width, 0);
+ fg_tiles.resize(new_height * width, 0);
+ height = new_height;
- for(int y = 0; y < height; ++y)
- {
- ia_tiles[y].resize(new_width, 0);
- bg_tiles[y].resize(new_width, 0);
- fg_tiles[y].resize(new_width, 0);
+ // remap horizontal tiles for new width
+ int np = 0;
+ for(int y = 0; y < height; ++y) {
+ for(int x = 0; x < new_width && x < width; ++x) {
+ ia_tiles[np] = ia_tiles[y * width + x];
+ bg_tiles[np] = bg_tiles[y * width + x];
+ fg_tiles[np] = fg_tiles[y * width + x];
+ np++;
}
+ }
+ ia_tiles.resize(new_height * new_width);
+ bg_tiles.resize(new_height * new_width);
+ fg_tiles.resize(new_height * new_width);
+
width = new_width;
}
-void
-Level::change_height (int new_height)
-{
- if(new_height < 15)
- new_height = 15;
-
- bg_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
- ia_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
- fg_tiles.resize(height+1, std::vector<unsigned int>(width, 0));
-
- height = new_height;
-}
-
void
Level::change(float x, float y, int tm, unsigned int c)
{
switch(tm)
{
case TM_BG:
- bg_tiles[yy][xx] = c;
+ bg_tiles[yy * width + xx] = c;
break;
case TM_IA:
- ia_tiles[yy][xx] = c;
+ ia_tiles[yy * width + xx] = c;
break;
case TM_FG:
- fg_tiles[yy][xx] = c;
+ fg_tiles[yy * width + xx] = c;
break;
}
}
xx = ((int)x / 32);
if (yy >= 0 && yy < height && xx >= 0 && xx <= width)
- c = ia_tiles[yy][xx];
+ c = ia_tiles[yy * width + xx];
else
c = 0;
unsigned int
Level::get_tile_at(int x, int y) const
{
- if(x < 0 || x > width || y < 0 || y > height)
+ if(x < 0 || x >= width || y < 0 || y >= height)
return 0;
- return ia_tiles[y][x];
+ return ia_tiles[y * width + x];
}
/* EOF */
#include "gameobjs.h"
class Tile;
+class World;
/** This type holds meta-information about a level-subset.
It could be extended to handle manipulation of subsets. */
std::string song_title;
std::string bkgd_image;
std::string particle_system;
- std::vector<std::vector<unsigned int> > bg_tiles; /* Tiles in the background */
- std::vector<std::vector<unsigned int> > ia_tiles; /* Tiles which can interact in the game (solids for example)*/
- std::vector<std::vector<unsigned int> > fg_tiles; /* Tiles in the foreground */
+ std::vector<unsigned int> bg_tiles; /* Tiles in the background */
+ std::vector<unsigned int> ia_tiles; /* Tiles which can interact in the game (solids for example)*/
+ std::vector<unsigned int> fg_tiles; /* Tiles in the foreground */
// std::vector<unsigned int> bg_tiles[15]; /* Tiles in the background */
// std::vector<unsigned int> ia_tiles[15]; /* Tiles which can interact in the game (solids for example)*/
// std::vector<unsigned int> fg_tiles[15]; /* Tiles in the foreground */
bool back_scrolling;
float hor_autoscroll_speed;
- std::vector<BadGuyData> badguy_data;
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:
Level();
- Level(const std::string& subset, int level);
- Level(const std::string& filename);
+ Level(const std::string& subset, int level, World* world);
+ Level(const std::string& filename, World* world);
~Level();
/** Will the Level structure with default values */
void cleanup();
/** Load data for this level:
- Returns -1, if the loading of the level failed. */
- int load(const std::string& subset, int level);
+ Returns -1, if the loading of the level failed.
+ XXX the world parameter is a temporary hack
+ */
+ int load(const std::string& subset, int level, World* world);
/** Load data for this level:
- Returns -1, if the loading of the level failed. */
- int load(const std::string& filename);
+ Returns -1, if the loading of the level failed.
+ XXX the world parameter is a temporary hack
+ */
+ int load(const std::string& filename, World* world);
void load_gfx();
MusicRef get_level_music();
MusicRef get_level_music_fast();
- void save(const std::string& subset, int level);
+ // XXX the world parameter is a temporary hack
+ void save(const std::string& subset, int level, World* world);
/** Edit a piece of the map! */
void change(float x, float y, int tm, unsigned int c);
/** Resize the level to a new width/height */
- void change_width (int new_width);
- void change_height (int new_height);
+ void resize(int new_width, int new_height);
/* Draw background */
void draw_bg();
#include "tile.h"
#include "resources.h"
#include "music_manager.h"
+#include "display_manager.h"
/* definitions to aid development */
static std::string cur_tilegroup;
static std::string cur_objects;
static MouseCursor* mouse_select_object;
-static GameObject* selected_game_object;
+static MovingObject* selected_game_object;
static square selection;
static SelectionMode le_selection_mode;
select_objects_menu->arrange_left = true;
select_objects_menu->additem(MN_LABEL,"Objects",0,0);
select_objects_menu->additem(MN_HL,"",0,0);
+ // TODO fix this
+#if 0
select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
+ DisplayManager dummy;
for(int i = 0; i < NUM_BadGuyKinds; ++i)
{
- BadGuy bad_tmp(0,0,BadGuyKind(i),false);
+ BadGuy bad_tmp(dummy, 0,0,BadGuyKind(i),false);
objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
- objects_map["BadGuys"]->manipulate_button(i)->set_game_object(new BadGuy(objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,BadGuyKind(i),false));
+ objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new
+ BadGuy(dummy,
+ objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,
+ objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,
+ BadGuyKind(i), false));
}
+#endif
select_objects_menu->additem(MN_HL,"",0,0);
le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
- le_world->get_level()->change_width(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
- le_world->get_level()->change_height(atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
+ le_world->get_level()->resize(
+ atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input),
+ atoi(level_settings_menu->get_item_by_id(MNID_HEIGHT).input));
le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
if(confirm_dialog(str))
{
- le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
+ le_world->get_level()->save(le_level_subset->name.c_str(), le_level,
+ le_world);
}
}
else
mini_tile_height = 1;
+ Level* level = le_world->get_level();
for (int y = 0; y < le_world->get_level()->height; ++y)
for (int x = 0; x < le_world->get_level()->width; ++x)
{
- Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
+ Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
+ mini_tile_width , 4, level->bg_tiles[y * level->width + x]);
- Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
+ Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
+ mini_tile_width , 4, level->ia_tiles[y * level->width + x]);
- Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
+ Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4,
+ mini_tile_width , 4, level->fg_tiles[y + level->width + x]);
}
/* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
+ Level* level = le_world->get_level();
for (y = 0; y < VISIBLE_TILES_Y && y < (unsigned)le_world->get_level()->height; ++y)
for (x = 0; x < (unsigned)VISIBLE_TILES_X - 2; ++x)
{
else
a = 128;
- Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->bg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
+ Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
+ level->bg_tiles[ (y + (int)(pos_y / 32)) * level->width +
+ (x + (int)(pos_x / 32))],a);
if(active_tm == TM_IA)
a = 255;
else
a = 128;
- Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
+ Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
+ level->ia_tiles[ (y + (int)(pos_y / 32)) * level->width +
+ (x + (int)(pos_x / 32))],a);
+
if(active_tm == TM_FG)
a = 255;
else
a = 128;
- Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32), le_world->get_level()->fg_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)],a);
+ Tile::draw(32*x - fmodf(pos_x, 32), y*32 - fmodf(pos_y, 32),
+ level->fg_tiles[ (y + (int)(pos_y / 32)) * level->width +
+ (x + (int)(pos_x / 32))],a);
/* draw whats inside stuff when cursor is selecting those */
/* (draw them all the time - is this the right behaviour?) */
- Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y + (int)(pos_y / 32)][x + (int)(pos_x / 32)]);
+ Tile* edit_image = TileManager::instance()->get(
+ level->ia_tiles
+ [ (y + (int)(pos_y / 32)) * level->width + (x + (int)(pos_x / 32))]);
if(edit_image && !edit_image->editor_images.empty())
edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32 - ((int)pos_y % 32));
}
/* Draw the Bad guys: */
- for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
+ for (std::vector<_GameObject*>::iterator it = le_world->gameobjects.begin();
+ it != le_world->gameobjects.end(); ++it)
{
+ BadGuy* badguy = dynamic_cast<BadGuy*> (*it);
+ if(badguy == 0)
+ continue;
+
/* to support frames: img_bsod_left[(frame / 5) % 4] */
-
- scroll_x = pos_x;
- scroll_y = pos_y;
- (*it)->draw();
+ ViewPort viewport;
+ viewport.set_translation(Vector(pos_x, pos_y));
+ badguy->draw(viewport, 0);
}
-
/* Draw the player: */
/* for now, the position is fixed at (100, 240) */
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();
object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
object_properties_menu->additem(MN_HL,"",0,0);
- if(pobj->type() == "BadGuy")
+ BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
+ if(pobj != 0)
{
- BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
for(int i = 0; i < NUM_BadGuyKinds; ++i)
{
- string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
+ string_list_add_item(object_properties_menu->get_item_by_id(1).list,
+ badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
if(pbad->kind == i)
object_properties_menu->get_item_by_id(1).list->active_item = i;
}
switch (object_properties_menu->check())
{
case 3:
- if(pobj->type() == "BadGuy")
{
+ BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
+ if(pbad != 0) {
BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
- int i = 0;
- std::list<BadGuy*>::iterator it;
- for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
- if((*it) == pbad)
- break;
- le_world->get_level()->badguy_data[i].kind = pbad->kind;
- le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
- delete (*it);
- (*it) = new BadGuy(le_world->get_level()->badguy_data[i].x,le_world->get_level()->badguy_data[i].y,le_world->get_level()->badguy_data[i].kind,le_world->get_level()->badguy_data[i].stay_on_platform);
}
loop = false;
break;
+ }
default:
break;
}
le_testlevel();
le_save_level_bt->event(event);
if(le_save_level_bt->get_state() == BUTTON_CLICKED)
- le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
+ le_world->get_level()->save(le_level_subset->name.c_str(),le_level,
+ le_world);
le_exit_bt->event(event);
if(le_exit_bt->get_state() == BUTTON_CLICKED)
{
if(confirm_dialog(str))
{
new_lev.init_defaults();
- new_lev.save(le_level_subset->name.c_str(),le_level+1);
+ new_lev.save(le_level_subset->name.c_str(),le_level+1, le_world);
le_level_subset->levels = le_level;
le_goto_level(le_level);
}
{
if(pbutton->get_state() == BUTTON_CLICKED)
{
- le_current.Object(pbutton->get_game_object());
+#if 0 // TODO fixme!!
+ le_current.Object(pbutton->get_drawable());
+#endif
}
}
}
{
if(MouseCursor::current() == mouse_select_object)
{
- int i = 0;
bool object_got_hit = false;
base_type cursor_base;
if(le_current.IsTile())
cursor_base.width = 32;
cursor_base.height = 32;
- for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
- if(rectcollision(cursor_base,(*it)->base))
+ for(std::vector<_GameObject*>::iterator it =
+ le_world->gameobjects.begin();
+ it != le_world->gameobjects.end(); ++it) {
+ MovingObject* mobj = dynamic_cast<MovingObject*> (*it);
+ if(!mobj)
+ continue;
+
+ if(rectcollision(cursor_base, mobj->base))
{
- selected_game_object = (*it);
+ selected_game_object = mobj;
object_got_hit = true;
break;
}
+ }
if(!object_got_hit)
{
}
else
{
+#if 0 // FIXME TODO
if(le_current.IsObject())
{
le_level_changed = true;
le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
}
}
+#endif
}
le_mouse_clicked[LEFT] = false;
{
int xx,yy;
int x1, x2, y1, y2;
- unsigned int i = 0;
le_level_changed = true;
cursor_base.height = 32;
/* if there is a bad guy over there, remove it */
+ // XXX TODO
+#if 0
for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
if(rectcollision(cursor_base,(*it)->base))
{
le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
break;
}
+#endif
break;
case SQUARE:
y2 /= 32;
/* if there is a bad guy over there, remove it */
+ // TODO FIXME
+#if 0
for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
it != le_world->bad_guys.end(); /* will be at end of loop */)
{
++it;
}
}
+#endif
for(xx = x1; xx <= x2; xx++)
for(yy = y1; yy <= y2; yy++)
if(le_world->get_level()->time_left == 0)
le_world->get_level()->time_left = 250;
- le_world->get_level()->save("test", le_level);
+ le_world->get_level()->save("test", le_level, le_world);
GameSession session("test",le_level, ST_GL_TEST);
session.run();
bool
LispReader::read_int_vector (const char* name, std::vector<int>* vec)
{
+ vec->clear();
+ lisp_object_t* obj = search_for (name);
+ if (obj)
+ {
+ while(!lisp_nil_p(obj))
+ {
+ if (!lisp_integer_p(lisp_car(obj)))
+ st_abort("LispReader expected type integer at token: ", name);
+ vec->push_back(lisp_integer(lisp_car(obj)));
+ obj = lisp_cdr(obj);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool
+LispReader::read_int_vector (const char* name, std::vector<unsigned int>* vec)
+{
+ vec->clear();
lisp_object_t* obj = search_for (name);
if (obj)
{
return false;
}
-LispWriter::LispWriter (const char* name)
-{
- lisp_objs.push_back(lisp_make_symbol (name));
-}
-
-void
-LispWriter::append (lisp_object_t* obj)
-{
- lisp_objs.push_back(obj);
-}
-
-lisp_object_t*
-LispWriter::make_list3 (lisp_object_t* a, lisp_object_t* b, lisp_object_t* c)
-{
- return lisp_make_cons (a, lisp_make_cons(b, lisp_make_cons(c, lisp_nil())));
-}
-
-lisp_object_t*
-LispWriter::make_list2 (lisp_object_t* a, lisp_object_t* b)
-{
- return lisp_make_cons (a, lisp_make_cons(b, lisp_nil()));
-}
-
-void
-LispWriter::write_float (const char* name, float f)
-{
- append(make_list2 (lisp_make_symbol (name),
- lisp_make_real(f)));
-}
-
-void
-LispWriter::write_int (const char* name, int i)
-{
- append(make_list2 (lisp_make_symbol (name),
- lisp_make_integer(i)));
-}
-
-void
-LispWriter::write_string (const char* name, const char* str)
-{
- append(make_list2 (lisp_make_symbol (name),
- lisp_make_string(str)));
-}
-
-void
-LispWriter::write_symbol (const char* name, const char* symname)
-{
- append(make_list2 (lisp_make_symbol (name),
- lisp_make_symbol(symname)));
-}
-
-void
-LispWriter::write_lisp_obj(const char* name, lisp_object_t* lst)
-{
- append(make_list2 (lisp_make_symbol (name),
- lst));
-}
-
-void
-LispWriter::write_boolean (const char* name, bool b)
-{
- append(make_list2 (lisp_make_symbol (name),
- lisp_make_boolean(b)));
-}
-
-lisp_object_t*
-LispWriter::create_lisp ()
-{
- lisp_object_t* lisp_obj = lisp_nil();
-
- for(std::vector<lisp_object_t*>::reverse_iterator i = lisp_objs.rbegin ();
- i != lisp_objs.rend (); ++i)
- {
- lisp_obj = lisp_make_cons (*i, lisp_obj);
- }
- lisp_objs.clear();
-
- return lisp_obj;
-}
-
#if 0
void mygzungetc(char c, void* file)
{
LispReader (lisp_object_t* l);
bool read_int_vector (const char* name, std::vector<int>* vec);
+ bool read_int_vector (const char* name, std::vector<unsigned int>* vec);
bool read_char_vector (const char* name, std::vector<char>* vec);
bool read_string_vector (const char* name, std::vector<std::string>* vec);
bool read_string (const char* name, std::string* str);
bool read_lisp (const char* name, lisp_object_t** b);
};
-/** */
-class LispWriter
- {
- private:
- std::vector<lisp_object_t*> lisp_objs;
-
- void append (lisp_object_t* obj);
- lisp_object_t* make_list3 (lisp_object_t*, lisp_object_t*, lisp_object_t*);
- lisp_object_t* make_list2 (lisp_object_t*, lisp_object_t*);
- public:
- LispWriter (const char* name);
- void write_float (const char* name, float f);
- void write_int (const char* name, int i);
- void write_boolean (const char* name, bool b);
- void write_string (const char* name, const char* str);
- void write_symbol (const char* name, const char* symname);
- void write_lisp_obj(const char* name, lisp_object_t* lst);
-
- /** caller is responible to free the returned lisp_object_t */
- lisp_object_t* create_lisp ();
- };
-
#endif
Player(DisplayManager& display_manager);
virtual ~Player();
- void init();
int key_event(SDLKey key, int state);
void level_begin();
void handle_input();
void grow();
private:
+ void init();
+
void handle_horizontal_input();
void handle_vertical_input();
void remove_powerups();
void
TileMap::draw(ViewPort& viewport, int layer)
{
- std::vector<std::vector<unsigned int> >* tiles;
+ std::vector<unsigned int>* tiles;
switch(layer) {
case LAYER_BACKGROUNDTILES:
tiles = &level->bg_tiles; break;
int tsy = int(viewport.get_translation().y / 32); // tilestartindex y
int sx = - (int(viewport.get_translation().x) % 32);
int sy = - (int(viewport.get_translation().y) % 32);
- for(int x = sx, tx = tsx; x < screen->w && tx < int((*tiles)[0].size());
+ for(int x = sx, tx = tsx; x < screen->w && tx < level->width;
x += 32, ++tx) {
- for(int y = sy, ty = tsy; y < screen->h && ty < int(tiles->size());
+ for(int y = sy, ty = tsy; y < screen->h && ty < level->height;
y += 32, ++ty) {
- Tile::draw(x, y, (*tiles) [ty][tx]);
+ Tile::draw(x, y, (*tiles) [ty * level->width + tx]);
}
}
}
for (int i = 1; i <= subset.levels; ++i)
{
Level level;
- level.load(subset.name, i);
+ level.load(subset.name, i, 0);
contrib_subset_menu->additem(MN_ACTION, level.name, 0, 0, i);
}
contrib_subset_menu->additem(MN_HL,"",0,0);
// world calls child functions
current_ = this;
- level = new Level(filename);
+ level = new Level();
+ level->load(filename, this);
tux = new Player(displaymanager);
gameobjects.push_back(tux);
set_defaults();
get_level()->load_gfx();
- activate_bad_guys();
// add background
activate_particle_systems();
Background* bg = new Background(displaymanager);
// world calls child functions
current_ = this;
- level = new Level(subset, level_nr);
- tux->init();
+ level = new Level();
+ level->load(subset, level_nr, this);
+
+ tux = new Player(displaymanager);
+ gameobjects.push_back(tux);
set_defaults();
get_level()->load_gfx();
- activate_bad_guys();
activate_objects();
activate_particle_systems();
Background* bg = new Background(displaymanager);
void
World::apply_bonuses()
{
-#if 0
// Apply bonuses from former levels
switch (player_status.bonus)
{
case PlayerStatus::NO_BONUS:
break;
-
+
case PlayerStatus::FLOWER_BONUS:
- tux->got_power = tux.FIRE_POWER; // FIXME: add ice power to here
+ tux->got_power = Player::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->grow();
break;
}
-#endif
}
World::~World()
{
- for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end(); ++i)
- delete *i;
-
for (Trampolines::iterator i = trampolines.begin(); i != trampolines.end(); ++i)
delete *i;
displaymanager.remove_drawable(drawable);
delete *i;
}
+ bad_guys.clear();
delete level;
}
}
void
-World::activate_bad_guys()
+World::add_object(_GameObject* object)
{
- for (std::vector<BadGuyData>::iterator i = level->badguy_data.begin();
- i != level->badguy_data.end();
- ++i)
+ // XXX hack for now until new collision code is ready
+ BadGuy* badguy = dynamic_cast<BadGuy*> (object);
+ if(badguy)
+ bad_guys.push_back(badguy);
+
+ gameobjects.push_back(object);
+}
+
+void
+World::parse_objects(lisp_object_t* cur)
+{
+ while(!lisp_nil_p(cur)) {
+ lisp_object_t* data = lisp_car(cur);
+ std::string object_type = "";
+
+ LispReader reader(lisp_cdr(data));
+ reader.read_string("type", &object_type);
+
+ if(object_type == "badguy" || object_type == "")
{
- add_bad_guy(i->x, i->y, i->kind, i->stay_on_platform);
+ BadGuyKind kind = badguykind_from_string(
+ lisp_symbol(lisp_car(data)));
+ add_object(new BadGuy(displaymanager, kind, reader));
}
+ // TODO add parsing code for trampolines
+
+ cur = lisp_cdr(cur);
+ }
}
void
{
if (level->particle_system == "clouds")
{
- gameobjects.push_back(new CloudParticleSystem(displaymanager));
+ add_object(new CloudParticleSystem(displaymanager));
}
else if (level->particle_system == "snow")
{
- gameobjects.push_back(new SnowParticleSystem(displaymanager));
+ add_object(new SnowParticleSystem(displaymanager));
}
else if (level->particle_system != "")
{
displaymanager.get_viewport().set_translation(Vector(scroll_x, scroll_y));
displaymanager.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();
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);
/* Handle all possible collisions. */
collision_handler();
-
- // Cleanup marked badguys
- for (BadGuys::iterator i = bad_guys.begin(); i != bad_guys.end();
- /* ++i handled at end of the loop */) {
- if ((*i)->is_removable()) {
- delete *i;
- i = bad_guys.erase(i);
- } else {
- ++i;
- }
- }
-
+
+ /** cleanup marked objects */
for(std::vector<_GameObject*>::iterator i = gameobjects.begin();
i != gameobjects.end(); /* nothing */) {
if((*i)->is_valid() == false) {
Drawable* drawable = dynamic_cast<Drawable*> (*i);
if(drawable)
displaymanager.remove_drawable(drawable);
+ BadGuy* badguy = dynamic_cast<BadGuy*> (*i);
+ if(badguy) {
+ std::remove(bad_guys.begin(), bad_guys.end(), badguy);
+ }
delete *i;
i = gameobjects.erase(i);
{
player_status.score += s;
- gameobjects.push_back(new FloatingScore(displaymanager, pos, s));
+ add_object(new FloatingScore(displaymanager, pos, s));
}
void
World::add_bouncy_distro(const Vector& pos)
{
- gameobjects.push_back(new BouncyDistro(displaymanager, pos));
+ add_object(new BouncyDistro(displaymanager, pos));
}
void
World::add_broken_brick_piece(const Vector& pos, const Vector& movement,
Tile* tile)
{
- gameobjects.push_back(new BrokenBrick(displaymanager, tile, pos, movement));
+ add_object(new BrokenBrick(displaymanager, tile, pos, movement));
}
void
World::add_bouncy_brick(const Vector& pos)
{
- gameobjects.push_back(new BouncyBrick(displaymanager, pos));
+ add_object(new BouncyBrick(displaymanager, pos));
}
BadGuy*
-World::add_bad_guy(float x, float y, BadGuyKind kind, bool stay_on_platform)
+World::add_bad_guy(float x, float y, BadGuyKind kind)
{
- BadGuy* badguy = new BadGuy(x,y,kind, stay_on_platform);
- bad_guys.push_back(badguy);
+ BadGuy* badguy = new BadGuy(displaymanager, kind, x, y);
+ add_object(badguy);
return badguy;
}
World(const std::string& filename);
World(const std::string& subset, int level_nr);
- World() {};
+ //World() {};
~World();
Level* get_level() { return level; }
Player* get_tux() { return tux; }
+ void add_object(_GameObject* object);
+
void set_defaults();
void draw();
void play_music(int musictype);
int get_music_type();
-
/** Checks for all possible collisions. And calls the
collision_handlers, which the collision_objects provide for this
case (or not). */
void collision_handler();
+
+ void parse_objects(lisp_object_t* cur);
void activate_particle_systems();
- void activate_bad_guys();
void activate_objects();
void add_score(const Vector& pos, int s);
const Vector& movement, Tile* tile);
void add_bouncy_brick(const Vector& pos);
- BadGuy* add_bad_guy(float x, float y, BadGuyKind kind, bool stay_on_platform = false);
+ 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);