Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving converted objects from tiles with tilemap #3019

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/object/light.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class Light : public GameObject
virtual void update(float dt_sec) override;
virtual void draw(DrawingContext& context) override;

inline void move(const Vector& dist) { position += dist; }

protected:
Vector position;
Color color;
Expand Down
116 changes: 109 additions & 7 deletions src/object/tilemap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
#include <simplesquirrel/vm.hpp>

#include "editor/editor.hpp"
#include "object/pulsing_light.hpp"
#include "supertux/autotile.hpp"
#include "supertux/debug.hpp"
#include "supertux/game_object_factory.hpp"
#include "supertux/gameconfig.hpp"
#include "supertux/globals.hpp"
#include "supertux/moving_object.hpp"
#include "supertux/resources.hpp"
#include "supertux/sector.hpp"
#include "supertux/tile.hpp"
Expand Down Expand Up @@ -54,6 +57,8 @@ TileMap::TileMap(const TileSet *new_tileset) :
m_z_pos(0),
m_offset(Vector(0,0)),
m_movement(0, 0),
m_converted_objects(),
m_converted_lights(),
m_objects_hit_bottom(),
m_ground_movement_manager(nullptr),
m_flip(NO_FLIP),
Expand Down Expand Up @@ -88,6 +93,8 @@ TileMap::TileMap(const TileSet *tileset_, const ReaderMapping& reader) :
m_z_pos(0),
m_offset(Vector(0, 0)),
m_movement(Vector(0, 0)),
m_converted_objects(),
m_converted_lights(),
m_objects_hit_bottom(),
m_ground_movement_manager(nullptr),
m_flip(NO_FLIP),
Expand Down Expand Up @@ -385,20 +392,44 @@ TileMap::update(float dt_sec)
}

// if we have a path to follow, follow it
if (get_walker()) {
if (get_walker())
{
m_movement = Vector(0, 0);
get_walker()->update(dt_sec);
Vector v = get_walker()->get_pos(get_size() * 32, m_path_handle);
if (get_path() && get_path()->is_valid()) {
if (get_path() && get_path()->is_valid())
{
m_movement = v - get_offset();
set_offset(v);
if (m_ground_movement_manager != nullptr) {
for (CollisionObject* other_object : m_objects_hit_bottom) {
m_ground_movement_manager->register_movement(*this, *other_object, m_movement);
other_object->propagate_movement(m_movement);

if (m_movement != Vector(0, 0))
{
if (m_ground_movement_manager != nullptr)
{
for (CollisionObject* other_object : m_objects_hit_bottom)
{
m_ground_movement_manager->register_movement(*this, *other_object, m_movement);
other_object->propagate_movement(m_movement);
}
}

// Move all objects (including lights), converted from tiles in this tilemap
for (const UID& uid : m_converted_objects)
{
MovingObject* obj = get_parent()->get_object_by_uid<MovingObject>(uid);
if (obj)
obj->move(m_movement);
}
for (const UID& uid : m_converted_lights)
{
Light* obj = get_parent()->get_object_by_uid<Light>(uid);
if (obj)
obj->move(m_movement);
}
}
} else {
}
else
{
set_offset(m_path_handle.get_pos(get_size() * 32, Vector(0, 0)));
}
}
Expand Down Expand Up @@ -987,6 +1018,77 @@ TileMap::set_tileset(const TileSet* new_tileset)
m_tileset = new_tileset;
}

void
TileMap::convert_tiles_to_objects()
{
// Since object setup is not yet complete, we have to manually add the offset.
// See https://github.com/SuperTux/supertux/issues/1378 for details.
const Path* path = get_path();
const Vector offset = path ? path->get_base() : Vector(0.f, 0.f);

for (int x = 0; x < m_width; ++x)
{
for (int y = 0; y < m_height; ++y)
{
const Tile& tile = get_tile(x, y);

if (!tile.get_object_name().empty())
{
// If a tile is associated with an object, insert that
// object and remove the tile.
if (is_solid() || tile.get_object_name() == "decal")
{
const Vector pos = get_tile_position(x, y) + offset;
try
{
GameObject& obj = get_parent()->add_object(GameObjectFactory::instance().create(tile.get_object_name(), pos, Direction::AUTO, tile.get_object_data()));
if (dynamic_cast<MovingObject*>(&obj))
m_converted_objects.push_back(obj.get_uid());

m_tiles[y*m_width + x] = 0;
}
catch (const std::exception& err)
{
log_warning << "Error converting tile to object: " << err.what() << std::endl;
}
}
}
else
{
// Add lights for fire tiles
const uint32_t attributes = tile.get_attributes();
if (attributes & Tile::FIRE)
{
const Vector pos = get_tile_position(x, y) + offset;
const Vector center = pos + Vector(16.f, 16.f);

if (attributes & Tile::HURTS)
{
// Lava or lavaflow
// Space lights a bit
if ((get_tile(x - 1, y).get_attributes() != attributes || x % 3 == 0) &&
(get_tile(x, y - 1).get_attributes() != attributes || y % 3 == 0))
{
float pseudo_rnd = static_cast<float>(static_cast<int>(pos.x) % 10) / 10;
GameObject& obj = get_parent()->add<PulsingLight>(center, 1.0f + pseudo_rnd, 0.8f, 1.0f,
(Color(1.0f, 0.3f, 0.0f, 1.0f) * m_current_tint).validate());
m_converted_lights.push_back(obj.get_uid());
}
}
else
{
// Torch
const float pseudo_rnd = static_cast<float>(static_cast<int>(pos.x) % 10) / 10;
GameObject& obj = get_parent()->add<PulsingLight>(center, 1.0f + pseudo_rnd, 0.9f, 1.0f,
(Color(1.0f, 1.0f, 0.6f, 1.0f) * m_current_tint).validate());
m_converted_lights.push_back(obj.get_uid());
}
}
}
}
}
}


void
TileMap::register_class(ssq::VM& vm)
Expand Down
9 changes: 9 additions & 0 deletions src/object/tilemap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@ class TileMap final : public GameObject,

const std::vector<uint32_t>& get_tiles() const { return m_tiles; }

/** Convert tiles into their corresponding GameObjects (e.g.
bonusblocks, add light to lava tiles). */
void convert_tiles_to_objects();

private:
void update_effective_solid(bool update_manager = true);
void float_channel(float target, float &current, float remaining_time, float dt_sec);
Expand Down Expand Up @@ -321,6 +325,11 @@ class TileMap final : public GameObject,
Vector m_offset;
Vector m_movement; /**< The movement that happened last frame */

/** UIDs of MovingObjects and Lights, which have been created from tiles in this tilemap.
Will be moved together with this tilemap. */
std::vector<UID> m_converted_objects;
std::vector<UID> m_converted_lights;

/** Objects that were touching the top of a solid tile at the last frame */
std::unordered_set<CollisionObject*> m_objects_hit_bottom;

Expand Down
71 changes: 4 additions & 67 deletions src/supertux/sector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
#include "object/music_object.hpp"
#include "object/player.hpp"
#include "object/portable.hpp"
#include "object/pulsing_light.hpp"
#include "object/smoke_cloud.hpp"
#include "object/spawnpoint.hpp"
#include "object/text_array_object.hpp"
Expand All @@ -49,7 +48,6 @@
#include "supertux/colorscheme.hpp"
#include "supertux/constants.hpp"
#include "supertux/debug.hpp"
#include "supertux/game_object_factory.hpp"
#include "supertux/level.hpp"
#include "supertux/player_status_hud.hpp"
#include "supertux/resources.hpp"
Expand Down Expand Up @@ -102,8 +100,10 @@ Sector::finish_construction(bool editable)
// but I don't know if it's going to introduce other bugs.. ~ Semphris
try_process_resolve_requests();

if (!editable) {
convert_tiles2gameobject();
if (!editable)
{
for (auto& tm : get_objects_by_type<TileMap>())
tm.convert_tiles_to_objects();

if (!m_level.is_worldmap())
{
Expand Down Expand Up @@ -819,69 +819,6 @@ Sector::save(Writer &writer)
writer.end_list("sector");
}

void
Sector::convert_tiles2gameobject()
{
// add lights for special tiles
for (auto& tm : get_objects_by_type<TileMap>())
{
// Since object setup is not yet complete, I have to manually add the offset
// See https://github.com/SuperTux/supertux/issues/1378 for details
Vector tm_offset = tm.get_path() ? tm.get_path()->get_base() : Vector(0, 0);

for (int x=0; x < tm.get_width(); ++x)
{
for (int y=0; y < tm.get_height(); ++y)
{
const Tile& tile = tm.get_tile(x, y);

if (!tile.get_object_name().empty())
{
// If a tile is associated with an object, insert that
// object and remove the tile
if (tile.get_object_name() == "decal" ||
tm.is_solid())
{
Vector pos = tm.get_tile_position(x, y) + tm_offset;
try {
auto object = GameObjectFactory::instance().create(tile.get_object_name(), pos, Direction::AUTO, tile.get_object_data());
add_object(std::move(object));
tm.change(x, y, 0);
} catch(std::exception& e) {
log_warning << e.what() << "" << std::endl;
}
}
}
else
{
// add lights for fire tiles
uint32_t attributes = tile.get_attributes();
Vector pos = tm.get_tile_position(x, y) + tm_offset;
Vector center = pos + Vector(16, 16);

if (attributes & Tile::FIRE) {
if (attributes & Tile::HURTS) {
// lava or lavaflow
// space lights a bit
if ((tm.get_tile(x-1, y).get_attributes() != attributes || x%3 == 0)
&& (tm.get_tile(x, y-1).get_attributes() != attributes || y%3 == 0)) {
float pseudo_rnd = static_cast<float>(static_cast<int>(pos.x) % 10) / 10;
add<PulsingLight>(center, 1.0f + pseudo_rnd, 0.8f, 1.0f,
(Color(1.0f, 0.3f, 0.0f, 1.0f) * tm.get_current_tint()).validate());
}
} else {
// torch
float pseudo_rnd = static_cast<float>(static_cast<int>(pos.x) % 10) / 10;
add<PulsingLight>(center, 1.0f + pseudo_rnd, 0.9f, 1.0f,
(Color(1.0f, 1.0f, 0.6f, 1.0f) * tm.get_current_tint()).validate());
}
}
}
}
}
}
}

Camera&
Sector::get_camera() const
{
Expand Down
4 changes: 0 additions & 4 deletions src/supertux/sector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,6 @@ class Sector final : public Base::Sector

int calculate_foremost_layer(bool including_transparent = true) const;

/** Convert tiles into their corresponding GameObjects (e.g.
bonusblocks, add light to lava tiles) */
void convert_tiles2gameobject();

SpawnPointMarker* get_spawn_point(const std::string& spawnpoint);

private:
Expand Down
Loading