Skip to content

Commit

Permalink
Merge pull request #8 from runvs/AnimationSpeedDependentOnSlope
Browse files Browse the repository at this point in the history
Set Animation Speed depending on slope
  • Loading branch information
Laguna1989 authored Jul 7, 2023
2 parents 5730c90 + 63df0d5 commit ee7293d
Show file tree
Hide file tree
Showing 23 changed files with 449 additions and 523 deletions.
2 changes: 1 addition & 1 deletion assets/maps/map_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Expand Down
1 change: 1 addition & 0 deletions ext/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ include(FetchContent)
message(STATUS "Fetching external libraries started")
add_subdirectory(asio)
add_subdirectory(box2d)
add_subdirectory(catch2)
add_subdirectory(imgui)
add_subdirectory(openalpp)
add_subdirectory(tileson)
Expand Down
9 changes: 9 additions & 0 deletions ext/catch2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
message(STATUS "Fetching catch2")
include(FetchContent)

FetchContent_Declare(
catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2
GIT_TAG v2.13.8
)
FetchContent_MakeAvailable(catch2)
10 changes: 9 additions & 1 deletion impl/game_client_lib/state_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <vector2.hpp>
#include <imgui.h>
#include <memory>
#include <ostream>

void StateGame::onCreate()
{
Expand Down Expand Up @@ -427,14 +426,23 @@ std::shared_ptr<InternalStateManager> StateGame::getStateManager()
{
return m_internalStateManager;
}

std::shared_ptr<ServerConnection> StateGame::getServerConnection() { return m_serverConnection; }

std::shared_ptr<Terrain> StateGame::getTerrain() { return m_terrain; }

std::shared_ptr<TerrainRenderer> StateGame::getTerrainRenderer() { return m_terrainRenderer; }

std::shared_ptr<PlacementManager> StateGame::getPlacementManager() { return m_placementManager; }

std::shared_ptr<UnitInfoCollection> StateGame::getUnitInfo() { return m_unitInfo; }

int StateGame::getRound() { return m_round; }

std::shared_ptr<jt::ObjectGroup<Unit>> StateGame::getUnits() { return m_units; }

std::shared_ptr<jt::ObjectGroup<Critter>> StateGame::getCritters() { return m_critters; }

void StateGame::flashUnitsForUpgrade(const std::string& unitType)
{
for (auto& u : *m_units) {
Expand Down
36 changes: 23 additions & 13 deletions impl/game_client_lib/unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ void Unit::doUpdate(float const elapsed)
{
m_glow->setPosition(m_anim->getPosition());
m_glow->update(elapsed);
m_anim->update(elapsed);
auto animationSpeedFactor = 1.0f;
if (m_anim->getCurrentAnimationName() == "walk") {
animationSpeedFactor = convertSlopeToSpeedFactor(m_slope);
}
m_anim->update(elapsed * animationSpeedFactor);
m_levelText->setPosition(m_anim->getPosition() + jt::Vector2f { -4.0f, -6.0f });
m_levelText->update(elapsed);

Expand Down Expand Up @@ -99,36 +103,37 @@ void Unit::doDraw() const
}
}

void Unit::updateState(UnitServerToClientData const& props)
void Unit::updateState(UnitServerToClientData const& data)
{
if (props.unitID != m_unitID) {
if (data.unitID != m_unitID) {
getGame()->logger().error(
"updateState called with invalid unit id", { "Unit", "updateState" });
return;
}
setOffset({ props.offsetX, props.offsetY });
setPosition({ props.positionX, props.positionY });
if (props.playerID == 0) {
setOffset({ data.offsetX, data.offsetY });
setPosition({ data.positionX, data.positionY });
if (data.playerID == 0) {
m_anim->setColor(GP::ColorPlayer0());
} else {
m_anim->setColor(GP::ColorPlayer1());
}
m_hp = props.hpCurrent;
m_hp = data.hpCurrent;

if (props.unitAnim.has_value()) {
m_newAnimName = props.unitAnim.value();
if (data.unitAnim.has_value()) {
m_newAnimName = data.unitAnim.value();
}

turnUnitIntoDirection(m_anim, props.unitWalkingRight);
turnUnitIntoDirection(m_anim, data.unitWalkingRight);

if (props.level != 1) {
if (data.level != 1) {

m_level = props.level;
m_level = data.level;
if (m_level != 1) {
m_levelText->setText(std::to_string(m_level));
}
}
m_exp = props.experience;
m_exp = data.experience;
m_slope = data.slope;
}

void Unit::playAnimation()
Expand Down Expand Up @@ -193,13 +198,15 @@ void Unit::setIDs(int uid, int pid)
int Unit::getPlayerID() const { return m_playerID; }

bool Unit::isUnitAlive() const { return m_hp > 0; }

bool Unit::isMouseOver() const
{
auto const mp = getGame()->input().mouse()->getMousePositionWorld();
jt::Rectf const rect { m_position.x + m_offset.x, m_position.y + m_offset.y, 16.0f, 16.0f };

return jt::MathHelper::checkIsIn(rect, mp);
}

UnitInfo const& Unit::getInfo() const { return m_info; }

int Unit::getLevel() const { return m_level; }
Expand All @@ -209,10 +216,13 @@ void Unit::resetForNewRound()
m_anim->play("idle", 0, true);
m_animTimeUntilBackToIdle = -1.0f;
}

void Unit::flash() { m_anim->flash(0.4f, jt::colors::Green); }

void Unit::setHighlight(bool v) { m_glowActive = v; }

int Unit::getExp() const { return m_exp; }

int Unit::getExpForLevelUp() const
{
auto info = getUnitInfoWithLevelAndUpgrades(m_info, m_level, {});
Expand Down
3 changes: 2 additions & 1 deletion impl/game_client_lib/unit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Unit : public jt::GameObject, public UnitInterface {
public:
explicit Unit(UnitInfo const& info);

void updateState(UnitServerToClientData const& props);
void updateState(UnitServerToClientData const& data);

void setPosition(jt::Vector2f const& pos);
jt::Vector2f getPosition() const;
Expand Down Expand Up @@ -81,6 +81,7 @@ class Unit : public jt::GameObject, public UnitInterface {
int m_exp { 0 };
std::vector<std::string> m_boughtUpgrades;
std::shared_ptr<jt::Bar> m_hpBar;
float m_slope { 0.0f };

void doCreate() override;
void doUpdate(float const elapsed) override;
Expand Down
29 changes: 29 additions & 0 deletions impl/game_common_lib/game_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,32 @@ jt::Color GP::ColorPlayer0() { return jt::ColorFactory::fromHexString("#5d7cd4")
jt::Color GP::ColorPlayer1() { return jt::ColorFactory::fromHexString("#f57979"); }

float GP::TimePerSimulationUpdate() { return 0.005f; }

float convertSlopeToSpeedFactor(float slope)
{
if (slope > 0) {
if (slope > 78.0f) {
return 0.3f;
} else if (slope > 75.0f) {
return 0.4f;
} else if (slope > 71.0f) {
return 0.5f;
} else if (slope > 60.0f) {
return 0.6f;
}
return 0.7f;
} else if (slope == 0) {
return 1.0f;
} else {
if (slope < -78.0f) {
return 1.6f;
} else if (slope < -75.0f) {
return 1.5f;
} else if (slope < -71.0f) {
return 1.4f;
} else if (slope < -60.0f) {
return 1.3f;
}
return 1.2f;
}
}
2 changes: 2 additions & 0 deletions impl/game_common_lib/game_properties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ class GP {
static float UnitExperienceForLevelUpExponent();
};

float convertSlopeToSpeedFactor(float slope);

#endif
1 change: 1 addition & 0 deletions impl/game_common_lib/json_keys.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ constexpr auto armor = "armor";
constexpr auto armorType = "armorTypes";

constexpr auto filename = "jsonfilename";
constexpr auto slope = "slope";

} // namespace jk

Expand Down
22 changes: 7 additions & 15 deletions impl/game_common_lib/map/terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ jt::Vector3f getNormalOfTriangleForPosition(
// value that can be used for an actual slope calculation when doing vector arithmetics
auto const convertHeightToZ = [&](auto const v) {
if (convertHeight) {
// conversion formula to map values of [0;terrainHeightMax] to degrees as follows:
// 0: 0 | 0.5: 14.0362 | 1: 26.565 | 1.5: 36.8699 | 2: 45 | 3: 56.3099 | 4: 63.4349 |
// 5: 68.19
return static_cast<float>(
v * 0.25 * terrainChunkSizeInPixel * 2 /*shift to center factor*/);
return static_cast<float>(v * terrainChunkSizeInPixel);
}
return v;
};
Expand All @@ -44,10 +40,10 @@ jt::Vector3f getNormalOfTriangleForPosition(
jt::Vector3f const c { 0, 0, convertHeightToZ(posHeight) };
auto const minXY = -terrainChunkSizeInPixelHalf;
auto const maxXY = terrainChunkSizeInPixelHalf - 1; // TODO check whether pixel 16 is an issue
jt::Vector3f const tl { minXY, minXY, convertHeightToZ(chunk.heightCorners[0]) };
jt::Vector3f const tr { maxXY, minXY, convertHeightToZ(chunk.heightCorners[1]) };
jt::Vector3f const bl { minXY, maxXY, convertHeightToZ(chunk.heightCorners[2]) };
jt::Vector3f const br { maxXY, maxXY, convertHeightToZ(chunk.heightCorners[3]) };
auto const tl = jt::Vector3f { minXY, minXY, convertHeightToZ(chunk.heightCorners[0]) };
auto const tr = jt::Vector3f { maxXY, minXY, convertHeightToZ(chunk.heightCorners[1]) };
auto const bl = jt::Vector3f { minXY, maxXY, convertHeightToZ(chunk.heightCorners[2]) };
auto const br = jt::Vector3f { maxXY, maxXY, convertHeightToZ(chunk.heightCorners[3]) };

// determine which triangle the position is in and calculate normal vector for it
int offX = static_cast<int>(pos.x) % terrainChunkSizeInPixel;
Expand Down Expand Up @@ -121,11 +117,8 @@ float Terrain::getSlopeAt(jt::Vector2f const& pos, jt::Vector2f const& dir) cons
if (normal.isZero() || (normal.x == 0 && normal.y == 0)) {
return 0.0f;
}
auto const v = jt::Vector3f { dir };
auto const np = normal * v.dot(normal);
auto const vp = v - np;
auto const slope = vp.angleDeg(v) * (v.x < 0 || v.y < 0 ? -1 : 1);
return slope;
auto const d3v = jt::Vector3f { dir };
return d3v.angleDeg(normal) - 90.0f;
}

float Terrain::getFieldHeight(jt::Vector2f const& pos) const
Expand Down Expand Up @@ -209,7 +202,6 @@ void Terrain::setChunks(Grid const& grid)
chunk.heightCorners[0] = left.heightCorners[1];
chunk.heightCorners[2] = left.heightCorners[3];
} else if (left.heightCenter < chunk.heightCenter) {
chunk.heightCenter = left.height + (chunk.height - left.height) / 2;
left.heightCorners[1] = chunk.heightCorners[0];
left.heightCorners[3] = chunk.heightCorners[2];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ void to_json(nlohmann::json& j, const UnitServerToClientData& d)
if (d.unitWalkingRight) {
j[jk::unitWalkingRight] = true;
}
if (d.slope != 0.0f) {
j[jk::slope] = d.slope;
}
}

void from_json(const nlohmann::json& j, UnitServerToClientData& d)
{
j.at(jk::unitID).get_to(d.unitID);
Expand Down Expand Up @@ -59,4 +63,7 @@ void from_json(const nlohmann::json& j, UnitServerToClientData& d)
j.at(jk::unitAnim).get_to(anim);
d.unitAnim = anim;
}
if (j.count(jk::slope) == 1) {
j.at(jk::slope).get_to(d.slope);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct UnitServerToClientData {
bool unitWalkingRight { false };

std::optional<std::string> unitAnim {};
float slope { 0.0f };
};

void to_json(nlohmann::json& j, const UnitServerToClientData& d);
Expand Down
26 changes: 2 additions & 24 deletions impl/game_server_lib/game_simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,31 +315,9 @@ std::weak_ptr<SimulationObjectInterface> GameSimulation::getClosestTargetTo(
return target;
}

float GameSimulation::getLocalSpeedFactorAt(jt::Vector2f const& pos, jt::Vector2f const& dir)
float GameSimulation::getLocalSlope(jt::Vector2f const& pos, jt::Vector2f const& dir)
{
auto const slope = m_world->getSlopeAt(pos, dir);
if (slope == 0.0f) {
return 1.0f;
}
if (slope > 0.0f && slope < 61.0f) {
// found acceptable curve with following input:
// 10 -> 0.95
// 20 -> 0.85
// 30 -> 0.7
// 45 -> 0.5
// 60 -> 0.2
return -0.000166516f * slope * slope - 0.00397695f * slope + 0.998285f;
}
if (slope > -61.0f && slope < 0.0f) {
// found acceptable curve with following input:
// -10 -> 1.09
// -20 -> 1.2
// -30 -> 1.4
// -45 -> 1.7
// -60 -> 2
return 0.0000983332f * slope * slope - 0.0122135f * slope + 0.957329f;
}
return 0.15f;
return m_world->getSlopeAt(pos, dir);
}

jt::Vector2f GameSimulation::getTerrainMappedFieldPosition(jt::Vector2f const& pos, int& x, int& y)
Expand Down
4 changes: 2 additions & 2 deletions impl/game_server_lib/game_simulation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ class GameSimulation : public WorldInfoInterface {
void addUnitUpgrade(UpgradeUnitData const& upg);

void performSimulation(SimulationResultSenderInterface& sender);

std::weak_ptr<SimulationObjectInterface> getClosestTargetTo(
const jt::Vector2f& pos, int playerId) override;
float getLocalSpeedFactorAt(jt::Vector2f const& pos, jt::Vector2f const& dir) override;
float getLocalSlope(jt::Vector2f const& pos, jt::Vector2f const& dir) override;
jt::Vector2f getTerrainMappedFieldPosition(jt::Vector2f const& pos, int& x, int& y) override;
float getTerrainMappedFieldHeight(jt::Vector2f const& pos) override;

Expand Down
5 changes: 4 additions & 1 deletion impl/game_server_lib/units/ai/ai_cannon.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ai_cannon.hpp"
#include <game_properties.hpp>
#include <map/terrain.hpp>
#include <math_helper.hpp>
#include <network_data/arrow_info.hpp>
Expand Down Expand Up @@ -28,7 +29,9 @@ void AiCannon::update(float elapsed, ServerUnit* unit, WorldInfoInterface& world
unit->setOffset(jt::Vector2f { 0.0f,
-world.getTerrainMappedFieldHeight(unit->getPosition() + terrainChunkSizeInPixelHalf)
* terrainHeightScalingFactor });
auto const speedFactor = world.getLocalSpeedFactorAt(unit->getPosition(), dir);
auto const slope = world.getLocalSlope(unit->getPosition(), dir);
unit->setCurrentSlope(slope);
auto const speedFactor = convertSlopeToSpeedFactor(slope);
float const speed = unit->getUnitInfoFull().movementSpeed * speedFactor;
unit->getPhysicsObject()->setVelocity(dir * speed);
unit->setAnim("walk");
Expand Down
5 changes: 4 additions & 1 deletion impl/game_server_lib/units/ai/ai_close_combat.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "ai_close_combat.hpp"
#include <close_combat_info.hpp>
#include <game_properties.hpp>
#include <map/terrain.hpp>
#include <math_helper.hpp>
#include <random/random.hpp>
Expand All @@ -26,7 +27,9 @@ void AiCloseCombat::update(float elapsed, ServerUnit* unit, WorldInfoInterface&
auto dir = target->getPosition() - unit->getPosition();
auto const dist = jt::MathHelper::length(dir);
jt::MathHelper::normalizeMe(dir);
auto const speedFactor = world.getLocalSpeedFactorAt(unit->getPosition(), dir);
auto const slope = world.getLocalSlope(unit->getPosition(), dir);
unit->setCurrentSlope(slope);
auto const speedFactor = convertSlopeToSpeedFactor(slope);
float speed = unit->getUnitInfoFull().movementSpeed * speedFactor;
auto const attackRange
= (unit->getUnitInfoFull().colliderRadius + target->getUnitInfoFull().colliderRadius)
Expand Down
5 changes: 4 additions & 1 deletion impl/game_server_lib/units/ai/ai_ranged_combat.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ai_ranged_combat.hpp"
#include <game_properties.hpp>
#include <map/terrain.hpp>
#include <math_helper.hpp>
#include <network_data/arrow_info.hpp>
Expand Down Expand Up @@ -28,7 +29,9 @@ void AiRangedCombat::update(float elapsed, ServerUnit* unit, WorldInfoInterface&
unit->setOffset(jt::Vector2f { 0.0f,
-world.getTerrainMappedFieldHeight(unit->getPosition() + terrainChunkSizeInPixelHalf)
* terrainHeightScalingFactor });
auto const speedFactor = world.getLocalSpeedFactorAt(unit->getPosition(), dir);
auto const slope = world.getLocalSlope(unit->getPosition(), dir);
unit->setCurrentSlope(slope);
auto const speedFactor = convertSlopeToSpeedFactor(slope);
float const speed = unit->getUnitInfoFull().movementSpeed * speedFactor;
unit->getPhysicsObject()->setVelocity(dir * speed);
unit->setAnim("walk");
Expand Down
Loading

0 comments on commit ee7293d

Please sign in to comment.