diff --git a/data/AUTHORS b/data/AUTHORS index f7b1bdca2be..d5344db9716 100644 --- a/data/AUTHORS +++ b/data/AUTHORS @@ -89,6 +89,9 @@ These are just more code. * bigjump.wav - self-made by wansti * brick.wav - replaced with a self-made sound submitted by Yaniel, GPLv2+CC-by-sa * coin.wav - Replaced by a self-made, almost identical sound by wansti +* crystallo-pop.ogg - remixed by weluvgoatz, originally created by fluerescence, licensed under CC0, from https://freesound.org/people/fleurescence/sounds/573153/ +* crystallo-shardhit.ogg - remixed by weluvgoatz, originally created by cyoung510, licensed under CC0, from https://freesound.org/people/cyoung510/sounds/521242/ +* crystallo-shatter.ogg - remixed by weluvgoatz, originally created by C_Rogers, licensed under CC0, from https://freesound.org/people/C_Rogers/sounds/203377/ * dartfire.wav - self-made by sommer * darthit.wav - self-made by sommer * door.wav - self-made by gwater (Jun 30 2006 13:42:40 ok it's my squeaky step, but it kind of sounds like a door.) diff --git a/data/images/creatures/crystallo/crystallo-fall-0.png b/data/images/creatures/crystallo/crystallo-fall-0.png new file mode 100644 index 00000000000..8b128cb71a0 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-0.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-1.png b/data/images/creatures/crystallo/crystallo-fall-1.png new file mode 100644 index 00000000000..0621b6a2d31 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-1.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-10.png b/data/images/creatures/crystallo/crystallo-fall-10.png new file mode 100644 index 00000000000..9d43eb9a340 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-10.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-2.png b/data/images/creatures/crystallo/crystallo-fall-2.png new file mode 100644 index 00000000000..26f5ad2d5d6 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-2.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-3.png b/data/images/creatures/crystallo/crystallo-fall-3.png new file mode 100644 index 00000000000..a9bc5dd9b7f Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-3.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-4.png b/data/images/creatures/crystallo/crystallo-fall-4.png new file mode 100644 index 00000000000..14e7816f845 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-4.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-5.png b/data/images/creatures/crystallo/crystallo-fall-5.png new file mode 100644 index 00000000000..afd2e4eff34 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-5.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-6.png b/data/images/creatures/crystallo/crystallo-fall-6.png new file mode 100644 index 00000000000..94a98e7ebce Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-6.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-7.png b/data/images/creatures/crystallo/crystallo-fall-7.png new file mode 100644 index 00000000000..9eff7ea9ac3 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-7.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-8.png b/data/images/creatures/crystallo/crystallo-fall-8.png new file mode 100644 index 00000000000..40191a17b91 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-8.png differ diff --git a/data/images/creatures/crystallo/crystallo-fall-9.png b/data/images/creatures/crystallo/crystallo-fall-9.png new file mode 100644 index 00000000000..ad5746870e2 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-fall-9.png differ diff --git a/data/images/creatures/crystallo/crystallo-jump-0.png b/data/images/creatures/crystallo/crystallo-jump-0.png new file mode 100644 index 00000000000..9dc32d4420f Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-jump-0.png differ diff --git a/data/images/creatures/crystallo/crystallo-jump-1.png b/data/images/creatures/crystallo/crystallo-jump-1.png new file mode 100644 index 00000000000..04367eeafb4 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-jump-1.png differ diff --git a/data/images/creatures/crystallo/crystallo-jump-2.png b/data/images/creatures/crystallo/crystallo-jump-2.png new file mode 100644 index 00000000000..dcc2b8fb7a8 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-jump-2.png differ diff --git a/data/images/creatures/crystallo/crystallo-jump-3.png b/data/images/creatures/crystallo/crystallo-jump-3.png new file mode 100644 index 00000000000..8fcf69c05c6 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-jump-3.png differ diff --git a/data/images/creatures/crystallo/crystallo-jump-4.png b/data/images/creatures/crystallo/crystallo-jump-4.png new file mode 100644 index 00000000000..5c6ba323843 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-jump-4.png differ diff --git a/data/images/creatures/crystallo/crystallo-jump-5.png b/data/images/creatures/crystallo/crystallo-jump-5.png new file mode 100644 index 00000000000..c159eb6a1c2 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-jump-5.png differ diff --git a/data/images/creatures/crystallo/crystallo-jump-6.png b/data/images/creatures/crystallo/crystallo-jump-6.png new file mode 100644 index 00000000000..c979d6eb642 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-jump-6.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-0.png b/data/images/creatures/crystallo/crystallo-left-0.png index 01911fe1dde..c97d3d5acf8 100644 Binary files a/data/images/creatures/crystallo/crystallo-left-0.png and b/data/images/creatures/crystallo/crystallo-left-0.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-1.png b/data/images/creatures/crystallo/crystallo-left-1.png index d08a8de80b4..126ea8d6014 100644 Binary files a/data/images/creatures/crystallo/crystallo-left-1.png and b/data/images/creatures/crystallo/crystallo-left-1.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-2.png b/data/images/creatures/crystallo/crystallo-left-2.png index 82a66d6c79f..9042a02a1bc 100644 Binary files a/data/images/creatures/crystallo/crystallo-left-2.png and b/data/images/creatures/crystallo/crystallo-left-2.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-3.png b/data/images/creatures/crystallo/crystallo-left-3.png new file mode 100644 index 00000000000..30e25699553 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-left-3.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-4.png b/data/images/creatures/crystallo/crystallo-left-4.png new file mode 100644 index 00000000000..41a85b9b9fb Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-left-4.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-5.png b/data/images/creatures/crystallo/crystallo-left-5.png new file mode 100644 index 00000000000..599c4841954 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-left-5.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-6.png b/data/images/creatures/crystallo/crystallo-left-6.png new file mode 100644 index 00000000000..e1b445338a0 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-left-6.png differ diff --git a/data/images/creatures/crystallo/crystallo-left-7.png b/data/images/creatures/crystallo/crystallo-left-7.png new file mode 100644 index 00000000000..77cd17cab71 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-left-7.png differ diff --git a/data/images/creatures/crystallo/crystallo-overlay.png b/data/images/creatures/crystallo/crystallo-overlay.png new file mode 100644 index 00000000000..561d92fd06a Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-overlay.png differ diff --git a/data/images/creatures/crystallo/crystallo-overlay.sprite b/data/images/creatures/crystallo/crystallo-overlay.sprite new file mode 100644 index 00000000000..743b397cbda --- /dev/null +++ b/data/images/creatures/crystallo/crystallo-overlay.sprite @@ -0,0 +1,6 @@ +(supertux-sprite + (action + (name "default") + (hitbox 11 16 32 20) + (images "crystallo-overlay.png")) +) diff --git a/data/images/creatures/crystallo/crystallo-preparing-0.png b/data/images/creatures/crystallo/crystallo-preparing-0.png new file mode 100644 index 00000000000..af3741deb27 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-preparing-0.png differ diff --git a/data/images/creatures/crystallo/crystallo-preparing-1.png b/data/images/creatures/crystallo/crystallo-preparing-1.png new file mode 100644 index 00000000000..bb0aa5e6ed4 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-preparing-1.png differ diff --git a/data/images/creatures/crystallo/crystallo-sleeping.png b/data/images/creatures/crystallo/crystallo-sleeping.png new file mode 100644 index 00000000000..606a19076a3 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-sleeping.png differ diff --git a/data/images/creatures/crystallo/crystallo-waking-0.png b/data/images/creatures/crystallo/crystallo-waking-0.png new file mode 100644 index 00000000000..04eddb5d590 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-waking-0.png differ diff --git a/data/images/creatures/crystallo/crystallo-waking-1.png b/data/images/creatures/crystallo/crystallo-waking-1.png new file mode 100644 index 00000000000..5693eca8174 Binary files /dev/null and b/data/images/creatures/crystallo/crystallo-waking-1.png differ diff --git a/data/images/creatures/crystallo/crystallo.sprite b/data/images/creatures/crystallo/crystallo.sprite index 1470e25f269..251f8328929 100644 --- a/data/images/creatures/crystallo/crystallo.sprite +++ b/data/images/creatures/crystallo/crystallo.sprite @@ -1,28 +1,45 @@ (supertux-sprite (action (name "left") - (hitbox 0 7 35 20) + (fps 14) + (hitbox 8 9 32 20) (images "crystallo-left-0.png" "crystallo-left-1.png" - "crystallo-left-0.png" - "crystallo-left-2.png") - ) + "crystallo-left-2.png" + "crystallo-left-3.png" + "crystallo-left-4.png" + "crystallo-left-5.png" + "crystallo-left-6.png" + "crystallo-left-7.png")) + (action - (hitbox 0 7 35 20) (name "right") - (mirror-action "left") - ) + (fps 14) + (hitbox 8 9 32 20) + (mirror-action "left")) + + (action + (name "slowdown-left") + (fps 5) + (hitbox 8 9 32 20) + (clone-action "left")) + + (action + (name "slowdown-right") + (fps 5) + (hitbox 8 9 32 20) + (clone-action "right")) + (action (name "shattered-left") - (images "shattered-left.png") - ) + (images "shattered-left.png")) + (action (name "shattered-right") - (mirror-action "shattered-left") - ) + (mirror-action "shattered-left")) + (action (name "editor") (hitbox 100 7 135 20) - (images "crystallo-editor.png") - ) + (images "crystallo-editor.png")) ) diff --git a/data/images/creatures/crystallo/rcrystallo-editor.png b/data/images/creatures/crystallo/rcrystallo-editor.png new file mode 100644 index 00000000000..089d01c8442 Binary files /dev/null and b/data/images/creatures/crystallo/rcrystallo-editor.png differ diff --git a/data/images/creatures/crystallo/rcrystallo.sprite b/data/images/creatures/crystallo/rcrystallo.sprite new file mode 100644 index 00000000000..8699cb00242 --- /dev/null +++ b/data/images/creatures/crystallo/rcrystallo.sprite @@ -0,0 +1,75 @@ +(supertux-sprite + (action + (name "left") + (fps 14) + (hitbox 8 1 32 25) + (images "crystallo-left-0.png" + "crystallo-left-1.png" + "crystallo-left-2.png" + "crystallo-left-3.png" + "crystallo-left-4.png" + "crystallo-left-5.png" + "crystallo-left-6.png" + "crystallo-left-7.png")) + + (action + (name "right") + (fps 14) + (hitbox 8 1 32 25) + (mirror-action "left")) + + (action + (name "slowdown-left") + (fps 5) + (hitbox 8 1 32 25) + (clone-action "left")) + + (action + (name "slowdown-right") + (fps 5) + (hitbox 8 1 32 25) + (clone-action "right")) + + (action + (name "shattered-left") + (images "shattered-left.png")) + + (action + (name "shattered-right") + (mirror-action "shattered-left")) + + (action + (name "detected-left") + (fps 15) + (hitbox 45 2 20 35) + (loops 1) + (images "crystallo-fall-0.png" + "crystallo-fall-1.png" + "crystallo-fall-2.png" + "crystallo-fall-3.png" + "crystallo-fall-4.png" + "crystallo-fall-5.png" + "crystallo-fall-6.png" + "crystallo-fall-7.png" + "crystallo-fall-6.png" + "crystallo-fall-8.png" + "crystallo-fall-9.png" + "crystallo-fall-8.png")) + + (action + (name "detected-right") + (fps 15) + (hitbox 35 2 20 35) + (loops 1) + (mirror-action "detected-left")) + + (action + (name "fall-left") + (hitbox 45 2 20 35) + (images "crystallo-fall-10.png")) + + (action + (name "fall-right") + (hitbox 35 2 20 35) + (mirror-action "fall-left")) +) diff --git a/data/images/creatures/crystallo/scrystallo.sprite b/data/images/creatures/crystallo/scrystallo.sprite new file mode 100644 index 00000000000..adaf4767973 --- /dev/null +++ b/data/images/creatures/crystallo/scrystallo.sprite @@ -0,0 +1,101 @@ +(supertux-sprite + (action + (name "editor-left") + (fps 14) + (hitbox 8 13 32 14) + (loops 1) + (images "crystallo-sleeping.png")) + + (action + (name "editor-right") + (fps 14) + (hitbox 9 13 32 14) + (loops 1) + (mirror-action "editor-left")) + + (action + (name "left") + (fps 14) + (hitbox 8 9 32 20) + (images "crystallo-left-0.png" + "crystallo-left-1.png" + "crystallo-left-2.png" + "crystallo-left-3.png" + "crystallo-left-4.png" + "crystallo-left-5.png" + "crystallo-left-6.png" + "crystallo-left-7.png")) + + (action + (name "right") + (fps 14) + (hitbox 8 9 32 20) + (mirror-action "left")) + + (action + (name "slowdown-left") + (fps 5) + (hitbox 8 9 32 20) + (clone-action "left")) + + (action + (name "slowdown-right") + (fps 5) + (hitbox 8 9 32 20) + (clone-action "right")) + + (action + (name "shattered-left") + (images "shattered-left.png")) + + (action + (name "shattered-right") + (mirror-action "shattered-left")) + + (action + (name "waking-left") + (fps 14) + (hitbox 8 13 32 14) + (loops 1) + (images "crystallo-waking-0.png" + "crystallo-waking-1.png" + "crystallo-sleeping.png" + "crystallo-waking-0.png" + "crystallo-waking-1.png" + "crystallo-waking-1.png" + "crystallo-waking-1.png" + "crystallo-waking-1.png" + "crystallo-preparing-0.png" + "crystallo-preparing-1.png" + "crystallo-preparing-0.png" + "crystallo-preparing-1.png" + "crystallo-preparing-0.png" + "crystallo-preparing-1.png" + "crystallo-preparing-0.png")) + + (action + (name "waking-right") + (fps 14) + (hitbox 9 13 32 14) + (loops 1) + (mirror-action "waking-left")) + + (action + (name "jumping-left") + (fps 14) + (hitbox 8 9 32 20) + (loops 1) + (images "crystallo-jump-1.png" + "crystallo-jump-2.png" + "crystallo-jump-3.png" + "crystallo-jump-4.png" + "crystallo-jump-5.png" + "crystallo-jump-6.png")) + + (action + (name "jumping-right") + (fps 14) + (hitbox 8 9 32 20) + (loops 1) + (mirror-action "jumping-left")) +) diff --git a/data/images/creatures/crystallo/shard.png b/data/images/creatures/crystallo/shard.png new file mode 100644 index 00000000000..c3010659c72 Binary files /dev/null and b/data/images/creatures/crystallo/shard.png differ diff --git a/data/images/creatures/crystallo/shard.sprite b/data/images/creatures/crystallo/shard.sprite new file mode 100644 index 00000000000..ab3ef056d3f --- /dev/null +++ b/data/images/creatures/crystallo/shard.sprite @@ -0,0 +1,6 @@ +(supertux-sprite + (action + (name "default") + (hitbox 8 8 16 16) + (images "shard.png")) +) diff --git a/data/images/creatures/crystallo/shattered-left.png b/data/images/creatures/crystallo/shattered-left.png index 018189a6148..530bae9df24 100644 Binary files a/data/images/creatures/crystallo/shattered-left.png and b/data/images/creatures/crystallo/shattered-left.png differ diff --git a/data/images/engine/editor/objects.stoi b/data/images/engine/editor/objects.stoi index ff12a01fd4f..603f2a9debf 100644 --- a/data/images/engine/editor/objects.stoi +++ b/data/images/engine/editor/objects.stoi @@ -63,6 +63,12 @@ (object (class "crystallo") (icon "images/creatures/crystallo/crystallo-left-0.png")) + (object + (class "scrystallo") + (icon "images/creatures/crystallo/crystallo-sleeping.png")) + (object + (class "rcrystallo") + (icon "images/creatures/crystallo/rcrystallo-editor.png")) (object (class "icecrusher") (icon "images/creatures/icecrusher/iceblock.png")) diff --git a/data/sounds/crystallo-pop.ogg b/data/sounds/crystallo-pop.ogg new file mode 100644 index 00000000000..66ca9ed7939 Binary files /dev/null and b/data/sounds/crystallo-pop.ogg differ diff --git a/data/sounds/crystallo-shardhit.ogg b/data/sounds/crystallo-shardhit.ogg new file mode 100644 index 00000000000..77f107d02fe Binary files /dev/null and b/data/sounds/crystallo-shardhit.ogg differ diff --git a/data/sounds/crystallo-shatter.ogg b/data/sounds/crystallo-shatter.ogg new file mode 100644 index 00000000000..3a25eeca49e Binary files /dev/null and b/data/sounds/crystallo-shatter.ogg differ diff --git a/src/badguy/crystallo.cpp b/src/badguy/crystallo.cpp index d766c628e66..8baa7926dc3 100644 --- a/src/badguy/crystallo.cpp +++ b/src/badguy/crystallo.cpp @@ -24,7 +24,6 @@ Crystallo::Crystallo(const ReaderMapping& reader) : { walk_speed = 80; max_drop_height = 16; - reader.get("radius", m_radius, 100.0f); } @@ -43,19 +42,16 @@ Crystallo::get_settings() void Crystallo::active_update(float dt_sec) { - if (get_pos().x > (m_start_position.x + m_radius)) { - if (m_dir != Direction::LEFT){ - turn_around(); - } - } - - if (get_pos().x < (m_start_position.x - m_radius)) { - if (m_dir != Direction::RIGHT){ - turn_around(); - } - } - - BadGuy::active_update(dt_sec); + //walking and turning properly + float targetwalk = m_dir == Direction::LEFT ? -80.f : 80.f; + if (m_dir != Direction::LEFT && get_pos().x > (m_start_position.x + m_radius - 20.f)) + targetwalk = -80.f; + if (m_dir != Direction::RIGHT && get_pos().x < (m_start_position.x - m_radius + 20.f)) + targetwalk = 80.f; + set_action(std::abs(m_physic.get_velocity_x()) < 80.f ? + m_dir == Direction::LEFT ? "slowdown-left" : "slowdown-right" : + m_dir == Direction::LEFT ? "left" : "right", -1); + WalkingBadguy::active_update(dt_sec, targetwalk, 2.f); } bool @@ -63,6 +59,9 @@ Crystallo::collision_squished(GameObject& object) { set_action(m_dir == Direction::LEFT ? "shattered-left" : "shattered-right", /* loops = */ -1, ANCHOR_BOTTOM); kill_squished(object); + m_physic.set_gravity_modifier(1.f); + m_physic.set_velocity_x(0.0); + m_physic.set_acceleration_x(0.0); return true; } diff --git a/src/badguy/rcrystallo.cpp b/src/badguy/rcrystallo.cpp new file mode 100644 index 00000000000..ad0ed0fe5dc --- /dev/null +++ b/src/badguy/rcrystallo.cpp @@ -0,0 +1,177 @@ +// SuperTux +// Copyright (C) 2021 Daniel Ward +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "badguy/rcrystallo.hpp" + +#include "audio/sound_manager.hpp" +#include "object/explosion.hpp" +#include "object/player.hpp" +#include "object/shard.hpp" +#include "supertux/sector.hpp" + +#include "util/reader_mapping.hpp" + +RCrystallo::RCrystallo(const ReaderMapping& reader) : + WalkingBadguy(reader, "images/creatures/crystallo/rcrystallo.sprite", "left", "right"), + state(RCRYSTALLO_ROOF), + m_radius() +{ + walk_speed = 80; + max_drop_height = 16; + reader.get("radius", m_radius, 100.0f); + SoundManager::current()->preload("sounds/crystallo-shatter.ogg"); +} + +void +RCrystallo::initialize() +{ + Rectf magnetic_box = get_bbox(); + magnetic_box.set_top(m_col.m_bbox.get_top() - 80.f); + state = Sector::get().is_free_of_statics(magnetic_box) ? RCRYSTALLO_FALLING : RCRYSTALLO_ROOF; +} + +ObjectSettings +RCrystallo::get_settings() +{ + ObjectSettings result = WalkingBadguy::get_settings(); + result.add_float(_("Radius"), &m_radius, "radius", 100.0f); + result.reorder({ "radius", "direction", "x", "y" }); + return result; +} + +void +RCrystallo::active_update(float dt_sec) +{ + //initialization of certain events prior to going into cases + auto player = get_nearest_player(); + float targetwalk = m_dir == Direction::LEFT ? -80.f : 80.f; + Rectf reversefallbox = get_bbox(); + + switch (state) + { + case RCRYSTALLO_ROOF: + m_physic.set_gravity_modifier(-1.f); + //walking and turning properly + if (m_dir != Direction::LEFT && get_pos().x > (m_start_position.x + m_radius - 20.f)) + targetwalk = -80.f; + if (m_dir != Direction::RIGHT && get_pos().x < (m_start_position.x - m_radius + 20.f)) + targetwalk = 80.f; + set_action(std::abs(m_physic.get_velocity_x()) < 80.f ? + m_dir == Direction::LEFT ? "slowdown-left" : "slowdown-right" : + m_dir == Direction::LEFT ? "left" : "right", -1); + //turn at holes + reversefallbox.set_top(m_col.m_bbox.get_top() - 33.f); + reversefallbox.set_left(m_col.m_bbox.get_left() + (m_dir == Direction::LEFT ? -5.f : 34.f)); + reversefallbox.set_right(m_col.m_bbox.get_right() + (m_dir == Direction::LEFT ? -34.f : 5.f)); + if (Sector::get().is_free_of_statics(reversefallbox)) + turn_around(); + //detect player and fall when it is time + if (player && player->get_bbox().get_right() > m_col.m_bbox.get_left() - 192.f + && player->get_bbox().get_left() < m_col.m_bbox.get_right() + 192.f + && player->get_bbox().get_bottom() > m_col.m_bbox.get_top() + && Sector::get().free_line_of_sight(m_col.m_bbox.get_middle() + Vector(0, 20), + player->get_bbox().get_middle() - Vector(0, 40), player)) + { + //center enemy, begin falling + m_col.m_bbox.move(Vector(3.f, 0.f)); + set_action(m_dir == Direction::LEFT ? "detected-left" : "detected-right", 1, ANCHOR_TOP); + state = RCRYSTALLO_DETECT; + } + WalkingBadguy::active_update(dt_sec, targetwalk, 2.f); + break; + case RCRYSTALLO_DETECT: + m_physic.set_velocity_x(0.f); + m_physic.set_acceleration_x(0.f); + if (m_sprite->animation_done()) + { + + m_physic.set_gravity_modifier(1.f); + set_action(m_dir == Direction::LEFT ? "fall-left" : "fall-right", 1, ANCHOR_TOP); + state = RCRYSTALLO_FALLING; + } + BadGuy::active_update(dt_sec); + break; + case RCRYSTALLO_FALLING: + BadGuy::active_update(dt_sec); + break; + } +} + +void +RCrystallo::draw(DrawingContext& context) +{ + context.push_transform(); + context.set_flip(context.get_flip() ^ (state == RCRYSTALLO_ROOF ? VERTICAL_FLIP : NO_FLIP)); + m_sprite->draw(context.color(), get_pos(), m_layer); + context.pop_transform(); +} + +void +RCrystallo::collision_solid(const CollisionHit& hit) +{ + if (state == RCRYSTALLO_FALLING && hit.bottom) + kill_fall(); + WalkingBadguy::collision_solid(hit); +} + +HitResponse +RCrystallo::collision_badguy(BadGuy& badguy, const CollisionHit& hit) +{ + if (state == RCRYSTALLO_FALLING) + { + badguy.kill_fall(); + kill_fall(); + } + return WalkingBadguy::collision_badguy(badguy, hit); +} + +HitResponse +RCrystallo::collision_player(Player& player, const CollisionHit& hit) +{ + if (state == RCRYSTALLO_FALLING) + kill_fall(); + return BadGuy::collision_player(player, hit); +} + +bool +RCrystallo::is_flammable() const +{ + return false; +} + +void +RCrystallo::kill_fall() +{ + m_physic.set_gravity_modifier(1.f); + if (state == RCRYSTALLO_FALLING) + { + SoundManager::current()->play("sounds/crystallo-shatter.ogg", get_pos()); + if (is_valid()) + { + remove_me(); + //create 4 shards that the enemy splits into, which serve as an additional threat + Sector::get().add(m_col.m_bbox.get_middle(), Vector(100.f, -500.f)); + Sector::get().add(m_col.m_bbox.get_middle(), Vector(270.f, -350.f)); + Sector::get().add(m_col.m_bbox.get_middle(), Vector(-100.f, -500.f)); + Sector::get().add(m_col.m_bbox.get_middle(), Vector(-270.f, -350.f)); + } + run_dead_script(); + } + else + BadGuy::kill_fall(); +} + +/* EOF */ diff --git a/src/badguy/rcrystallo.hpp b/src/badguy/rcrystallo.hpp new file mode 100644 index 00000000000..c78d09b0fe9 --- /dev/null +++ b/src/badguy/rcrystallo.hpp @@ -0,0 +1,59 @@ +// SuperTux +// Copyright (C) 2021 Daniel Ward +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef HEADER_SUPERTUX_BADGUY_RCRYSTALLO_HPP +#define HEADER_SUPERTUX_BADGUY_RCRYSTALLO_HPP + +#include "badguy/walking_badguy.hpp" + +class RCrystallo final : public WalkingBadguy +{ +public: + RCrystallo(const ReaderMapping& reader); + + virtual void initialize() override; + virtual ObjectSettings get_settings() override; + virtual std::string get_class() const override { return "rcrystallo"; } + virtual std::string get_display_name() const override { return _("Roof Crystallo"); } + + virtual void active_update(float dt_sec) override; + virtual void draw(DrawingContext& context) override; + virtual void collision_solid(const CollisionHit& hit) override; + virtual HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit) override; + virtual HitResponse collision_player(Player& player, const CollisionHit& hit) override; + virtual bool is_flammable() const override; + virtual void kill_fall() override; + +protected: + enum RCrystalloState + { + RCRYSTALLO_ROOF, + RCRYSTALLO_DETECT, + RCRYSTALLO_FALLING + }; + RCrystalloState state; + +private: + float m_radius; + +private: + RCrystallo(const RCrystallo&) = delete; + RCrystallo& operator=(const RCrystallo&) = delete; +}; + +#endif + +/* EOF */ diff --git a/src/badguy/scrystallo.cpp b/src/badguy/scrystallo.cpp new file mode 100644 index 00000000000..a278cde86d3 --- /dev/null +++ b/src/badguy/scrystallo.cpp @@ -0,0 +1,162 @@ +// SuperTux +// Copyright (C) 2021 Daniel Ward +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "badguy/scrystallo.hpp" + +#include "audio/sound_manager.hpp" +#include "object/player.hpp" +#include "sprite/sprite.hpp" +#include "supertux/sector.hpp" +#include "util/reader_mapping.hpp" + +SCrystallo::SCrystallo(const ReaderMapping& reader) : + WalkingBadguy(reader, "images/creatures/crystallo/scrystallo.sprite", "editor-left", "editor-right"), + state(SCRYSTALLO_SLEEPING), + m_radius(), + m_range(), + m_radius_anchor() +{ + walk_speed = 80; + max_drop_height = 16; + reader.get("radius", m_radius, 100.0f); + reader.get("range", m_range, 250.0f); + SoundManager::current()->preload("sounds/crystallo-pop.ogg"); +} + +void +SCrystallo::initialize() +{ + state = SCRYSTALLO_SLEEPING; + m_physic.enable_gravity(false); + m_sprite->set_action(m_dir == Direction::LEFT ? "editor-left" : "editor-right"); +} + +ObjectSettings +SCrystallo::get_settings() +{ + ObjectSettings result = WalkingBadguy::get_settings(); + + result.add_float(_("Walk Radius"), &m_radius, "radius", 100.0f); + result.add_float(_("Awakening Radius"), &m_range, "range", 250.0f); + + result.reorder({ "radius", "range", "direction", "x", "y" }); + + return result; +} + +void +SCrystallo::collision_solid(const CollisionHit& hit) +{ + if (state != SCRYSTALLO_WALKING) + { + BadGuy::collision_solid(hit); + return; + } + WalkingBadguy::collision_solid(hit); +} + +HitResponse +SCrystallo::collision_badguy(BadGuy& badguy, const CollisionHit& hit) +{ + if (state != SCRYSTALLO_WALKING) + { + return BadGuy::collision_badguy(badguy, hit); + } + return WalkingBadguy::collision_badguy(badguy, hit); +} + +void +SCrystallo::active_update(float dt_sec) +{ + auto player = get_nearest_player(); + Rectf downbox = get_bbox(); + switch (state) + { + case SCRYSTALLO_SLEEPING: + m_physic.set_velocity(0.f, 0.f); + m_physic.set_acceleration(0.f, 0.f); + // is sleeping peacefully + if (player) + { + Vector p1 = m_col.m_bbox.get_middle(); + Vector p2 = player->get_bbox().get_middle(); + Vector dist = (p2 - p1); + if (glm::length(dist) <= m_range) + { + m_sprite->set_action(m_dir == Direction::LEFT ? "waking-left" : "waking-right", 1); + state = SCRYSTALLO_WAKING; + } + } + BadGuy::active_update(dt_sec); + break; + case SCRYSTALLO_WAKING: + m_physic.set_velocity(0.f, 0.f); + m_physic.set_acceleration(0.f, 0.f); + //wake up, acknowledge surroundings + if (m_sprite->animation_done()) + { + SoundManager::current()->play("sounds/crystallo-pop.ogg", get_pos()); + m_physic.enable_gravity(true); + m_physic.set_velocity_y(-250.f); + WalkingBadguy::initialize(); + set_action(m_dir == Direction::LEFT ? "jumping-left" : "jumping-right", -1); + state = SCRYSTALLO_JUMPING; + } + BadGuy::active_update(dt_sec); + break; + case SCRYSTALLO_JUMPING: + //popping out of the hole, ends when near ground + downbox.set_bottom(get_bbox().get_bottom() + 10.f); + if (!Sector::get().is_free_of_statics(downbox)) + { + m_radius_anchor = get_pos(); + state = SCRYSTALLO_WALKING; + } + WalkingBadguy::active_update(dt_sec); + break; + case SCRYSTALLO_WALKING: + //walking and turning properly + float targetwalk = m_dir == Direction::LEFT ? -80.f : 80.f; + if (m_dir != Direction::LEFT && get_pos().x > (m_radius_anchor.x + m_radius - 20.f)) + targetwalk = -80.f; + if (m_dir != Direction::RIGHT && get_pos().x < (m_radius_anchor.x - m_radius + 20.f)) + targetwalk = 80.f; + set_action(std::abs(m_physic.get_velocity_x()) < 80.f ? + m_dir == Direction::LEFT ? "slowdown-left" : "slowdown-right" : + m_dir == Direction::LEFT ? "left" : "right", -1); + WalkingBadguy::active_update(dt_sec, targetwalk, 2.f); + break; + } +} + +bool +SCrystallo::collision_squished(GameObject& object) +{ + set_action(m_dir == Direction::LEFT ? "shattered-left" : "shattered-right", /* loops = */ -1, ANCHOR_BOTTOM); + kill_squished(object); + m_physic.enable_gravity(true); + m_physic.set_velocity_x(0.0); + m_physic.set_acceleration_x(0.0); + return true; +} + +bool +SCrystallo::is_flammable() const +{ + return false; +} + +/* EOF */ diff --git a/src/badguy/scrystallo.hpp b/src/badguy/scrystallo.hpp new file mode 100644 index 00000000000..b689ca7388d --- /dev/null +++ b/src/badguy/scrystallo.hpp @@ -0,0 +1,59 @@ +// SuperTux +// Copyright (C) 2021 Daniel Ward +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef HEADER_SUPERTUX_BADGUY_SCRYSTALLO_HPP +#define HEADER_SUPERTUX_BADGUY_SCRYSTALLO_HPP + +#include "badguy/walking_badguy.hpp" + +class SCrystallo final : public WalkingBadguy +{ +public: + SCrystallo(const ReaderMapping& reader); + + virtual void initialize() override; + virtual ObjectSettings get_settings() override; + virtual std::string get_class() const override { return "scrystallo"; } + virtual std::string get_display_name() const override { return _("Sleeping Crystallo"); } + + virtual void collision_solid(const CollisionHit& hit) override; + virtual HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit) override; + + virtual void active_update(float dt_sec) override; + virtual bool is_flammable() const override; + +protected: + virtual bool collision_squished(GameObject& object) override; +protected: + enum SCrystalloState + { + SCRYSTALLO_SLEEPING, + SCRYSTALLO_WAKING, + SCRYSTALLO_JUMPING, + SCRYSTALLO_WALKING + }; + SCrystalloState state; + +private: + float m_radius; + float m_range; + Vector m_radius_anchor; +private: + SCrystallo(const SCrystallo&) = delete; + SCrystallo& operator=(const SCrystallo&) = delete; +}; + +#endif diff --git a/src/badguy/walking_badguy.cpp b/src/badguy/walking_badguy.cpp index 26bd7ee247c..5ae987eb0c0 100644 --- a/src/badguy/walking_badguy.cpp +++ b/src/badguy/walking_badguy.cpp @@ -94,7 +94,7 @@ WalkingBadguy::add_velocity (const Vector& velocity) } void -WalkingBadguy::active_update(float dt_sec, float dest_x_velocity) +WalkingBadguy::active_update(float dt_sec, float dest_x_velocity, float modifier) { BadGuy::active_update(dt_sec); @@ -118,7 +118,7 @@ WalkingBadguy::active_update(float dt_sec, float dest_x_velocity) { /* acceleration == walk-speed => it will take one second to get from zero * to full speed. */ - m_physic.set_acceleration_x (dest_x_velocity); + m_physic.set_acceleration_x (dest_x_velocity * modifier); } /* Check if we're going too fast */ else if (((dest_x_velocity <= 0.0f) && (current_x_velocity < dest_x_velocity)) || diff --git a/src/badguy/walking_badguy.hpp b/src/badguy/walking_badguy.hpp index 1bf8ea032f6..48e2aa5cabb 100644 --- a/src/badguy/walking_badguy.hpp +++ b/src/badguy/walking_badguy.hpp @@ -51,7 +51,7 @@ class WalkingBadguy : public BadGuy virtual void freeze() override; virtual void unfreeze() override; - void active_update(float dt_sec, float target_velocity); + void active_update(float dt_sec, float target_velocity, float modifier = 1.f); float get_velocity_x() const { return m_physic.get_velocity_x(); } float get_velocity_y() const { return m_physic.get_velocity_y(); } diff --git a/src/object/shard.cpp b/src/object/shard.cpp new file mode 100644 index 00000000000..68a6631fa66 --- /dev/null +++ b/src/object/shard.cpp @@ -0,0 +1,87 @@ +// SuperTux +// Copyright (C) 2021 Daniel Ward +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "object/shard.hpp" + +#include "audio/sound_manager.hpp" +#include "badguy/badguy.hpp" +#include "math/util.hpp" +#include "object/player.hpp" +#include "sprite/sprite.hpp" +#include "util/reader_mapping.hpp" + +Shard::Shard(const ReaderMapping& reader) : + MovingSprite(reader, "images/creatures/crystallo/shard.sprite", LAYER_TILES - 2, COLGROUP_MOVING), + m_physic(), + m_stick_timer() +{ + m_physic.enable_gravity(true); + SoundManager::current()->preload("sounds/crystallo-shardhit.ogg"); +} + +Shard::Shard(const Vector& pos, const Vector& velocity) : + MovingSprite(pos, "images/creatures/crystallo/shard.sprite", LAYER_TILES - 2, COLGROUP_MOVING), + m_physic(), + m_stick_timer() +{ + m_physic.enable_gravity(true); + m_physic.set_velocity(velocity); + m_sprite->set_action("default"); + SoundManager::current()->preload("sounds/crystallo-shardhit.ogg"); +} + +void +Shard::update(float dt_sec) +{ + if (m_physic.get_velocity() != Vector(0.f, 0.f)) + m_sprite->set_angle(math::degrees(math::angle(Vector(m_physic.get_velocity_x(), m_physic.get_velocity_y())))); + m_col.set_movement(m_physic.get_movement(dt_sec)); + if (m_stick_timer.check()) + remove_me(); +} + +void +Shard::collision_solid(const CollisionHit& hit) +{ + m_physic.set_velocity(0.f, 0.f); + m_physic.set_acceleration(0.f, 0.f); + m_physic.enable_gravity(hit.bottom); + if (!m_stick_timer.started()) + { + m_stick_timer.start(5.f); + SoundManager::current()->play("sounds/crystallo-shardhit.ogg", get_pos()); + } +} + +HitResponse +Shard::collision(GameObject& other, const CollisionHit&) +{ + // ignore collisions with other shards + auto shard = dynamic_cast(&other); + if (&other == shard) + return ABORT_MOVE; + // kill badguys + auto badguy = dynamic_cast(&other); + if (badguy != nullptr) + badguy->kill_fall(); + // kill players + auto player = dynamic_cast(&other); + if (player != nullptr) + player->kill(false); + return ABORT_MOVE; +} + +/* EOF */ diff --git a/src/object/shard.hpp b/src/object/shard.hpp new file mode 100644 index 00000000000..c2adf74b3dc --- /dev/null +++ b/src/object/shard.hpp @@ -0,0 +1,49 @@ +// SuperTux +// Copyright (C) 2021 Daniel Ward +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef HEADER_SUPERTUX_OBJECT_SHARD_HPP +#define HEADER_SUPERTUX_OBJECT_SHARD_HPP + +#include "object/moving_sprite.hpp" +#include "supertux/physic.hpp" +#include "supertux/timer.hpp" + +class Shard final : public MovingSprite +{ +public: + Shard(const ReaderMapping& reader); + Shard(const Vector& pos, const Vector& velocity); + + virtual void update(float dt_sec) override; + virtual void collision_solid(const CollisionHit& hit) override; + virtual HitResponse collision(GameObject& other, const CollisionHit& hit) override; + virtual std::string get_class() const override { return "shard"; } + virtual std::string get_display_name() const override { return _("Shard"); } + +protected: + Physic m_physic; + +private: + Timer m_stick_timer; + +private: + Shard(const Shard&) = delete; + Shard& operator=(const Shard&) = delete; +}; + +#endif + +/* EOF */ diff --git a/src/supertux/game_object_factory.cpp b/src/supertux/game_object_factory.cpp index 27d9fb2ea72..c36a016356a 100644 --- a/src/supertux/game_object_factory.cpp +++ b/src/supertux/game_object_factory.cpp @@ -45,6 +45,7 @@ #include "badguy/owl.hpp" #include "badguy/plant.hpp" #include "badguy/poisonivy.hpp" +#include "badguy/rcrystallo.hpp" #include "badguy/short_fuse.hpp" #include "badguy/skullyhop.hpp" #include "badguy/skydive.hpp" @@ -54,6 +55,7 @@ #include "badguy/snowball.hpp" #include "badguy/snowman.hpp" #include "badguy/spidermite.hpp" +#include "badguy/scrystallo.hpp" #include "badguy/spiky.hpp" #include "badguy/sspiky.hpp" #include "badguy/stalactite.hpp" @@ -107,6 +109,7 @@ #include "object/rublight.hpp" #include "object/rusty_trampoline.hpp" #include "object/scripted_object.hpp" +#include "object/shard.hpp" #include "object/skull_tile.hpp" #include "object/snow_particle_system.hpp" #include "object/spawnpoint.hpp" @@ -179,6 +182,8 @@ GameObjectFactory::init_factories() add_factory("owl"); add_factory("plant"); add_factory("poisonivy"); + add_factory("rcrystallo"); + add_factory("scrystallo"); add_factory("short_fuse"); add_factory("sspiky"); add_factory("skydive"); @@ -243,6 +248,7 @@ GameObjectFactory::init_factories() add_factory("rock"); add_factory("rublight"); add_factory("scriptedobject"); + add_factory("shard"); add_factory("skull_tile"); add_factory("particles-snow"); add_factory("spotlight");