Nimbin[12]?SDL & Graphics / mapcreator / commits / fd8f457

mapcreator git · master

SDL3 2.5D game and engine using assets, with map editor

sdl3 c++ game engine map-editor cmake · first commit 2025-10-31 · last commit 2026-09-07 (1 month ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/sdl-spieleentwicklung/map_creator

C++ 99.3%
git clone https://git.christianimmanuel.de/sdl-graphics/mapcreator.gitwget https://git.christianimmanuel.de/sdl-graphics/mapcreator/archive/mapcreator.tar.gz

Start implementing bird

Christian Immanuel · 2025-12-15 10:18 · fd8f4577219d51558c3cdabceee6596b4bfc84ec

 src/bird/bird.cpp           | 139 ++++++++++++++++++++++++++++++++++++++++++++
 src/bird/bird.hpp           |  53 +++++++++++++++++
 src/character/character.cpp |  12 +++-
 src/character/character.hpp |   2 +
 src/game/state_playing.cpp  |   5 +-
 5 files changed, 209 insertions(+), 2 deletions(-)

diff --git a/src/bird/bird.cpp b/src/bird/bird.cpp
new file mode 100644
index 0000000..812400f
--- /dev/null
+++ b/src/bird/bird.cpp
@@ -0,0 +1,139 @@
+#include "bird.hpp"
+
+#include <SDL3/SDL.h>
+#include <SDL3_image/SDL_image.h>
+#include <cstdint>
+#include <iostream>
+
+#include "defaults/defaults.hpp"
+
+SDL_Texture* Bird::texture;
+
+Bird::Bird(int x, int y)
+    : pos_x(x),
+      pos_y(y) {
+    set_State(BirdState::IDLE);
+}
+
+bool
+Bird::Init(SDL_Renderer* renderer) {
+    texture = IMG_LoadTexture(renderer, "Bird/Spritesheet/Bird Spritesheet.png");
+    SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
+    return texture != nullptr;
+
+}
+
+void
+Bird::Update(double delta_ms) {
+    animation_timer += delta_ms;
+
+    std::cout << "FT: " << current_frame << " " << animation_timer << std::endl;
+    if (animation_timer >= frame_duration_ms) {
+        animation_timer = 0;
+        current_frame += frame_step;
+
+        if (current_frame >= frame_count || current_frame < 0) {
+            if (state == BirdState::START_TO_FLY) {
+                set_State(BirdState::FLYING);
+                return;
+            }
+
+            if (state == BirdState::STOP_FLYING) {
+                set_State(BirdState::IDLE);
+                return;
+            }
+
+            current_frame = 0;
+        }
+
+        src_rect.x = current_frame * tile_size;
+    }
+}
+
+void
+Bird::Render(SDL_Renderer* renderer) {
+    SDL_FRect dst;
+    dst.x = Scale(static_cast<float>(pos_x));
+    dst.y = Scale(static_cast<float>(pos_y));
+    dst.w = Scale(tile_size);
+    dst.h = Scale(tile_size);
+
+    SDL_RenderTexture(renderer, texture, &src_rect, &dst);
+}
+
+void
+Bird::set_Position(SDL_FPoint point) {
+    pos_x = point.x;
+    pos_y = point.y;
+}
+
+void
+Bird::set_State(BirdState new_state) {
+    if (state == new_state)
+        return;
+
+    state = new_state;
+    std::cout << "SET BIRD STATE\n";
+    animation_timer = 0;
+
+    reverse_animation = false;
+    frame_step = 1;
+
+    switch (state) {
+        case BirdState::IDLE:
+            current_frame = 0;
+            set_Animation(0, 2, 0.05);
+            break;
+
+        case BirdState::FLYING:
+            current_frame = 0;
+            set_Animation(1, 8, 0.08);
+            break;
+
+        case BirdState::WALKING:
+            current_frame = 0;
+            set_Animation(2, 3, 0.02);
+            break;
+
+        case BirdState::EATING:
+            current_frame = 0;
+            set_Animation(3, 3, 0.03);
+            break;
+
+        case BirdState::START_TO_FLY:
+            current_frame = 0;
+            set_Animation(4, 8, 0.01);
+            break;
+
+        case BirdState::STOP_FLYING:
+            set_Animation(4, 8, 0.01);
+            reverse_animation = true;
+            frame_step = -1;
+            current_frame = frame_count - 1;
+            break;
+
+        case BirdState::ATTACK:
+            current_frame = 0;
+            set_Animation(1, 8, 0.06);
+            break;
+    }
+
+    src_rect.x = current_frame * tile_size;
+}
+
+BirdState
+Bird::get_State() const {
+    return state;
+}
+
+
+void
+Bird::set_Animation(int row, int frames, double frame_time) {
+    frame_count = frames;
+    frame_duration_ms = frame_time;
+
+    src_rect.x = 0;
+    src_rect.y = row * tile_size;
+    src_rect.w = tile_size;
+    src_rect.h = tile_size;
+}
diff --git a/src/bird/bird.hpp b/src/bird/bird.hpp
new file mode 100644
index 0000000..ed26f86
--- /dev/null
+++ b/src/bird/bird.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+
+enum class BirdState {
+    IDLE,
+    FLYING,
+    WALKING,
+    EATING,
+    START_TO_FLY,
+    STOP_FLYING,
+    ATTACK
+};
+
+#include <SDL3/SDL.h>
+#include <cstdint>
+
+class Bird
+{
+public:
+    Bird(int x, int y);
+
+    static bool Init(SDL_Renderer*);
+
+    void Update(double delta_ms);
+
+    void Render(SDL_Renderer* renderer);
+
+    void set_State(BirdState new_state);
+    void set_Position(SDL_FPoint);
+
+    BirdState get_State() const;
+
+private:
+    void set_Animation(int row, int frames, double frame_time);
+
+    static SDL_Texture* texture;
+
+    float pos_x = 0;
+    float pos_y = 0;
+
+    static constexpr int tile_size = 16;
+
+    BirdState state = BirdState::IDLE;
+
+    SDL_FRect src_rect{};
+    int current_frame = 0;
+    int frame_count = 1;
+    bool reverse_animation = false;
+    int frame_step = 1;
+
+    double frame_duration_ms = 200;
+    double animation_timer = 0;
+};
diff --git a/src/character/character.cpp b/src/character/character.cpp
index 900f368..8aea8a9 100644
--- a/src/character/character.cpp
+++ b/src/character/character.cpp
@@ -32,7 +32,7 @@ Character::Character(Character&&) {
 
 
 Character::~Character() {
-
+    delete bird;
 }
 
 void
@@ -69,6 +69,10 @@ Character::Init(SDL_Renderer* renderer) {
 
     selected_item = inventory->hotbar_hands;
 
+    bird = new Bird(x, y);
+    bird->set_State(BirdState::FLYING);
+
+
     // load_MapTiles animations
     animation.idle[WalkDirection::DOWN] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Down-Sheet.png", tile_size, tile_size);
     animation.idle[WalkDirection::SIDE] = Animation::load(renderer, "Pixel_Crawler/Entities/Characters/Body_A/Animations/Idle_Base/Idle_Side-Sheet.png", tile_size, tile_size);
@@ -301,6 +305,9 @@ Character::Draw(SDL_Renderer* renderer) {
     float center_x = x + (src.w * 0.5f);
     float start_y  = y - row_h - 2.0f;
     messages->Render(renderer, center_x, start_y);
+
+    // DRAW BIRD
+    bird->Render(renderer);
 }
 
 /*
@@ -1607,6 +1614,9 @@ void Character::handle_Move() {
 
 
 void Character::Update() {
+    bird->set_Position({x,y});
+    bird->Update(Default::delta_time);
+
     if ( is_placing_build)
         BuildingData::update_ActiveBuildData(collider_world.x, collider_world.y - collider.h);
 
diff --git a/src/character/character.hpp b/src/character/character.hpp
index 7c97293..1e9d33d 100644
--- a/src/character/character.hpp
+++ b/src/character/character.hpp
@@ -19,6 +19,7 @@
 #include "building/building_data.hpp"
 #include "building/building.hpp"
 #include "vegetables/vegetables.hpp"
+#include "bird/bird.hpp"
 
 // Character stuff
 
@@ -158,6 +159,7 @@ class Character {
     CharacterAttackingLogic   attacking_logic;
     CharacterConsumingLogic   consuming_logic;
     CharacterSprintStartLogic sprintstart_logic;
+    Bird* bird = nullptr;
 
     float death_duration;
     float death_duration_max;
diff --git a/src/game/state_playing.cpp b/src/game/state_playing.cpp
index 033f779..83c62f5 100644
--- a/src/game/state_playing.cpp
+++ b/src/game/state_playing.cpp
@@ -7,6 +7,7 @@
 #include "game/game.hpp"
 #include "defaults/ui.hpp"
 #include "character/message.hpp"
+#include "bird/bird.hpp"
 
 StatePlaying::StatePlaying() { 
     std::cout << "CREATE STATE_PLAYING\n";
@@ -33,6 +34,9 @@ bool StatePlaying::Init(Game* game) {
     // INIT Building
     BuildingData::Init(game->renderer);
 
+    // INIT Bird
+    Bird::Init(game->renderer);
+
     Map::tile_map = Map::load_MapTiles(Map::save_path);
     if (Map::tile_map.size() == 0) Map::Init();
 
@@ -219,7 +223,6 @@ void StatePlaying::Update(Game* game) {
 
     // CAMERA
     update_CameraOffset({player->x+player->tile_size/2, player->y+player->tile_size/2}, game->win_size);
-    std::cout << "WO: " << game->win_size.w << " " << game->win_size.h << std::endl;
 }
 
 void StatePlaying::Render(Game* game) {