Now have animated torches that are defined from json, and smoother animations in the arena.

This commit is contained in:
Zed A. Shaw 2025-10-21 00:21:46 -04:00
parent 387d1a5bf5
commit 7c11ffa2af
10 changed files with 111 additions and 73 deletions

View file

@ -38,12 +38,12 @@ namespace components {
float tick = twitching();
if(stationary) {
scale_out.x = std::lerp(scale, max_scale, tick);
scale_out.y = std::lerp(scale, max_scale, tick);
scale_out.x = std::lerp(scale_x, max_scale, tick);
scale_out.y = std::lerp(scale_y, max_scale, tick);
pos_out.y = pos_out.y - (pos_out.y * scale_out.y - pos_out.y);
} else {
scale_out.x = std::lerp(scale_out.x * scale, scale_out.x * max_scale, tick);
scale_out.y = std::lerp(scale_out.y * scale, scale_out.y * max_scale, tick);
scale_out.x = std::lerp(scale_out.x * scale_x, scale_out.x * max_scale, tick);
scale_out.y = std::lerp(scale_out.y * scale_y, scale_out.y * max_scale, tick);
}
if(!simple) {
@ -51,8 +51,8 @@ namespace components {
}
subframe += speed;
current = int(subframe);
} else if(!looped) {
current = looped ? int(subframe) % frames : int(subframe);
} else if(toggled) {
playing = false;
current = frames - 1;
subframe = float(frames - 1);
@ -61,8 +61,8 @@ namespace components {
rect_out.position.x += current * frame_width;
}
} else {
scale_out.x = scale;
scale_out.y = scale;
scale_out.x = scale_x;
scale_out.y = scale_y;
playing = false;
current = 0;
subframe = 0.0f;
@ -80,7 +80,7 @@ namespace animation {
bool apply(Animation& anim, sf::Sprite& sprite, sf::Vector2f pos) {
sf::IntRect rect{{0,0}, {anim.frame_width, anim.frame_height}};
sf::Vector2f scale{anim.scale, anim.scale};
sf::Vector2f scale{anim.scale_x, anim.scale_y};
anim.step(scale, pos, rect);

View file

@ -3,154 +3,196 @@
"_type": "Animation",
"easing": 0,
"ease_rate": 0.5,
"scale": 1.0,
"scale_x": 1.0,
"scale_y": 1.0,
"max_scale": 1.0,
"simple": false,
"frames": 5,
"speed": 0.1,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"male_hand": {
"_type": "Animation",
"easing": 0,
"ease_rate": 0.5,
"scale": 1.0,
"scale_x": 1.0,
"scale_y": 1.0,
"max_scale": 1.0,
"simple": false,
"frames": 3,
"speed": 0.08,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"female_hand": {
"_type": "Animation",
"easing": 0,
"ease_rate": 0.5,
"scale": 1.0,
"scale_x": 1.0,
"scale_y": 1.0,
"max_scale": 1.0,
"simple": false,
"frames": 3,
"speed": 0.08,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"lightning_animation": {
"_type": "Animation",
"easing": 0,
"ease_rate": 0.5,
"scale": 1.0,
"scale_x": 1.0,
"scale_y": 1.0,
"max_scale": 1.0,
"simple": false,
"frames": 5,
"speed": 0.5,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"ritual_crafting_area": {
"_type": "Animation",
"easing": 0,
"ease_rate": 0.5,
"scale": 1.0,
"scale_x": 1.0,
"scale_y": 1.0,
"max_scale": 1.0,
"simple": false,
"frames": 3,
"speed": 0.2,
"stationary": true
"stationary": true,
"toggled": true,
"looped": false
},
"peasant_girl_rear_view": {
"_type": "Animation",
"easing": 3,
"ease_rate": 0.2,
"scale": 0.5,
"scale_x": 0.5,
"scale_y": 0.5,
"max_scale": 0.5,
"simple": true,
"frames": 1,
"speed": 0.03,
"stationary": true
"stationary": true,
"toggled": false,
"looped": false
},
"gold_savior": {
"_type": "Animation",
"easing": 1,
"ease_rate": 0.2,
"scale": 1.1,
"scale_x": 1.1,
"scale_y": 1.1,
"max_scale": 1.2,
"simple": true,
"frames": 10,
"speed": 0.3,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"armored_knight" : {
"_type": "Animation",
"easing": 1,
"ease_rate": 0.2,
"scale": 1.1,
"scale_x": 1.1,
"scale_y": 1.1,
"max_scale": 1.2,
"simple": true,
"frames": 10,
"speed": 0.3,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"axe_ranger": {
"_type": "Animation",
"easing": 3,
"ease_rate": 0.5,
"scale": 1.1,
"scale_x": 1.1,
"scale_y": 1.1,
"max_scale": 1.2,
"simple": true,
"frames": 1,
"speed": 0.6,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"rat_with_sword": {
"_type": "Animation",
"easing": 3,
"ease_rate": 0.5,
"scale": 1.0,
"scale_x": 1.0,
"scale_y": 1.0,
"max_scale": 0.9,
"simple": true,
"frames": 1,
"speed": 1.0,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"hairy_spider": {
"_type": "Animation",
"easing": 2,
"ease_rate": 0.5,
"scale": 0.9,
"scale_x": 0.9,
"scale_y": 0.9,
"max_scale": 1.1,
"simple": true,
"frames": 10,
"speed": 1.0,
"stationary": false
"stationary": false,
"toggled": false,
"looped": false
},
"test_boss": {
"_type": "Animation",
"easing": 1,
"ease_rate": 0.5,
"scale": 0.4,
"scale_x": 0.4,
"scale_y": 0.4,
"max_scale": 0.4,
"simple": true,
"frames": 1,
"speed": 0.02,
"stationary": true
"stationary": true,
"toggled": false,
"looped": false
},
"rat_king_boss": {
"_type": "Animation",
"easing": 4,
"ease_rate": 0.9,
"scale": 0.6,
"scale_x": 0.6,
"scale_y": 0.6,
"max_scale": 0.7,
"simple": false,
"frames": 2,
"speed": 0.02,
"stationary": true
"stationary": true,
"toggled": false,
"looped": false
},
"torch_fixture": {
"_type": "Animation",
"easing": 0,
"ease_rate": 0.5,
"scale": 0.4,
"scale_x": 0.5,
"scale_y": 0.5,
"max_scale": 0.4,
"simple": true,
"frames": 1,
"speed": 0.02,
"stationary": true
"simple": false,
"frames": 3,
"speed": 0.2,
"stationary": true,
"toggled": false,
"looped": true
}
}

View file

@ -18,8 +18,8 @@
"sprite": "rat_king_boss"
},
"fixtures": [
{"name": "torch_fixture", "scale_x": 0.5, "scale_y": 0.5, "cell": "torch1", "x": 66, "y": -10},
{"name": "torch_fixture", "scale_x": -0.5, "scale_y": 0.5, "cell": "torch2", "x": 130, "y": -10}
{"name": "torch_fixture", "scale_x": 0.5, "scale_y": 0.5, "cell": "torch1", "x": 66, "y": -50},
{"name": "torch_fixture", "scale_x": -0.5, "scale_y": 0.5, "cell": "torch2", "x": 132, "y": -30}
]
},
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Before After
Before After

View file

@ -128,7 +128,8 @@ namespace boss {
}
void Fight::render(sf::RenderWindow& window) {
$ui.play_animations(window);
window.clear();
$ui.play_animations();
$ui.render(window);
}
}

View file

@ -35,10 +35,14 @@ namespace boss {
auto st = textures::get_sprite(name);
// clone the sprite so it can be positioned
st.sprite = std::make_shared<sf::Sprite>(*st.texture);
auto anim = animation::load(name);
float scale_x = fixture["scale_x"];
float scale_y = fixture["scale_y"];
auto anim = animation::load(name);
anim.scale_x = scale_x;
anim.scale_y = scale_y;
anim.play();
std::string cell = fixture["cell"];
float x = fixture["x"];
float y = fixture["y"];
@ -72,6 +76,7 @@ namespace boss {
for(auto& fixture : $fixtures) {
position_sprite(fixture.st, fixture.cell,
fixture.scale_x, fixture.scale_y, false, fixture.x, fixture.y);
fixture.pos = fixture.st.sprite->getPosition();
}
$arena.init();
@ -147,27 +152,14 @@ namespace boss {
position_sprite($player_sprite, cell_name, scale, scale, $scene.player["mid_cell"]);
}
void UI::play_animations(sf::RenderWindow& window) {
if($boss_anim.playing) {
using namespace std::chrono_literals;
auto& sound = $world->get<components::Sound>($boss_id);
animation::apply($boss_anim, *$boss_sprite.sprite, $boss_pos);
if($boss_anim.current == 1 && !sound::playing(sound.attack)) {
sound::play(sound.attack);
void UI::play_animations() {
for(auto& fixture : $fixtures) {
if(fixture.anim.playing) {
animation::apply(fixture.anim, *fixture.st.sprite, fixture.pos);
}
}
// https://www.construct.net/en/blogs/ashleys-blog-2/using-lerp-delta-time-924
// frame start
render(window);
window.display();
// frame end
// deltaTime = end - start
// lerp(a, b, 1 - f ^ deltaTime)
// std::this_thread::sleep_for(16ms);
} else {
if($boss_anim.playing) {
animation::apply($boss_anim, *$boss_sprite.sprite, $boss_pos);
}
}

View file

@ -16,6 +16,7 @@ struct AnimatedFixture {
float x;
float y;
bool at_mid=false;
sf::Vector2f pos{0,0};
};
namespace boss {
@ -47,6 +48,6 @@ namespace boss {
void status(const std::wstring& msg);
void move_boss(const std::string& cell_name);
void move_player(const std::string& cell_name);
void play_animations(sf::RenderWindow& window);
void play_animations();
};
}

View file

@ -117,7 +117,8 @@ namespace components {
};
struct Animation {
float scale = 1.0f;
float scale_x = 1.0f;
float scale_y = 1.0f;
float max_scale = 1.0f;
bool simple = true;
int frames = 10;
@ -125,10 +126,12 @@ namespace components {
ease::Style easing = ease::IN_OUT_BACK;
float ease_rate = 0.5f;
bool stationary = false;
bool toggled = false;
bool looped = false;
int current = 0;
bool playing = false;
float subframe = 0.0f;
bool looped = false;
// BUG: this is weirdly not used in most animations but also named wrong should be frame_width
int frame_width = -1;
int frame_height = -1;
@ -159,8 +162,8 @@ namespace components {
ENROLL_COMPONENT(Motion, dx, dy, random);
ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead);
ENROLL_COMPONENT(Device, config, events);
ENROLL_COMPONENT(Animation, scale, max_scale, simple, frames,
speed, easing, ease_rate, stationary);
ENROLL_COMPONENT(Animation, scale_x, scale_y, max_scale, simple, frames,
speed, easing, ease_rate, stationary, toggled, looped);
ENROLL_COMPONENT(Sound, attack, death);
ENROLL_COMPONENT(Collision, has);

View file

@ -28,10 +28,10 @@ function Build-Images {
# Build-Images -Source "Textures" -pixel_count 12
# Build-Images -Source "Sprites" -pixel_count 6
# Build-Images -Source "Items" -pixel_count 2
# Build-Images -Source "Animations" -pixel_count 6
Build-Images -Source "Animations" -pixel_count 24
# Build-Images -Source "Hands" -pixel_count 6
# Build-Images -Source "Boss2" -pixel_count 4
Build-Images -Source "Fixtures" -pixel_count 24
# Build-Images -Source "Fixtures" -pixel_count 24
#magick montage -tile 3x1 -geometry +0+0 -background transparent .\assets\hands\female_hand_*.png .\assets\hands\female_hand.png

View file

@ -36,7 +36,7 @@ int main(int, char*[]) {
gui::routing::Router router;
sound::mute(true);
sound::mute(false);
sound::play("ambient_1", true);
GameDB::create_level();
@ -71,7 +71,6 @@ int main(int, char*[]) {
}
}
window.clear();
main->render(window);
window.display();
}