Skip to content
Snippets Groups Projects
Unverified Commit ed0f6784 authored by David Hermann's avatar David Hermann
Browse files

Implementing animated movement of units (tile-based)

- Creating `Box2dHelper.hpp` with inline converting helper functions of Box2D coordinates, tiles and pixels
- Outsourcing  `PIXELS_PER_METER` into `Box2dHelper.hpp`
- Setting `PIXELS_PER_METER` from 32 to 16 (tile length = 1 meter)
parent f4ad0309
No related branches found
No related tags found
No related merge requests found
namespace advanced_wars
{
constexpr float PIXELS_PER_METER = 16.0f;
/// Tile → Pixel
inline int tileToPixel(int tile)
{
return tile * 16;
}
/// Pixel → Tile
inline int pixelToTile(int pixel)
{
return pixel / 16;
}
/// Box2D (Meter) → Pixel
inline float worldToPixel(float world)
{
return world * PIXELS_PER_METER;
}
/// Pixel → Box2D (Meter)
inline float pixelToWorld(float pixel)
{
return pixel / PIXELS_PER_METER;
}
/// Tile → Box2D (Meter) (Oberer linker Punkt des Tiles)
inline float tileToWorld(int tile)
{
return pixelToWorld(tileToPixel(tile));
}
/// Box2D (Meter) → Tile (Berechnung über Pixel)
inline int worldToTile(float world)
{
return pixelToTile(worldToPixel(world));
}
}
\ No newline at end of file
#include "Bullet.hpp" #include "Bullet.hpp"
#include "Box2dHelper.hpp"
#include "Engine.hpp" #include "Engine.hpp"
#include "UnitContactListener.hpp" #include "UnitContactListener.hpp"
#include <iostream> #include <iostream>
......
...@@ -8,10 +8,6 @@ ...@@ -8,10 +8,6 @@
namespace advanced_wars namespace advanced_wars
{ {
// Wir definieren einen Umrechnungsfaktor, um zwischen Pixeln und Box2D-Metern umzurechnen.
// Passe diesen Wert an deine Spielwelt an. Hier gehen wir von 32 Pixel pro Meter aus.
constexpr float PIXELS_PER_METER = 32.0f;
class Bullet class Bullet
{ {
public: public:
......
#include "Level.hpp" #include "Level.hpp"
#include "Box2dHelper.hpp"
#include "Building.hpp" #include "Building.hpp"
#include "Effect.hpp" #include "Effect.hpp"
#include "Engine.hpp" #include "Engine.hpp"
...@@ -241,8 +242,7 @@ void Level::handleEvent(Engine& engine, SDL_Event& event) ...@@ -241,8 +242,7 @@ void Level::handleEvent(Engine& engine, SDL_Event& event)
} }
else else
{ {
m_units.at(m_selectedUnit)->moveToTile(tileX, tileY);
m_units.at(m_selectedUnit)->updatePosition(tileX, tileY);
} }
} }
else else
...@@ -309,6 +309,7 @@ void Level::render(Engine& engine) ...@@ -309,6 +309,7 @@ void Level::render(Engine& engine)
// Units // Units
for (auto& [id, unit] : m_units) for (auto& [id, unit] : m_units)
{ {
unit->update();
unit->render(engine, RENDERING_SCALE); unit->render(engine, RENDERING_SCALE);
} }
......
#include "Unit.hpp" #include "Unit.hpp"
#include "Box2dHelper.hpp"
#include "Bullet.hpp" #include "Bullet.hpp"
#include "UnitContactListener.hpp" #include "UnitContactListener.hpp"
#include <iostream> #include <iostream>
...@@ -51,6 +52,8 @@ void Unit::setWorld(b2World* world) ...@@ -51,6 +52,8 @@ void Unit::setWorld(b2World* world)
void Unit::render(Engine& engine, int scale) void Unit::render(Engine& engine, int scale)
{ {
b2Vec2 pos = m_body->GetPosition();
Spritesheet* spritesheet = engine.getSpritesheet(); Spritesheet* spritesheet = engine.getSpritesheet();
int step = engine.getStage() % spritesheet->getUnitTextures() int step = engine.getStage() % spritesheet->getUnitTextures()
...@@ -58,46 +61,35 @@ void Unit::render(Engine& engine, int scale) ...@@ -58,46 +61,35 @@ void Unit::render(Engine& engine, int scale)
.at(static_cast<int>(m_id)) .at(static_cast<int>(m_id))
.at(static_cast<int>(m_state)) .at(static_cast<int>(m_state))
.second; .second;
SDL_Rect src;
SDL_Rect dst;
if (m_state == UnitState::IDLE || m_state == UnitState::UNAVAILABLE) if (m_state == UnitState::IDLE || m_state == UnitState::UNAVAILABLE)
{ {
SDL_Rect src;
src.x = step * spritesheet->getUnitWidth(); src.x = step * spritesheet->getUnitWidth();
src.y = 0; src.y = 0;
src.w = spritesheet->getUnitWidth(); src.w = spritesheet->getUnitWidth();
src.h = spritesheet->getUnitHeight(); src.h = spritesheet->getUnitHeight();
SDL_Rect dst; dst.x = worldToTile(pos.x) * spritesheet->getUnitWidth() * scale;
dst.x = m_x * spritesheet->getUnitWidth() * scale; dst.y = worldToTile(pos.y) * spritesheet->getUnitHeight() * scale;
dst.y = m_y * spritesheet->getUnitHeight() * scale;
dst.w = spritesheet->getUnitWidth() * scale; dst.w = spritesheet->getUnitWidth() * scale;
dst.h = spritesheet->getUnitHeight() * scale; dst.h = spritesheet->getUnitHeight() * scale;
SDL_RenderCopyEx(
engine.renderer(),
spritesheet->getUnitTextures()
.at(static_cast<int>(m_faction))
.at(static_cast<int>(m_id))
.at(static_cast<int>(m_state))
.first,
&src, &dst, 0, NULL, SDL_FLIP_NONE);
} }
else else
{ {
// The moving states have a resolution of 24x24 instead of 16x16 and need to // The moving states have a resolution of 24x24 instead of 16x16 and need to
// be handled separately // be handled separately
SDL_Rect src;
src.x = step * spritesheet->getUnitMovingWidth(); src.x = step * spritesheet->getUnitMovingWidth();
src.y = 0; src.y = 0;
src.w = spritesheet->getUnitMovingWidth(); src.w = spritesheet->getUnitMovingWidth();
src.h = spritesheet->getUnitMovingHeight(); src.h = spritesheet->getUnitMovingHeight();
SDL_Rect dst; dst.x = ((worldToTile(pos.x) * spritesheet->getUnitWidth()) - 4) * scale;
dst.x = ((m_x * spritesheet->getUnitWidth()) - 4) * scale; dst.y = ((worldToTile(pos.y) * spritesheet->getUnitHeight()) - 4) * scale;
dst.y = ((m_y * spritesheet->getUnitHeight()) - 4) * scale;
dst.w = spritesheet->getUnitMovingWidth() * scale; dst.w = spritesheet->getUnitMovingWidth() * scale;
dst.h = spritesheet->getUnitMovingHeight() * scale; dst.h = spritesheet->getUnitMovingHeight() * scale;
}
SDL_RenderCopyEx( SDL_RenderCopyEx(
engine.renderer(), engine.renderer(),
...@@ -108,7 +100,6 @@ void Unit::render(Engine& engine, int scale) ...@@ -108,7 +100,6 @@ void Unit::render(Engine& engine, int scale)
.first, .first,
&src, &dst, 0, NULL, SDL_FLIP_NONE); &src, &dst, 0, NULL, SDL_FLIP_NONE);
} }
}
void Unit::attack(Unit& enemy) void Unit::attack(Unit& enemy)
{ {
...@@ -287,4 +278,62 @@ int Unit::getMapId() ...@@ -287,4 +278,62 @@ int Unit::getMapId()
return this->m_mapId; return this->m_mapId;
} }
void Unit::moveToTile(int targetX, int targetY)
{
// Speichere die Ziel-Tile-Koordinaten
m_targetTileX = targetX;
m_targetTileY = targetY;
// Zielposition in Meter umrechnen (Mitte des Tiles)
float worldTargetX = (targetX * 16 + 8) / PIXELS_PER_METER;
float worldTargetY = (targetY * 16 + 8) / PIXELS_PER_METER;
// Aktuelle Position abrufen
b2Vec2 currentPos = m_body->GetPosition();
// Differenz berechnen
float deltaX = worldTargetX - currentPos.x;
float deltaY = worldTargetY - currentPos.y;
// Distanz berechnen
float distance = std::sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance < 0.1f)
{
return; // Falls schon fast da, nichts tun
}
// Normierte Richtung berechnen
float directionX = deltaX / distance;
float directionY = deltaY / distance;
// Geschwindigkeit setzen
float speed = 2.0f; // Tiles pro Sekunde
m_body->SetLinearVelocity(b2Vec2(directionX * speed, directionY * speed));
// State setzen
calcState(targetX, targetY);
}
void Unit::update()
{
b2Vec2 pos = m_body->GetPosition();
// Berechne aktuelle Tile-Position
int currentTileX = static_cast<int>((pos.x * PIXELS_PER_METER) / 16);
int currentTileY = static_cast<int>((pos.y * PIXELS_PER_METER) / 16);
/* if (getMapId() == 66)
{
std::cout << "Current Tile: " << currentTileX << ", " << currentTileY << std::endl;
} */
// Prüfe, ob wir am Ziel sind
if (currentTileX == m_targetTileX && currentTileY == m_targetTileY)
{
m_body->SetLinearVelocity(b2Vec2(0, 0)); // Bewegung stoppen
m_x = m_targetTileX; // Stelle sicher, dass die Unit auf dem richtigen Tile registriert
// ist
m_y = m_targetTileY;
m_state = UnitState::IDLE;
}
}
} // namespace advanced_wars } // namespace advanced_wars
\ No newline at end of file
...@@ -201,6 +201,17 @@ class Unit ...@@ -201,6 +201,17 @@ class Unit
*/ */
int getMapId(); int getMapId();
/**
* @brief Aktualisiert den Zustand der Unit.
*
* Diese Methode prüft, ob sich die Unit gerade bewegt und ob sie nahe genug am Ziel ist.
* Ist das der Fall, wird die Bewegung gestoppt, und die Tile-Koordinaten werden
* aktualisiert.
*/
void update();
void moveToTile(int targetX, int targetY);
private: private:
UnitFaction m_faction; UnitFaction m_faction;
UnitId m_id; UnitId m_id;
...@@ -209,6 +220,9 @@ class Unit ...@@ -209,6 +220,9 @@ class Unit
b2World* m_world = nullptr; b2World* m_world = nullptr;
int m_mapId = -1; int m_mapId = -1;
int m_targetTileX;
int m_targetTileY;
int m_maxHealth; // max_health required for damage_scaling int m_maxHealth; // max_health required for damage_scaling
int m_range; int m_range;
int m_fuel; int m_fuel;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment