//Player moves
if ( changedDirection ) {
player.setDirection( this.playerDirection );
}
MapGridElement playerFooting = this.painter.getSecond();
assert playerFooting != null;
//Apply the coloring animations to the grid element
if ( playerPath == null ) {
//If the path wasn't created yet, create it
playerPath = new PathAnimationImpl();
playerPath.startNewPart( this.playerDirection );
playerPath.addPoint( playerPosition );
if ( player.modifiesColor() ) {
utilPushAnimation( entitiesColoringTrace,
playerFooting,
playerPath,
player.isColoring(),
playerPath.getNewPart() );
}
} else if ( changedDirection ) {
playerPath.startNewPart( this.playerDirection );
playerPath.addPoint( playerPosition );
if ( player.modifiesColor() ) {
utilPushAnimation( entitiesColoringTrace,
playerFooting,
playerPath,
player.isColoring(),
playerPath.getNewPart() );
}
}
switch ( this.playerDirection ) {
case LEFT:
playerPosition.x--;
break;
case RIGHT:
playerPosition.x++;
break;
case UP:
playerPosition.y--;
break;
case DOWN:
playerPosition.y++;
break;
}
player.setPosition( playerPosition );
playerPath.addPoint( playerPosition );
if ( ! playerFooting.contains( playerPosition ) ) {
//The player changed grid element, the animations must be applied to this element too
playerFooting = findElementRelativeTo( this.levelGraph, playerFooting,
this.playerDirection );
this.painter.setSecond( playerFooting );
if ( player.modifiesColor() ) {
utilPushAnimation( entitiesColoringTrace,
playerFooting,
playerPath,
player.isColoring(),
playerPath.getNewPart() );
}
}
if ( player.modifiesColor() ) {
//Colors this part of the grid
if ( playerFooting.isColoredAt( playerPosition ) != player.isColoring() ) {
if ( player.isColoring() ) {
this.addScore( COLORING_SCORE );
} else {
//Decoloration by the player is allowed, only for completeness
this.addScore( - COLORING_SCORE );
}
}
this.utilColorGridElementAndUpdateChanges( playerFooting,
playerPosition,
player.isColoring() );
}
for (Monster stillMonster : stillMonsters) {
//Moving monster will be checked for collision in the code below
if ( stillMonster.getPosition().equals( playerPosition ) ) {
deadMan = true;
}
}
} else {
remainingPlayerSpeed = 0;
}
}
final Point actualPlayerPosition = player.getPosition();
//Monsters are moved
Iterator<Map.Entry<Monster, Integer>> monstersIterator = roundRobin.entrySet()
.iterator();
while ( monstersIterator.hasNext() ) {
final Map.Entry<Monster, Integer> monsterWithSpeed = monstersIterator.next();
final int remainingMonsterSpeed = monsterWithSpeed.getValue();
final Monster mob = monsterWithSpeed.getKey();
if ( remainingMonsterSpeed > 0 ) {
monsterWithSpeed.setValue( remainingMonsterSpeed - 1 );
final Point monsterPosition = mob.getPosition();
if ( actualPlayerPosition.equals( monsterPosition ) ) {
deadMan = true;
}
final PathAnimation mobAnimation;
@Nullable
PERPENDICULAR_DIRECTION monsterDirection;
if ( this.firstStep ) {
monsterDirection = null;
} else {
monsterDirection = mob.getActualDirection();
}
MapGridElement monsterFooting = this.monstersPosition.get( mob );
assert monsterFooting != null;
if ( monsterFooting instanceof Junction || monsterDirection == null ) {
//Monster is in a junction, must change direction
monsterDirection = mob.getNewDirection( monsterDirection, false );
}
if ( mob instanceof AnimatedElement ) {
//This is an animated monster, an animations must be applied
PathAnimation animation = this.monstersAndAnimations.get( mob );
if ( animation == null ) {
//If the animations wasn't created yet, create it
animation = new PathAnimationImpl();
animation.startNewPart( monsterDirection );
animation.addPoint( monsterPosition );
this.monstersAndAnimations.put( ( (AnimatedElement) mob ), animation );
if ( mob.modifiesColor() ) {
utilPushAnimation( entitiesColoringTrace,
monsterFooting,
animation,
mob.isColoring(),
animation.getNewPart() );
}
} else if ( monsterDirection != animation.getNewPartDirection() ) {
animation.startNewPart( monsterDirection );
animation.addPoint( monsterPosition );
if ( mob.modifiesColor() ) {
utilPushAnimation( entitiesColoringTrace,
monsterFooting,
animation,
mob.isColoring(),
animation.getNewPart() );
}
}
mobAnimation = animation;
} else {
mobAnimation = null;
}
switch ( monsterDirection ) {
case LEFT:
monsterPosition.x--;
break;
case RIGHT:
monsterPosition.x++;
break;
case UP:
monsterPosition.y--;
break;
case DOWN:
monsterPosition.y++;
break;
}
mob.setPosition( monsterPosition );
if ( mobAnimation != null ) {
mobAnimation.addPoint( monsterPosition );
}
if ( ! monsterFooting.contains( monsterPosition ) ) {
//The monster changed grid element, the animations must be applied to this element too
monsterFooting = findElementRelativeTo( this.levelGraph,
monsterFooting,
monsterDirection );
this.monstersPosition.put( mob, monsterFooting );
if ( mob.modifiesColor() && mobAnimation != null ) {
utilPushAnimation( entitiesColoringTrace,
monsterFooting,
mobAnimation,
mob.isColoring(),
mobAnimation.getNewPart() );
}
}
if ( mob.modifiesColor() ) {
//(De)Colors this part of the grid
final boolean isMobColoring = mob.isColoring();
final boolean wasColoredHere = monsterFooting.isColoredAt( monsterPosition );
if ( wasColoredHere != isMobColoring ) {
if ( wasColoredHere ) {
this.addScore( - COLORING_SCORE );
} else {
this.addScore( COLORING_SCORE );
}
}
this.utilColorGridElementAndUpdateChanges( monsterFooting, monsterPosition,
isMobColoring );
}
if ( actualPlayerPosition.equals( monsterPosition ) ) {
deadMan = true;
}
} else {
//Monster remaining speed is 0, remove it from the moving monsters
stillMonsters.add( mob );
monstersIterator.remove();
}
}
}
//Computes the end time of all the animations
final long scheduledAnimationEndTime = millisCallTime + GameSettings.getInstance()
.getValue( GameSettings.INTEGER_SETTINGS_TYPE.MOVE_MILLIS_TIMEOUT );
if ( playerPath != null && player instanceof AnimatedElement ) {
//Applies the previously computed path animations to the Player entity as an entity animations
playerPath.startAnimation( millisCallTime, scheduledAnimationEndTime );
( (AnimatedElement) player )
.applyAnimation( new PathBasedMovementAnimation( playerPath ) );
}
for (Map.Entry<AnimatedElement, PathAnimation> animatedEntry : this.monstersAndAnimations
.entrySet()) {
//Applies the previously computed path animations to the Monster entity as an entity animations
final PathAnimation entryAnimation = animatedEntry.getValue();
if ( entryAnimation != null ) {
entryAnimation.startAnimation( millisCallTime, scheduledAnimationEndTime );
animatedEntry.getKey()
.applyAnimation( new PathBasedMovementAnimation( entryAnimation ) );
}
}
for (Map.Entry<MapGridElement, Map<PathAnimation, Pair<Boolean, Collection<Segment>>>> mapGridElementEntry : entitiesColoringTrace
.entrySet()) {
//The key of the outer map keeps the grid element the animations refer to
final MapGridElement mapElement = mapGridElementEntry.getKey();
if ( mapElement instanceof Pipe ) {
final Collection<PipeColoringAnimation> resultElementAnimations = new LinkedList<>();
for (Map.Entry<PathAnimation, Pair<Boolean, Collection<Segment>>> pathAnimationEntry : mapGridElementEntry