mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-13 01:20:34 +02:00
Hero movement speed and map scrolling speed now matches H3
This commit is contained in:
14
Global.h
14
Global.h
@ -442,6 +442,20 @@ namespace vstd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// c++17: makes a to fit the range <b, c>
|
||||||
|
template <typename t1, typename t2, typename t3>
|
||||||
|
t1 clamp(const t1 &value, const t2 &low, const t3 &high)
|
||||||
|
{
|
||||||
|
if ( value > high)
|
||||||
|
return high;
|
||||||
|
|
||||||
|
if ( value < low)
|
||||||
|
return low;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//makes a to fit the range <b, c>
|
//makes a to fit the range <b, c>
|
||||||
template <typename t1, typename t2, typename t3>
|
template <typename t1, typename t2, typename t3>
|
||||||
t1 &abetween(t1 &a, const t2 &b, const t3 &c)
|
t1 &abetween(t1 &a, const t2 &b, const t3 &c)
|
||||||
|
@ -592,20 +592,22 @@ void CAdvMapInt::show(SDL_Surface * to)
|
|||||||
|
|
||||||
void CAdvMapInt::handleMapScrollingUpdate()
|
void CAdvMapInt::handleMapScrollingUpdate()
|
||||||
{
|
{
|
||||||
int scrollSpeed = static_cast<int>(settings["adventure"]["scrollSpeed"].Float());
|
uint32_t timePassed = GH.mainFPSmng->getElapsedMilliseconds();
|
||||||
|
double scrollSpeedPixels = settings["adventure"]["scrollSpeedPixels"].Float();
|
||||||
|
int32_t scrollDistance = static_cast<int32_t>(scrollSpeedPixels * timePassed / 1000);
|
||||||
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
|
//if advmap needs updating AND (no dialog is shown OR ctrl is pressed)
|
||||||
|
|
||||||
if(scrollingDir & LEFT)
|
if(scrollingDir & LEFT)
|
||||||
terrain->moveViewBy(Point(-scrollSpeed, 0));
|
terrain->moveViewBy(Point(-scrollDistance, 0));
|
||||||
|
|
||||||
if(scrollingDir & RIGHT)
|
if(scrollingDir & RIGHT)
|
||||||
terrain->moveViewBy(Point(+scrollSpeed, 0));
|
terrain->moveViewBy(Point(+scrollDistance, 0));
|
||||||
|
|
||||||
if(scrollingDir & UP)
|
if(scrollingDir & UP)
|
||||||
terrain->moveViewBy(Point(0, -scrollSpeed));
|
terrain->moveViewBy(Point(0, -scrollDistance));
|
||||||
|
|
||||||
if(scrollingDir & DOWN)
|
if(scrollingDir & DOWN)
|
||||||
terrain->moveViewBy(Point(0, +scrollSpeed));
|
terrain->moveViewBy(Point(0, +scrollDistance));
|
||||||
|
|
||||||
if(scrollingDir)
|
if(scrollingDir)
|
||||||
{
|
{
|
||||||
|
@ -396,8 +396,7 @@ std::shared_ptr<IImage> MapRendererObjects::getImage(const IMapRendererContext &
|
|||||||
if(animation->size(groupIndex) == 0)
|
if(animation->size(groupIndex) == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
size_t frameCounter = context.getAnimationTime() / context.getAnimationPeriod();
|
size_t frameIndex = context.objectImageIndex(obj->id, animation->size(groupIndex));
|
||||||
size_t frameIndex = frameCounter % animation->size(groupIndex);
|
|
||||||
|
|
||||||
return animation->getImage(frameIndex, groupIndex);
|
return animation->getImage(frameIndex, groupIndex);
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,8 @@ public:
|
|||||||
/// returns object animation transparency. IF set to 0, object will not be visible
|
/// returns object animation transparency. IF set to 0, object will not be visible
|
||||||
virtual double objectTransparency(ObjectInstanceID objectID) const = 0;
|
virtual double objectTransparency(ObjectInstanceID objectID) const = 0;
|
||||||
|
|
||||||
/// returns how long should each frame of animation be visible, in milliseconds
|
/// returns animation frame for selected object
|
||||||
virtual uint32_t getAnimationPeriod() const = 0;
|
virtual size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const = 0;
|
||||||
|
|
||||||
/// returns total animation time since creation of this context
|
|
||||||
virtual uint32_t getAnimationTime() const = 0;
|
|
||||||
|
|
||||||
/// returns size of ouput tile, in pixels. 32x32 for "standard" map, may be smaller for world view mode
|
/// returns size of ouput tile, in pixels. 32x32 for "standard" map, may be smaller for world view mode
|
||||||
virtual Point getTileSize() const = 0;
|
virtual Point getTileSize() const = 0;
|
||||||
|
@ -166,19 +166,24 @@ const CGPath * MapRendererContext::currentPath() const
|
|||||||
return &LOCPLINT->paths.getPath(hero);
|
return &LOCPLINT->paths.getPath(hero);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MapRendererContext::getAnimationPeriod() const
|
size_t MapRendererContext::objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const
|
||||||
{
|
{
|
||||||
|
assert(groupSize > 0);
|
||||||
|
if (groupSize == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// H3 timing for adventure map objects animation is 180 ms
|
// H3 timing for adventure map objects animation is 180 ms
|
||||||
// Terrain animations also use identical interval, however those are only present in HotA and/or HD Mod
|
// Terrain animations also use identical interval, however those are only present in HotA and/or HD Mod
|
||||||
// TODO: duration of fade-in/fade-out for teleport, entering/leaving boat, removal of objects
|
size_t baseFrameTime = 180;
|
||||||
// TOOD: duration of hero movement animation, frame timing of hero movement animation, effect of hero speed option
|
|
||||||
// TOOD: duration of enemy hero movement animation, frame timing of enemy hero movement animation, effect of enemy hero speed option
|
|
||||||
return 180;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MapRendererContext::getAnimationTime() const
|
// hero movement animation always plays at ~50ms / frame
|
||||||
{
|
// in-game setting only affect movement across screen
|
||||||
return animationTime;
|
if (movementAnimation && movementAnimation->target == objectID)
|
||||||
|
baseFrameTime = 50;
|
||||||
|
|
||||||
|
size_t frameCounter = animationTime / baseFrameTime;
|
||||||
|
size_t frameIndex = frameCounter % groupSize;
|
||||||
|
return frameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point MapRendererContext::getTileSize() const
|
Point MapRendererContext::getTileSize() const
|
||||||
@ -193,14 +198,19 @@ bool MapRendererContext::showGrid() const
|
|||||||
|
|
||||||
void MapViewController::setViewCenter(const int3 & position)
|
void MapViewController::setViewCenter(const int3 & position)
|
||||||
{
|
{
|
||||||
model->setViewCenter(Point(position.x, position.y) * model->getSingleTileSize());
|
assert(context->isInMap(position));
|
||||||
model->setLevel(position.z);
|
setViewCenter(Point(position) * model->getSingleTileSize(), position.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapViewController::setViewCenter(const Point & position, int level)
|
void MapViewController::setViewCenter(const Point & position, int level)
|
||||||
{
|
{
|
||||||
model->setViewCenter(position);
|
Point betterPosition = {
|
||||||
model->setLevel(level);
|
vstd::clamp(position.x, 0, context->getMapSize().x * model->getSingleTileSize().x),
|
||||||
|
vstd::clamp(position.y, 0, context->getMapSize().y * model->getSingleTileSize().y)
|
||||||
|
};
|
||||||
|
|
||||||
|
model->setViewCenter(betterPosition);
|
||||||
|
model->setLevel(vstd::clamp(level, 0, context->getMapSize().z));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapViewController::setTileSize(const Point & tileSize)
|
void MapViewController::setTileSize(const Point & tileSize)
|
||||||
@ -452,14 +462,16 @@ void MapViewController::update(uint32_t timeDelta)
|
|||||||
{
|
{
|
||||||
static const double fadeOutDuration = 1.0;
|
static const double fadeOutDuration = 1.0;
|
||||||
static const double fadeInDuration = 1.0;
|
static const double fadeInDuration = 1.0;
|
||||||
static const double heroMoveDuration = 1.0;
|
|
||||||
static const double heroTeleportDuration = 1.0;
|
static const double heroTeleportDuration = 1.0;
|
||||||
|
|
||||||
//FIXME: remove code duplication?
|
//FIXME: remove code duplication?
|
||||||
|
|
||||||
if (context->movementAnimation)
|
if (context->movementAnimation)
|
||||||
{
|
{
|
||||||
context->movementAnimation->progress += heroMoveDuration * timeDelta / 1000;
|
// TODO: enemyMoveTime
|
||||||
|
double heroMoveTime = settings["adventure"]["heroMoveTime"].Float();
|
||||||
|
|
||||||
|
context->movementAnimation->progress += timeDelta / heroMoveTime;
|
||||||
|
|
||||||
Point positionFrom = Point(context->movementAnimation->tileFrom) * model->getSingleTileSize();
|
Point positionFrom = Point(context->movementAnimation->tileFrom) * model->getSingleTileSize();
|
||||||
Point positionDest = Point(context->movementAnimation->tileDest) * model->getSingleTileSize();
|
Point positionDest = Point(context->movementAnimation->tileDest) * model->getSingleTileSize();
|
||||||
@ -503,7 +515,7 @@ void MapViewController::update(uint32_t timeDelta)
|
|||||||
}
|
}
|
||||||
|
|
||||||
context->animationTime += timeDelta;
|
context->animationTime += timeDelta;
|
||||||
context->tileSize =model->getSingleTileSize();
|
context->tileSize = model->getSingleTileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapViewController::onObjectFadeIn(const CGObjectInstance * obj)
|
void MapViewController::onObjectFadeIn(const CGObjectInstance * obj)
|
||||||
@ -539,8 +551,17 @@ void MapViewController::onHeroMoved(const CGHeroInstance * obj, const int3 & fro
|
|||||||
{
|
{
|
||||||
assert(!context->movementAnimation);
|
assert(!context->movementAnimation);
|
||||||
context->removeObject(obj);
|
context->removeObject(obj);
|
||||||
context->addMovingObject(obj, from, dest);
|
|
||||||
context->movementAnimation = HeroAnimationState{ obj->id, from, dest, 0.0 };
|
if (settings["adventure"]["heroMoveTime"].Float() > 1)
|
||||||
|
{
|
||||||
|
context->addMovingObject(obj, from, dest);
|
||||||
|
context->movementAnimation = HeroAnimationState{ obj->id, from, dest, 0.0 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// instant movement
|
||||||
|
context->addObject(obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapViewController::onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
void MapViewController::onHeroRotated(const CGHeroInstance * obj, const int3 & from, const int3 & dest)
|
||||||
|
@ -65,8 +65,7 @@ public:
|
|||||||
size_t objectGroupIndex(ObjectInstanceID objectID) const override;
|
size_t objectGroupIndex(ObjectInstanceID objectID) const override;
|
||||||
Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const override;
|
Point objectImageOffset(ObjectInstanceID objectID, const int3 & coordinates) const override;
|
||||||
double objectTransparency(ObjectInstanceID objectID) const override;
|
double objectTransparency(ObjectInstanceID objectID) const override;
|
||||||
uint32_t getAnimationPeriod() const override;
|
size_t objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const override;
|
||||||
uint32_t getAnimationTime() const override;
|
|
||||||
Point getTileSize() const override;
|
Point getTileSize() const override;
|
||||||
bool showGrid() const override;
|
bool showGrid() const override;
|
||||||
};
|
};
|
||||||
|
@ -424,7 +424,6 @@ CLevelWindow::~CLevelWindow()
|
|||||||
LOCPLINT->showingDialog->setn(false);
|
LOCPLINT->showingDialog->setn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj)
|
CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj)
|
||||||
: CStatusbarWindow(PLAYER_COLORED, "TPTAVERN"),
|
: CStatusbarWindow(PLAYER_COLORED, "TPTAVERN"),
|
||||||
tavernObj(TavernObj)
|
tavernObj(TavernObj)
|
||||||
|
@ -37,15 +37,15 @@ AdventureOptionsTab::AdventureOptionsTab()
|
|||||||
const JsonNode config(ResourceID("config/widgets/settings/adventureOptionsTab.json"));
|
const JsonNode config(ResourceID("config/widgets/settings/adventureOptionsTab.json"));
|
||||||
addCallback("playerHeroSpeedChanged", [](int value)
|
addCallback("playerHeroSpeedChanged", [](int value)
|
||||||
{
|
{
|
||||||
return setIntSetting("adventure", "heroSpeed", value);
|
return setIntSetting("adventure", "heroMoveTime", value);
|
||||||
});
|
});
|
||||||
addCallback("enemyHeroSpeedChanged", [](int value)
|
addCallback("enemyHeroSpeedChanged", [](int value)
|
||||||
{
|
{
|
||||||
return setIntSetting("adventure", "enemySpeed", value);
|
return setIntSetting("adventure", "enemyMoveTime", value);
|
||||||
});
|
});
|
||||||
addCallback("mapScrollSpeedChanged", [](int value)
|
addCallback("mapScrollSpeedChanged", [](int value)
|
||||||
{
|
{
|
||||||
return setIntSetting("adventure", "scrollSpeed", value);
|
return setIntSetting("adventure", "scrollSpeedPixels", value);
|
||||||
});
|
});
|
||||||
addCallback("heroReminderChanged", [](bool value)
|
addCallback("heroReminderChanged", [](bool value)
|
||||||
{
|
{
|
||||||
@ -93,4 +93,4 @@ AdventureOptionsTab::AdventureOptionsTab()
|
|||||||
|
|
||||||
std::shared_ptr<CToggleButton> showGridCheckbox = widget<CToggleButton>("showGridCheckbox");
|
std::shared_ptr<CToggleButton> showGridCheckbox = widget<CToggleButton>("showGridCheckbox");
|
||||||
showGridCheckbox->setSelected(settings["gameTweaks"]["showGrid"].Bool());
|
showGridCheckbox->setSelected(settings["gameTweaks"]["showGrid"].Bool());
|
||||||
}
|
}
|
||||||
|
@ -161,19 +161,19 @@
|
|||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
"default": {},
|
"default": {},
|
||||||
"required" : [ "heroSpeed", "enemySpeed", "scrollSpeed", "heroReminder", "quickCombat" ],
|
"required" : [ "heroMoveTime", "enemyMoveTime", "scrollSpeedPixels", "heroReminder", "quickCombat" ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"heroSpeed" : {
|
"heroMoveTime" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"default" : 2
|
"default" : 150
|
||||||
},
|
},
|
||||||
"enemySpeed" : {
|
"enemyMoveTime" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"default" : 2
|
"default" : 150
|
||||||
},
|
},
|
||||||
"scrollSpeed" : {
|
"scrollSpeedPixels" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
"default" : 1
|
"default" : 800
|
||||||
},
|
},
|
||||||
"heroReminder" : {
|
"heroReminder" : {
|
||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"items":
|
"items":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"index": 1,
|
"index": 200,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb1",
|
"image": "sysopb1",
|
||||||
"help": "core.help.349",
|
"help": "core.help.349",
|
||||||
@ -39,7 +39,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 2,
|
"index": 150,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb2",
|
"image": "sysopb2",
|
||||||
"help": "core.help.350",
|
"help": "core.help.350",
|
||||||
@ -47,7 +47,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 4,
|
"index": 100,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb3",
|
"image": "sysopb3",
|
||||||
"help": "core.help.351",
|
"help": "core.help.351",
|
||||||
@ -55,7 +55,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 16,
|
"index": 0,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb4",
|
"image": "sysopb4",
|
||||||
"help": "core.help.352",
|
"help": "core.help.352",
|
||||||
@ -80,7 +80,7 @@
|
|||||||
"items":
|
"items":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"index": 2,
|
"index": 150,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb5",
|
"image": "sysopb5",
|
||||||
"help": "core.help.353",
|
"help": "core.help.353",
|
||||||
@ -88,7 +88,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 4,
|
"index": 100,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb6",
|
"image": "sysopb6",
|
||||||
"help": "core.help.354",
|
"help": "core.help.354",
|
||||||
@ -96,7 +96,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 8,
|
"index": 0,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb7",
|
"image": "sysopb7",
|
||||||
"help": "core.help.355",
|
"help": "core.help.355",
|
||||||
@ -104,7 +104,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 0,
|
"index": -1,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb8",
|
"image": "sysopb8",
|
||||||
"help": "core.help.356",
|
"help": "core.help.356",
|
||||||
@ -121,7 +121,7 @@
|
|||||||
"items":
|
"items":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"index": 1,
|
"index": 400,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysopb9",
|
"image": "sysopb9",
|
||||||
"help": "core.help.357",
|
"help": "core.help.357",
|
||||||
@ -129,7 +129,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 2,
|
"index": 800,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysob10",
|
"image": "sysob10",
|
||||||
"help": "core.help.358",
|
"help": "core.help.358",
|
||||||
@ -137,7 +137,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"index": 4,
|
"index": 1200,
|
||||||
"type": "toggleButton",
|
"type": "toggleButton",
|
||||||
"image": "sysob11",
|
"image": "sysob11",
|
||||||
"help": "core.help.359",
|
"help": "core.help.359",
|
||||||
@ -264,4 +264,4 @@
|
|||||||
"callback": "showGridChanged"
|
"callback": "showGridChanged"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user