mapcreator git · master
SDL3 2.5D game and engine using assets, with map editor
C++ 99.3%git clone https://git.christianimmanuel.de/sdl-graphics/mapcreator.gitwget https://git.christianimmanuel.de/sdl-graphics/mapcreator/archive/mapcreator.tar.gzBird fix zindex
src/bird/bird.cpp | 109 +++++++++++++++++++++++++++++++++++--------- src/bird/bird.hpp | 27 +++++++---- src/character/character.cpp | 3 -- src/map/map.cpp | 22 +++++++++ 4 files changed, 127 insertions(+), 34 deletions(-) diff --git a/src/bird/bird.cpp b/src/bird/bird.cpp index 88ca72d..6e4860d 100644 --- a/src/bird/bird.cpp +++ b/src/bird/bird.cpp @@ -18,11 +18,17 @@ static constexpr float FLIGHT_HEIGHT = 80.0f; // Consistent flying altitude SDL_Texture* Bird::texture; +std::vector<Bird*> Bird::birds{}; +std::atomic<std::uint64_t> Bird::next_id{0}; + Bird::Bird(float x, float y) - : pos_x(x), + : drawn(false), + pos_x(x), pos_y(y), + id(next_id.fetch_add(1, std::memory_order_relaxed)), target_pos{x, y}, decision_timer(0.0) { + birds.push_back(this); set_State(BirdState::WALKING, 2.4); } @@ -33,7 +39,8 @@ bool Bird::Init(SDL_Renderer* renderer) { } void Bird::Update(double delta_s, const SDL_FPoint& player_pos) { - std::cout << (int)state << " ISTART " << is_starting_to_fly << " ILAND " << is_landing << " XY: " << pos_x << " " << pos_y << " DC " << decision_timer << " STT: " << state_timer << std::endl; + // std::cout << "ALT: " << altitude << std::endl; + // std::cout << (int)state << " ISTART " << is_starting_to_fly << " ILAND " << is_landing << " XY: " << pos_x << " " << pos_y << " DC " << decision_timer << " STT: " << state_timer << std::endl; state_timer += delta_s; decision_timer -= delta_s; @@ -52,7 +59,7 @@ void Bird::Update(double delta_s, const SDL_FPoint& player_pos) { eating_timer += delta_s; if (eating_timer >= 3.0) { set_State(BirdState::START_TO_FLY, 0.0); - PickFlyTarget(player_pos); + pick_FlyTarget(player_pos); return; } } @@ -99,13 +106,35 @@ void Bird::Update(double delta_s, const SDL_FPoint& player_pos) { if (dist > 0.4) { float move = speed * delta_s; if (move > dist) move = dist; - pos_x += (dx / dist) * move; - pos_y += (dy / dist) * move; + + float next_px = pos_x + (dx / dist) * move; + float next_py = pos_y + (dy / dist) * move; + bool can_walk = false; + if (Map::is_FreePosition({ + next_px - tile_size / 2, + pos_y - tile_size / 2, + tile_size, + tile_size + })) { + pos_x = next_px; + can_walk = true; + } + if (Map::is_FreePosition({ + pos_x - tile_size / 2, + next_py - tile_size / 2, + tile_size, + tile_size + })) { + pos_y += (dy / dist) * move; + can_walk = true; + } + if (!can_walk) + set_State(BirdState::IDLE, 0.4); if (fabsf(dx) > 0.01f) facing_left = (dx < 0.0f); } else { - set_State(BirdState::IDLE, 0.0); - return; + std::cout << "BIRD WALK REACHED GOAL" << std::endl; + set_State(BirdState::IDLE, 0.4); } } else @@ -141,12 +170,11 @@ void Bird::Update(double delta_s, const SDL_FPoint& player_pos) { float y_offset_delta = -((takeoff_progress + y_offset) - takeoff_prev_y_offset); takeoff_prev_y_offset = takeoff_progress + y_offset; - std::cout << "FACIN A: " << facing_left << std::endl; facing_left = ( pos_x+x_offset_delta - pos_x < 0.0f); - std::cout << "FACIN B: " << facing_left << std::endl; pos_x += x_offset_delta; pos_y += y_offset_delta; + altitude += y_offset_delta*-1; // If finished takeoff, align for straight flight if (takeoff_progress >= FLIGHT_HEIGHT) { @@ -159,7 +187,7 @@ void Bird::Update(double delta_s, const SDL_FPoint& player_pos) { facing_left = (target_pos.x - pos_x < 0.0f); } - std::cout << "DEL: " << x_offset_delta << " " << y_offset_delta << std::endl; + // std::cout << "DEL: " << x_offset_delta << " " << y_offset_delta << std::endl; } // Handle landing animation with circular arc (position-based) else if (is_landing) { @@ -169,6 +197,7 @@ void Bird::Update(double delta_s, const SDL_FPoint& player_pos) { if (landing_progress >= FLIGHT_HEIGHT) { // if (fabs(target_pos.y - landing_start_y) >= FLIGHT_HEIGHT+1) { std::cout << "STOP FLYING! START LANDING" << std::endl; + altitude = 0.0f; set_State(BirdState::STOP_FLYING, 0.0); return; } @@ -197,6 +226,7 @@ void Bird::Update(double delta_s, const SDL_FPoint& player_pos) { if (fabsf(dx) > 0.01f) { facing_left = (dx < 0.0f); } + altitude -= y_offset_delta; pos_x += x_offset_delta; pos_y += y_offset_delta; } @@ -238,10 +268,13 @@ void Bird::set_Position(SDL_FPoint point) { void Bird::set_State(BirdState new_state, double dec_timer) { + std::cout << "BIRD SET STATE " << (int)new_state << std::endl; decision_timer = dec_timer; + /* if (state == new_state) return; + */ state = new_state; state_timer = 0.0f; @@ -268,13 +301,13 @@ void Bird::set_State(BirdState new_state, double dec_timer) { case BirdState::EATING: current_frame = 0; - //eating_timer = 0.0; set_Animation(3, 3, 0.15); break; case BirdState::START_TO_FLY: { current_frame = 0; is_starting_to_fly = true; + altitude = 0.0f; set_Animation(4, 8, 0.06); decision_timer = 8*0.06; takeoff_progress = 0.0f; @@ -322,6 +355,7 @@ void Bird::Decide(const SDL_FPoint& player_pos) { float dy = pos_y - player_pos.y; float dist_sq = dx * dx + dy * dy; + std::cout << "START DECIED\n"; // If too far, fly closer if ( dist_sq > MAX_RADIUS * MAX_RADIUS && state != BirdState::FLYING && @@ -329,19 +363,21 @@ void Bird::Decide(const SDL_FPoint& player_pos) { state != BirdState::START_TO_FLY) { std::cout << "BIRD TARGET TOO FAR\n"; set_State(BirdState::START_TO_FLY, 0.0); - PickFlyTarget(player_pos); + pick_FlyTarget(player_pos); return; } if (state == BirdState::START_TO_FLY) { + std::cout << "FUU 1 " << std::endl; set_State(BirdState::FLYING, 0.0); return; } // Random behavior when close to player int choice = rand() % 100; - float duration = rand() % 80 * 0.1f + 1.1f; + float duration = rand() % 70 * 0.1f + 1.1f; if (state == BirdState::STOP_FLYING) { + std::cout << "FUU 2 " << std::endl; set_State(BirdState::IDLE, duration); return; } @@ -351,22 +387,27 @@ void Bird::Decide(const SDL_FPoint& player_pos) { } else if (choice < 50) { set_State(BirdState::WALKING, duration); - PickGroundTarget(player_pos); + pick_GroundTarget(player_pos); } else if (choice < 75) { set_State(BirdState::IDLE, duration); } else { set_State(BirdState::START_TO_FLY, 0.0); - PickFlyTarget(player_pos); + std::cout << "PDECIDE PICK START\n"; + pick_FlyTarget(player_pos); + std::cout << "PDECIDE PICK END\n"; } + std::cout << "END\n"; } -void Bird::PickFlyTarget(const SDL_FPoint& player_pos) { +void Bird::pick_FlyTarget(const SDL_FPoint& player_pos) { const float MIN_DIST = MAX_RADIUS; // minimum distance from current position float angle, radius, dx, dy, dist_sq; - do { + constexpr int max_attempts = 100; + + for (int i = 0; i < max_attempts; ++i) { angle = (rand() % 628) / 100.0f; // 0 to ~2*PI radius = MIN_RADIUS + (rand() % static_cast<int>(MAX_RADIUS - MIN_RADIUS)); @@ -381,11 +422,35 @@ void Bird::PickFlyTarget(const SDL_FPoint& player_pos) { dy = target_pos.y - pos_y; dist_sq = dx * dx + dy * dy; - } while (dist_sq < MIN_DIST * MIN_DIST); // ensure minimum distance + if (!Map::is_FreePosition({ + target_pos.x - tile_size / 2, + target_pos.y - tile_size / 2, + tile_size, + tile_size + })) + dist_sq = MIN_DIST*MIN_DIST+1; + + if (dist_sq >= MIN_DIST * MIN_DIST) + return; + }; + set_State(BirdState::IDLE, 0.8); } -void Bird::PickGroundTarget(const SDL_FPoint& player_pos) { - float offset = static_cast<float>((rand() % 64) - 32); // -32 to +32 - target_pos.x = player_pos.x + offset; - target_pos.y = player_pos.y; +void Bird::pick_GroundTarget(const SDL_FPoint& player_pos) { + constexpr int max_attempts = 100; + + for (int i = 0; i < max_attempts; ++i) { + float offset_x= static_cast<float>((rand() % 64) - 32); // -32 to +32 + float offset_y= static_cast<float>((rand() % 64) - 32); // -32 to +32 + target_pos.x = player_pos.x + offset_x; + target_pos.y = player_pos.y + offset_y; + if (Map::is_FreePosition({ + target_pos.x - tile_size / 2, + target_pos.y - tile_size / 2, + tile_size, + tile_size + })) + return; + }; + set_State(BirdState::IDLE, 0.8); } diff --git a/src/bird/bird.hpp b/src/bird/bird.hpp index c683fe3..e5456c6 100644 --- a/src/bird/bird.hpp +++ b/src/bird/bird.hpp @@ -1,5 +1,10 @@ #pragma once +#include <SDL3/SDL.h> +#include <cstdint> +#include <vector> +#include <atomic> + static constexpr float MIN_RADIUS = 124.f; static constexpr float MAX_RADIUS = 164.f; static constexpr float FLY_SPEED = 42.f; @@ -16,19 +21,23 @@ enum class BirdState { ATTACK // 6 }; -#include <SDL3/SDL.h> -#include <cstdint> - class Bird { public: + static std::vector<Bird*> birds; + bool drawn; + float altitude = 0.0f; + + float pos_x = 0; + float pos_y = 0; + Bird(float x, float y); static bool Init(SDL_Renderer*); void Update(double delta_s, const SDL_FPoint& player_pos); void Decide(const SDL_FPoint& player_pos); - void PickFlyTarget(const SDL_FPoint& player_pos); - void PickGroundTarget(const SDL_FPoint& player_pos); + void pick_FlyTarget(const SDL_FPoint& player_pos); + void pick_GroundTarget(const SDL_FPoint& player_pos); void Render(SDL_Renderer* renderer); @@ -39,19 +48,19 @@ public: BirdState get_State() const; private: + static std::atomic<std::uint64_t> next_id; + std::uint64_t id; + + void set_Animation(int row, int frames, double frame_time); static SDL_Texture* texture; - float pos_x = 0; - float pos_y = 0; - SDL_FPoint velocity{0.f, 0.f}; SDL_FPoint target_pos{0.f, 0.f}; double state_timer = 0.0; double decision_timer = 0.0; - double eating_timer = 0.0; bool is_landing = false; bool is_starting_to_fly = false; diff --git a/src/character/character.cpp b/src/character/character.cpp index 0127f60..ed38916 100644 --- a/src/character/character.cpp +++ b/src/character/character.cpp @@ -305,9 +305,6 @@ 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); } /* diff --git a/src/map/map.cpp b/src/map/map.cpp index 737af21..31980fa 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -10,6 +10,7 @@ #include "building/building.hpp" #include "game/game.hpp" #include "farm/farm.hpp" +#include "bird/bird.hpp" namespace Map { @@ -693,6 +694,9 @@ namespace Map { float character_collider_x = player.collider_world.x; // - player.collider.w*0.5; float character_collider_y = player.collider_world.y; // - player.collider.h*0.5; + for (Bird* bird : Bird::birds) + bird->drawn = false; + for (size_t i = 0; i < Map::tile_map.size(); ++i) { TileMap& tilemap = Map::tile_map[i]; @@ -707,6 +711,7 @@ namespace Map { // Render Character if no object is hiding it player_behind = false; + // DRAW BIRD for (TileObject& o : tilemap.objects) { Object* object = Object::get_ObjectById(o.object_id); // o = relative position, @@ -821,6 +826,23 @@ namespace Map { } j++; } + for (Bird* bird : Bird::birds) { + if (bird->drawn) + continue; + if ( static_cast<int>(bird->pos_x/Tile::tile_size) != x_i || + static_cast<int>((bird->pos_y+bird->altitude)/Tile::tile_size) != y_i) + continue; + + bird->Render(renderer); + bird->drawn = true; + } + } + for (Bird* bird : Bird::birds) { + if (bird->drawn) + continue; + + bird->Render(renderer); + bird->drawn = true; } }