1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Merge pull request #1792 from IvanSavenko/happy_dydzio

Fixes for beta - graphical artifacts
This commit is contained in:
Ivan Savenko 2023-03-30 00:11:19 +03:00 committed by GitHub
commit 974be97e6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 115 additions and 70 deletions

View File

@ -38,7 +38,6 @@
"name" : "Ключевые файлы VCMI",
"description" : "Файлы, необходимые для полноценной работы VCMI",
"author" : "Команда VCMI",
"modType" : "Графический",
"skipValidation" : true,
"translations" : [

View File

@ -2033,7 +2033,7 @@ bool CPlayerInterface::capturedAllEvents()
return true;
}
bool needToLockAdventureMap = adventureInt->active && CGI->mh->hasOngoingAnimations();
bool needToLockAdventureMap = adventureInt && adventureInt->active && CGI->mh->hasOngoingAnimations();
if (ignoreEvents || needToLockAdventureMap)
{

View File

@ -694,14 +694,14 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
if (action.spell() == SpellID::SACRIFICE)
{
heroSpellToCast->aimToHex(targetHex);
possibleActions.push_back(PossiblePlayerBattleAction::SACRIFICE);
possibleActions.push_back({PossiblePlayerBattleAction::SACRIFICE, action.spell()});
owner.stacksController->setSelectedStack(targetStack);
return;
}
if (action.spell() == SpellID::TELEPORT)
{
heroSpellToCast->aimToUnit(targetStack);
possibleActions.push_back(PossiblePlayerBattleAction::TELEPORT);
possibleActions.push_back({PossiblePlayerBattleAction::TELEPORT, action.spell()});
owner.stacksController->setSelectedStack(targetStack);
return;
}

View File

@ -35,8 +35,6 @@
#include "../../lib/CStack.h"
#include "../../lib/spells/ISpellMechanics.h"
#include <SDL_events.h>
BattleFieldController::BattleFieldController(BattleInterface & owner):
owner(owner)
{
@ -67,10 +65,7 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
backgroundWithHexes = std::make_unique<Canvas>(Point(background->width(), background->height()));
auto accessibility = owner.curInt->cb->getAccesibility();
for(int i = 0; i < accessibility.size(); i++)
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
updateAccessibleHexes();
addUsedEvents(LCLICK | RCLICK | MOVE);
LOCPLINT->cingconsole->pos = this->pos;
}
@ -180,11 +175,6 @@ void BattleFieldController::redrawBackgroundWithHexes()
if (activeStack)
occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes);
auto accessibility = owner.curInt->cb->getAccesibility();
for(int i = 0; i < accessibility.size(); i++)
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
//prepare background graphic with hexes and shaded hexes
backgroundWithHexes->draw(background, Point(0,0));
owner.obstacleController->showAbsoluteObstacles(*backgroundWithHexes);
@ -579,6 +569,14 @@ bool BattleFieldController::isTileAttackable(const BattleHex & number) const
return false;
}
void BattleFieldController::updateAccessibleHexes()
{
auto accessibility = owner.curInt->cb->getAccesibility();
for(int i = 0; i < accessibility.size(); i++)
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE || (accessibility[i] == EAccessibility::SIDE_COLUMN));
}
bool BattleFieldController::stackCountOutsideHex(const BattleHex & number) const
{
return stackCountOutsideHexes[number];
@ -591,6 +589,7 @@ void BattleFieldController::showAll(SDL_Surface * to)
void BattleFieldController::show(SDL_Surface * to)
{
updateAccessibleHexes();
owner.stacksController->update();
owner.obstacleController->update();

View File

@ -56,6 +56,7 @@ class BattleFieldController : public CIntObject
void showBackgroundImage(Canvas & canvas);
void showBackgroundImageWithHexes(Canvas & canvas);
void showHighlightedHexes(Canvas & canvas);
void updateAccessibleHexes();
BattleHex::EDir selectAttackDirection(BattleHex myNumber, const Point & point);

View File

@ -267,12 +267,8 @@ bool BattleStacksController::stackNeedsAmountBox(const CStack * stack) const
return false;
// if stack has any ongoing animation - hide the box
for(auto anim : currentAnimations)
{
auto stackAnimation = dynamic_cast<BattleStackAnimation*>(anim);
if(stackAnimation && (stackAnimation->stack->ID == stack->ID))
return false;
}
if (stackAmountBoxHidden.count(stack->ID))
return false;
return true;
}
@ -300,26 +296,42 @@ std::shared_ptr<IImage> BattleStacksController::getStackAmountBox(const CStack *
void BattleStacksController::showStackAmountBox(Canvas & canvas, const CStack * stack)
{
//blitting amount background box
auto amountBG = getStackAmountBox(stack);
const int sideShift = stack->side == BattleSide::ATTACKER ? 1 : -1;
const int reverseSideShift = stack->side == BattleSide::ATTACKER ? -1 : 1;
const BattleHex nextPos = stack->getPosition() + sideShift;
const bool edge = stack->getPosition() % GameConstants::BFIELD_WIDTH == (stack->side == BattleSide::ATTACKER ? GameConstants::BFIELD_WIDTH - 2 : 1);
const bool moveInside = !edge && !owner.fieldController->stackCountOutsideHex(nextPos);
bool doubleWide = stack->doubleWide();
bool turnedRight = facingRight(stack);
bool attacker = stack->side == BattleSide::ATTACKER;
int xAdd = (stack->side == BattleSide::ATTACKER ? 220 : 202) +
(stack->doubleWide() ? 44 : 0) * sideShift +
(moveInside ? amountBG->width() + 10 : 0) * reverseSideShift;
int yAdd = 260 + ((stack->side == BattleSide::ATTACKER || moveInside) ? 0 : -15);
BattleHex stackPos = stack->getPosition();
canvas.draw(amountBG, stackAnimation[stack->ID]->pos.topLeft() + Point(xAdd, yAdd));
// double-wide unit turned around - use opposite hex for stack label
if (doubleWide && turnedRight != attacker)
stackPos = stack->occupiedHex();
//blitting amount
Point textPos = stackAnimation[stack->ID]->pos.topLeft() + amountBG->dimensions()/2 + Point(xAdd, yAdd);
BattleHex frontPos = turnedRight ?
stackPos.cloneInDirection(BattleHex::RIGHT) :
stackPos.cloneInDirection(BattleHex::LEFT);
canvas.drawText(textPos, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, TextOperations::formatMetric(stack->getCount(), 4));
bool moveInside = !owner.fieldController->stackCountOutsideHex(frontPos);
Point boxPosition;
if (moveInside)
{
boxPosition = owner.fieldController->hexPositionLocal(stackPos).center() + Point(-15, 1);
}
else
{
if (turnedRight)
boxPosition = owner.fieldController->hexPositionLocal(frontPos).center() + Point (-22, 1);
else
boxPosition = owner.fieldController->hexPositionLocal(frontPos).center() + Point(-8, -14);
}
Point textPosition = amountBG->dimensions()/2 + boxPosition;
canvas.draw(amountBG, boxPosition);
canvas.drawText(textPosition, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, TextOperations::formatMetric(stack->getCount(), 4));
}
void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
@ -368,6 +380,7 @@ void BattleStacksController::updateBattleAnimations()
if (hadAnimations && currentAnimations.empty())
{
//stackAmountBoxHidden.clear();
owner.executeStagedAnimations();
if (currentAnimations.empty())
owner.onAnimationsFinished();
@ -378,8 +391,15 @@ void BattleStacksController::updateBattleAnimations()
void BattleStacksController::addNewAnim(BattleAnimation *anim)
{
if (currentAnimations.empty())
stackAmountBoxHidden.clear();
owner.onAnimationsStarted();
currentAnimations.push_back(anim);
auto stackAnimation = dynamic_cast<BattleStackAnimation*>(anim);
if(stackAnimation)
stackAmountBoxHidden.insert(stackAnimation->stack->ID);
}
void BattleStacksController::stackRemoved(uint32_t stackID)
@ -668,6 +688,8 @@ void BattleStacksController::endAction(const BattleAction* action)
owner.executeStagedAnimations();
owner.waitForAnimations();
stackAmountBoxHidden.clear();
owner.windowObject->blockUI(activeStack == nullptr);
removeExpiredColorFilters();
}
@ -738,8 +760,8 @@ Point BattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CSta
if(stack && stack->initialPosition < 0) //creatures in turrets
return owner.siegeController->getTurretCreaturePosition(stack->initialPosition);
static const Point basePos(-190, -139); // position of creature in topleft corner
static const int imageShiftX = 30; // X offset to base pos for facing right stacks, negative for facing left
static const Point basePos(-189, -139); // position of creature in topleft corner
static const int imageShiftX = 29; // X offset to base pos for facing right stacks, negative for facing left
ret.x = basePos.x + 22 * ( (hexNum.getY() + 1)%2 ) + 44 * hexNum.getX();
ret.y = basePos.y + 42 * hexNum.getY();

View File

@ -67,6 +67,9 @@ class BattleStacksController
/// <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
std::map<int, bool> stackFacingRight;
/// Stacks have amount box hidden due to ongoing animations
std::set<int> stackAmountBoxHidden;
/// currently active stack; nullptr - no one
const CStack *activeStack;

View File

@ -66,16 +66,18 @@ void BasicMapView::render(Canvas & target, bool fullUpdate)
void BasicMapView::show(SDL_Surface * to)
{
controller->update(GH.mainFPSmng->getElapsedMilliseconds());
controller->updateBefore(GH.mainFPSmng->getElapsedMilliseconds());
Canvas target(to);
CSDL_Ext::CClipRectGuard guard(to, pos);
render(target, false);
controller->updateAfter(GH.mainFPSmng->getElapsedMilliseconds());
}
void BasicMapView::showAll(SDL_Surface * to)
{
controller->update(0);
controller->updateBefore(0);
Canvas target(to);
CSDL_Ext::CClipRectGuard guard(to, pos);

View File

@ -88,7 +88,7 @@ std::shared_ptr<IMapRendererContext> MapViewController::getContext() const
return context;
}
void MapViewController::update(uint32_t timeDelta)
void MapViewController::updateBefore(uint32_t timeDelta)
{
// confirmed to match H3 for
// - hero embarking on boat (500 ms)
@ -116,56 +116,32 @@ void MapViewController::update(uint32_t timeDelta)
settings["adventure"]["enemyMoveTime"].Float();
movementContext->progress += timeDelta / heroMoveTime;
movementContext->progress = std::min( 1.0, movementContext->progress);
Point positionFrom = Point(hero->convertToVisitablePos(movementContext->tileFrom)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
Point positionDest = Point(hero->convertToVisitablePos(movementContext->tileDest)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
Point positionCurr = vstd::lerp(positionFrom, positionDest, movementContext->progress);
if(movementContext->progress >= 1.0)
{
setViewCenter(hero->getSightCenter());
removeObject(context->getObject(movementContext->target));
addObject(context->getObject(movementContext->target));
activateAdventureContext(movementContext->animationTime);
}
else
{
setViewCenter(positionCurr, movementContext->tileDest.z);
}
setViewCenter(positionCurr, movementContext->tileDest.z);
}
if(teleportContext)
{
teleportContext->progress += timeDelta / heroTeleportDuration;
if(teleportContext->progress >= 1.0)
{
activateAdventureContext(teleportContext->animationTime);
}
teleportContext->progress = std::min( 1.0, teleportContext->progress);
}
if(fadingOutContext)
{
fadingOutContext->progress -= timeDelta / fadeOutDuration;
if(fadingOutContext->progress <= 0.0)
{
removeObject(context->getObject(fadingOutContext->target));
activateAdventureContext(fadingOutContext->animationTime);
}
fadingOutContext->progress = std::max( 0.0, fadingOutContext->progress);
}
if(fadingInContext)
{
fadingInContext->progress += timeDelta / fadeInDuration;
if(fadingInContext->progress >= 1.0)
{
activateAdventureContext(fadingInContext->animationTime);
}
fadingInContext->progress = std::min( 1.0, fadingInContext->progress);
}
if(adventureContext)
@ -180,6 +156,48 @@ void MapViewController::update(uint32_t timeDelta)
}
}
void MapViewController::updateAfter(uint32_t timeDelta)
{
if(movementContext)
{
const auto * object = context->getObject(movementContext->target);
const auto * hero = dynamic_cast<const CGHeroInstance *>(object);
const auto * boat = dynamic_cast<const CGBoat *>(object);
assert(boat || hero);
if(!hero)
hero = boat->hero;
if(movementContext->progress >= 1.0)
{
setViewCenter(hero->getSightCenter());
removeObject(context->getObject(movementContext->target));
addObject(context->getObject(movementContext->target));
activateAdventureContext(movementContext->animationTime);
}
}
if(teleportContext && teleportContext->progress >= 1.0)
{
activateAdventureContext(teleportContext->animationTime);
}
if(fadingOutContext && fadingOutContext->progress <= 0.0)
{
removeObject(context->getObject(fadingOutContext->target));
activateAdventureContext(fadingOutContext->animationTime);
}
if(fadingInContext && fadingInContext->progress >= 1.0)
{
activateAdventureContext(fadingInContext->animationTime);
}
}
bool MapViewController::isEventVisible(const CGObjectInstance * obj)
{
if(adventureContext == nullptr)

View File

@ -83,7 +83,8 @@ public:
void setViewCenter(const int3 & position);
void setViewCenter(const Point & position, int level);
void setTileSize(const Point & tileSize);
void update(uint32_t timeDelta);
void updateBefore(uint32_t timeDelta);
void updateAfter(uint32_t timeDelta);
void activateAdventureContext(uint32_t animationTime);
void activateAdventureContext();