//---------------------------------------------------------------------------
-WorldMap::WorldMap(const std::string& filename)
- : tux(0), solids(0)
+WorldMap::WorldMap(const std::string& filename, const std::string& force_spawnpoint)
+ : tux(0), solids(0), force_spawnpoint(force_spawnpoint)
{
tile_manager.reset(new TileManager("images/worldmap.strf"));
worldmap_menu->add_entry(MNID_QUITWORLDMAP, _("Quit World"));
load(filename);
+
+ // create a new squirrel table for the worldmap
+ using namespace Scripting;
+
+ sq_collectgarbage(global_vm);
+ sq_newtable(global_vm);
+ sq_pushroottable(global_vm);
+ if(SQ_FAILED(sq_setdelegate(global_vm, -2)))
+ throw Scripting::SquirrelError(global_vm, "Couldn't set worldmap_table delegate");
+
+ sq_resetobject(&worldmap_table);
+ if(SQ_FAILED(sq_getstackobj(global_vm, -1, &worldmap_table)))
+ throw Scripting::SquirrelError(global_vm, "Couldn't get table from stack");
+
+ sq_addref(global_vm, &worldmap_table);
+ sq_pop(global_vm, 1);
}
WorldMap::~WorldMap()
HSQOBJECT& object = *i;
sq_release(global_vm, &object);
}
+ sq_release(global_vm, &worldmap_table);
+
+ sq_collectgarbage(global_vm);
if(current_ == this)
current_ = NULL;
for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ++i)
- delete *i;
+ i != game_objects.end(); ++i) {
+ GameObject* object = *i;
+ object->unref();
+ }
for(SpawnPoints::iterator i = spawn_points.begin();
i != spawn_points.end(); ++i) {
solids = tilemap;
}
+ object->ref();
game_objects.push_back(object);
}
void
+WorldMap::move_to_spawnpoint(const std::string& spawnpoint)
+{
+ for(SpawnPoints::iterator i = spawn_points.begin(); i != spawn_points.end(); ++i) {
+ SpawnPoint* sp = *i;
+ if(sp->name == spawnpoint) {
+ Vector p = sp->pos;
+ tux->set_tile_pos(p);
+ return;
+ }
+ }
+ log_warning << "Spawnpoint '" << spawnpoint << "' not found." << std::endl;
+ if (spawnpoint != "main") {
+ move_to_spawnpoint("main");
+ }
+}
+
+void
+WorldMap::change(const std::string& filename, const std::string& force_spawnpoint)
+{
+ main_loop->exit_screen();
+ main_loop->push_screen(new WorldMap(filename, force_spawnpoint));
+}
+
+void
WorldMap::load(const std::string& filename)
{
map_filename = filename;
add_object(new Background(*(iter.lisp())));
} else if(iter.item() == "music") {
iter.value()->get(music);
+ } else if(iter.item() == "init-script") {
+ iter.value()->get(init_script);
} else if(iter.item() == "worldmap-spawnpoint") {
SpawnPoint* sp = new SpawnPoint(iter.lisp());
spawn_points.push_back(sp);
} else if(iter.item() == "level") {
LevelTile* level = new LevelTile(levels_path, iter.lisp());
levels.push_back(level);
- game_objects.push_back(level);
+ add_object(level);
} else if(iter.item() == "special-tile") {
SpecialTile* special_tile = new SpecialTile(iter.lisp());
special_tiles.push_back(special_tile);
- game_objects.push_back(special_tile);
+ add_object(special_tile);
} else if(iter.item() == "sprite-change") {
SpriteChange* sprite_change = new SpriteChange(iter.lisp());
sprite_changes.push_back(sprite_change);
- game_objects.push_back(sprite_change);
+ add_object(sprite_change);
+ } else if(iter.item() == "teleporter") {
+ Teleporter* teleporter = new Teleporter(iter.lisp());
+ teleporters.push_back(teleporter);
+ add_object(teleporter);
} else if(iter.item() == "name") {
// skip
} else {
if(solids == 0)
throw std::runtime_error("No solid tilemap specified");
- // search for main spawnpoint
- for(SpawnPoints::iterator i = spawn_points.begin();
- i != spawn_points.end(); ++i) {
- SpawnPoint* sp = *i;
- if(sp->name == "main") {
- Vector p = sp->pos;
- tux->set_tile_pos(p);
- break;
- }
- }
+ move_to_spawnpoint("main");
} catch(std::exception& e) {
std::stringstream msg;
}
// update GameObjects
- for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ++i) {
- GameObject* object = *i;
+ for(size_t i = 0; i < game_objects.size(); ++i) {
+ GameObject* object = game_objects[i];
object->update(delta);
}
i != game_objects.end(); ) {
GameObject* object = *i;
if(!object->is_valid()) {
- delete object;
+ object->unref();
i = game_objects.erase(i);
} else {
++i;
enter_level = true;
if(main_controller->pressed(Controller::PAUSE_MENU))
on_escape_press();
-
+
+ // check for teleporters
+ Teleporter* teleporter = at_teleporter(tux->get_tile_pos());
+ if (teleporter && (teleporter->automatic || (enter_level && (!tux->is_moving())))) {
+ enter_level = false;
+ if (teleporter->worldmap != "") {
+ change(teleporter->worldmap, teleporter->spawnpoint);
+ } else {
+ // TODO: an animation, camera scrolling or a fading would be a nice touch
+ sound_manager->play("sounds/warp.wav");
+ tux->back_direction = D_NONE;
+ move_to_spawnpoint(teleporter->spawnpoint);
+ }
+ }
+
if (enter_level && !tux->is_moving())
{
- /* Check special tile action */
- SpecialTile* special_tile = at_special_tile();
- if(special_tile)
- {
- if (special_tile->teleport_dest != Vector(-1,-1))
- {
- // TODO: an animation, camera scrolling or a fading would be a nice touch
- sound_manager->play("sounds/warp.wav");
- tux->back_direction = D_NONE;
- tux->set_tile_pos(special_tile->teleport_dest);
- SDL_Delay(1000);
- }
- }
-
/* Check level action */
LevelTile* level = at_level();
if (!level) {
return NULL;
}
+Teleporter*
+WorldMap::at_teleporter(const Vector& pos)
+{
+ for(std::vector<Teleporter*>::iterator i = teleporters.begin(); i != teleporters.end(); ++i) {
+ Teleporter* teleporter = *i;
+ if(teleporter->pos == pos) return teleporter;
+ }
+
+ return NULL;
+}
+
void
WorldMap::draw(DrawingContext& context)
{
SCREEN_HEIGHT - white_text->get_height() - 30),
CENTER_ALLIGN, LAYER_FOREGROUND1);
+ // if level is solved, draw level picture behind stats
+ /*
+ if (level->solved) {
+ if (const Surface* picture = level->get_picture()) {
+ Vector pos = Vector(SCREEN_WIDTH - picture->get_width(), SCREEN_HEIGHT - picture->get_height());
+ context.push_transform();
+ context.set_alpha(0.5);
+ context.draw_surface(picture, pos, LAYER_FOREGROUND1-1);
+ context.pop_transform();
+ }
+ }
+ */
+
level->statistics.draw_worldmap_info(context);
break;
}
break;
}
}
+
+ // display teleporter messages
+ Teleporter* teleporter = at_teleporter(tux->get_tile_pos());
+ if (teleporter && (teleporter->message != "")) {
+ Vector pos = Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 30);
+ context.draw_text(white_text, teleporter->message, pos, CENTER_ALLIGN, LAYER_FOREGROUND1);
+ }
+
}
/* Display a passive message in the map, if needed */
current_ = this;
load_state();
+
+ // if force_spawnpoint was set, move Tux there, then clear force_spawnpoint
+ if (force_spawnpoint != "") {
+ move_to_spawnpoint(force_spawnpoint);
+ force_spawnpoint = "";
+ }
+
+ tux->setup();
+
+ // register worldmap_table as worldmap in scripting
+ using namespace Scripting;
+
+ sq_pushroottable(global_vm);
+ sq_pushstring(global_vm, "worldmap", -1);
+ sq_pushobject(global_vm, worldmap_table);
+ if(SQ_FAILED(sq_createslot(global_vm, -3)))
+ throw SquirrelError(global_vm, "Couldn't set worldmap in roottable");
+ sq_pop(global_vm, 1);
+
+ if(init_script != "") {
+ std::istringstream in(init_script);
+ run_script(in, "WorldMap::init");
+ }
+}
+
+void
+WorldMap::leave()
+{
+ // remove worldmap_table from roottable
+ using namespace Scripting;
+
+ sq_pushroottable(global_vm);
+ sq_pushstring(global_vm, "worldmap", -1);
+ if(SQ_FAILED(sq_deleteslot(global_vm, -2, SQFalse)))
+ throw SquirrelError(global_vm, "Couldn't unset worldmap in roottable");
+ sq_pop(global_vm, 1);
}
static void store_float(HSQUIRRELVM vm, const char* name, float val)
HSQUIRRELVM vm = object_to_vm(object);
+ // set worldmap_table as roottable for the thread
+ sq_pushobject(vm, worldmap_table);
+ sq_setroottable(vm);
+
compile_and_run(vm, in, sourcename);
return vm;