#include <stdexcept>
#include <float.h>
#include <math.h>
+#include <limits>
+#include <physfs.h>
#include "sector.hpp"
#include "object/player.hpp"
#include "object/coin.hpp"
#include "object/block.hpp"
#include "object/invisible_block.hpp"
+#include "object/light.hpp"
+#include "object/pulsing_light.hpp"
#include "object/bullet.hpp"
#include "object/text_object.hpp"
#include "object/portable.hpp"
Sector::Sector(Level* parent)
: level(parent), currentmusic(LEVEL_MUSIC),
- ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ), gravity(10), player(0), camera(0)
+ ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ), gravity(10.0), player(0), camera(0)
{
add_object(new Player(player_status, "Tux"));
add_object(new DisplayEffect("Effect"));
} else if(token == "ambient-light") {
std::vector<float> vColor;
sector.get_vector( "ambient-light", vColor );
- ambient_light = Color( vColor );
+ if(vColor.size() < 3) {
+ log_warning << "(ambient-light) requires a color as argument" << std::endl;
+ } else {
+ ambient_light = Color( vColor );
+ }
} else {
GameObject* object = parse_object(token, *(iter.lisp()));
if(object) {
reader.get("gravity", gravity);
std::string backgroundimage;
- reader.get("background", backgroundimage);
+ if (reader.get("background", backgroundimage) && (backgroundimage != "")) {
+ if (backgroundimage == "arctis.png") backgroundimage = "arctis.jpg";
+ if (backgroundimage == "arctis2.jpg") backgroundimage = "arctis.jpg";
+ if (backgroundimage == "ocean.png") backgroundimage = "ocean.jpg";
+ backgroundimage = "images/background/" + backgroundimage;
+ if (!PHYSFS_exists(backgroundimage.c_str())) {
+ log_warning << "Background image \"" << backgroundimage << "\" not found. Ignoring." << std::endl;
+ backgroundimage = "";
+ }
+ }
+
float bgspeed = .5;
reader.get("bkgd_speed", bgspeed);
bgspeed /= 100;
if(backgroundimage != "") {
Background* background = new Background();
- background->set_image(
- std::string("images/background/") + backgroundimage, bgspeed);
+ background->set_image(backgroundimage, bgspeed);
add_object(background);
} else {
Gradient* gradient = new Gradient();
spawnpoints.push_back(spawn);
music = "chipdisko.ogg";
+ // skip reading music filename. It's all .ogg now, anyway
+ /*
reader.get("music", music);
+ */
music = "music/" + music;
int width = 30, height = 15;
|| reader.get_vector("tilemap", tiles)) {
TileMap* tilemap = new TileMap();
tilemap->set(width, height, tiles, LAYER_TILES, true);
+
+ // replace tile id 112 (old invisible tile) with 1311 (new invisible tile)
+ for(size_t x=0; x < tilemap->get_width(); ++x) {
+ for(size_t y=0; y < tilemap->get_height(); ++y) {
+ const Tile* tile = tilemap->get_tile(x, y);
+ if(tile->getID() == 112) tilemap->change(x, y, 1311);
+ }
+ }
+
+ if (height < 19) tilemap->resize(width, 19);
add_object(tilemap);
}
if(reader.get_vector("background-tm", tiles)) {
TileMap* tilemap = new TileMap();
tilemap->set(width, height, tiles, LAYER_BACKGROUNDTILES, false);
+ if (height < 19) tilemap->resize(width, 19);
add_object(tilemap);
}
if(reader.get_vector("foreground-tm", tiles)) {
TileMap* tilemap = new TileMap();
tilemap->set(width, height, tiles, LAYER_FOREGROUNDTILES, false);
+
+ // fill additional space in foreground with tiles of ID 2035 (lightmap/black)
+ if (height < 19) tilemap->resize(width, 19, 2035);
+
add_object(tilemap);
}
}
}
}
+
+ // add lights for special tiles
+ for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end(); i++) {
+ TileMap* tm = dynamic_cast<TileMap*>(*i);
+ if (!tm) continue;
+ for(size_t x=0; x < tm->get_width(); ++x) {
+ for(size_t y=0; y < tm->get_height(); ++y) {
+ const Tile* tile = tm->get_tile(x, y);
+ Vector pos(tm->get_x_offset() + x*32, tm->get_y_offset() + y*32);
+ Vector center(pos.x + 16, pos.y + 16);
+
+ // torch
+ if (tile->getID() == 1517) {
+ float pseudo_rnd = (float)((int)pos.x % 10) / 10;
+ add_object(new PulsingLight(center, 1.0 + pseudo_rnd, 0.9, 1.0, Color(1.0, 1.0, 0.6, 1.0)));
+ }
+ // lava or lavaflow
+ if ((tile->getID() == 173) || (tile->getID() == 1700) || (tile->getID() == 1705) || (tile->getID() == 1706)) {
+ // space lights a bit
+ if (((tm->get_tile(x-1, y)->getID() != tm->get_tile(x,y)->getID())
+ && (tm->get_tile(x, y-1)->getID() != tm->get_tile(x,y)->getID()))
+ || ((x % 3 == 0) && (y % 3 == 0))) {
+ float pseudo_rnd = (float)((int)pos.x % 10) / 10;
+ add_object(new PulsingLight(center, 1.0 + pseudo_rnd, 0.8, 1.0, Color(1.0, 0.3, 0.0, 1.0)));
+ }
+ }
+
+ }
+ }
+ }
+
+
}
void
try_expose(object);
}
}
+ try_expose_me();
+
+ // spawn smalltux below spawnpoint
+ if (!player->is_big()) {
+ player->move(player_pos + Vector(0,32));
+ } else {
+ player->move(player_pos);
+ }
- player->move(player_pos);
+ // spawning tux in the ground would kill him
+ if(!is_free_of_tiles(player->get_bbox())) {
+ log_warning << "Tried spawning Tux in solid matter. Compensating." << std::endl;
+ Vector npos = player->get_bbox().p1;
+ npos.y-=32;
+ player->move(npos);
+ }
+
camera->reset(player->get_pos());
update_game_objects();
try_unexpose(object);
}
+ try_unexpose_me();
_current = NULL;
}
this->player = player;
}
+ UsesPhysic *physic_object = dynamic_cast<UsesPhysic *>(object);
+ if(physic_object)
+ {
+ physic_object->physic.set_gravity(gravity);
+ }
+
+
if(_current == this) {
try_expose(object);
}
}
void
+Sector::try_expose_me()
+{
+ HSQUIRRELVM vm = Scripting::global_vm;
+ sq_pushobject(vm, sector_table);
+ Scripting::SSector* interface = static_cast<Scripting::SSector*> (this);
+ expose_object(vm, -1, interface, "settings", false);
+ sq_pop(vm, 1);
+}
+
+void
Sector::before_object_remove(GameObject* object)
{
Portable* portable = dynamic_cast<Portable*> (object);
}
void
+Sector::try_unexpose_me()
+{
+ HSQUIRRELVM vm = Scripting::global_vm;
+ SQInteger oldtop = sq_gettop(vm);
+ sq_pushobject(vm, sector_table);
+ try {
+ Scripting::unexpose_object(vm, -1, "settings");
+ } catch(std::exception& e) {
+ log_warning << "Couldn't unregister object: " << e.what() << std::endl;
+ }
+ sq_settop(vm, oldtop);
+}
+void
Sector::draw(DrawingContext& context)
{
context.set_ambient_color( ambient_light );
Sector::collision_static_constrains(MovingObject& object)
{
using namespace collision;
+ float infinity = (std::numeric_limits<float>::has_infinity ? std::numeric_limits<float>::infinity() : std::numeric_limits<float>::max());
Constraints constraints;
Vector movement = object.get_movement();
break;
// apply calculated horizontal constraints
- if(constraints.bottom < INFINITY) {
+ if(constraints.bottom < infinity) {
float height = constraints.bottom - constraints.top;
if(height < oheight) {
// we're crushed, but ignore this for now, we'll get this again
}
dest.p2.y = constraints.bottom - DELTA;
dest.p1.y = dest.p2.y - oheight;
- } else if(constraints.top > -INFINITY) {
+ } else if(constraints.top > -infinity) {
dest.p1.y = constraints.top + DELTA;
dest.p2.y = dest.p1.y + oheight;
}
break;
// apply calculated vertical constraints
- if(constraints.right < INFINITY) {
+ if(constraints.right < infinity) {
float width = constraints.right - constraints.left;
if(width + SHIFT_DELTA < owidth) {
printf("Object %p crushed horizontally... L:%f R:%f\n", &object,
dest.p2.x = constraints.right - DELTA;
dest.p1.x = dest.p2.x - owidth;
}
- } else if(constraints.left > -INFINITY) {
+ } else if(constraints.left > -infinity) {
dest.p1.x = constraints.left + DELTA;
dest.p2.x = dest.p1.x + owidth;
}
// an extra pass to make sure we're not crushed horizontally
constraints = Constraints();
collision_static(&constraints, movement, dest, object);
- if(constraints.bottom < INFINITY) {
+ if(constraints.bottom < infinity) {
float height = constraints.bottom - constraints.top;
if(height + SHIFT_DELTA < oheight) {
printf("Object %p crushed vertically...\n", &object);
}
bool
-Sector::is_free_space(const Rect& rect) const
+Sector::is_free_of_tiles(const Rect& rect) const
{
using namespace collision;
}
}
+ return true;
+}
+
+bool
+Sector::is_free_of_statics(const Rect& rect, const MovingObject* ignore_object) const
+{
+ using namespace collision;
+
+ if (!is_free_of_tiles(rect)) return false;
+
for(MovingObjects::const_iterator i = moving_objects.begin();
i != moving_objects.end(); ++i) {
const MovingObject* moving_object = *i;
- if(moving_object->get_group() != COLGROUP_STATIC
- || !moving_object->is_valid())
- continue;
+ if (moving_object == ignore_object) continue;
+ if (!moving_object->is_valid()) continue;
+ if (moving_object->get_group() == COLGROUP_STATIC) {
+ if(intersects(rect, moving_object->get_bbox())) return false;
+ }
+ }
- if(intersects(rect, moving_object->get_bbox()))
- return false;
+ return true;
+}
+
+bool
+Sector::is_free_of_movingstatics(const Rect& rect, const MovingObject* ignore_object) const
+{
+ using namespace collision;
+
+ if (!is_free_of_tiles(rect)) return false;
+
+ for(MovingObjects::const_iterator i = moving_objects.begin();
+ i != moving_objects.end(); ++i) {
+ const MovingObject* moving_object = *i;
+ if (moving_object == ignore_object) continue;
+ if (!moving_object->is_valid()) continue;
+ if ((moving_object->get_group() == COLGROUP_MOVING)
+ || (moving_object->get_group() == COLGROUP_MOVING_STATIC)
+ || (moving_object->get_group() == COLGROUP_STATIC)) {
+ if(intersects(rect, moving_object->get_bbox())) return false;
+ }
}
return true;
// TODO remove this function and move these checks elsewhere...
Bullet* new_bullet = 0;
- if((int)bullets.size() >= player_status->max_fire_bullets)
+ if((player_status->bonus == FIRE_BONUS &&
+ (int)bullets.size() >= player_status->max_fire_bullets) ||
+ (player_status->bonus == ICE_BONUS &&
+ (int)bullets.size() >= player_status->max_ice_bullets))
return false;
- new_bullet = new Bullet(pos, xm, dir);
+ new_bullet = new Bullet(pos, xm, dir, player_status->bonus);
add_object(new_bullet);
sound_manager->play("sounds/shoot.wav");
solids->change_all(old_tile_id, new_tile_id);
}
}
+
+
+void
+Sector::set_ambient_light(float red, float green, float blue)
+{
+ ambient_light.red = red;
+ ambient_light.green = green;
+ ambient_light.blue = blue;
+}
+
+float
+Sector::get_ambient_red()
+{
+ return ambient_light.red;
+}
+
+float
+Sector::get_ambient_green()
+{
+ return ambient_light.green;
+}
+
+float
+Sector::get_ambient_blue()
+{
+ return ambient_light.blue;
+}