...
 
Commits (6)
  • Terence Martin's avatar
    Include method to find and vanish blocked balls. · d9bc2a01
    Terence Martin authored
    This will be used during end game, just prior to vanishing all of the
    gray bricks and dropping the final balls.
    
    We want to be able to find all balls that have no chance of moving
    because they are either stopped on an arrow, or stopped on top of a
    ball waiting on an arrow, and then remove them away like the gray
    bricks do.
    d9bc2a01
  • Terence Martin's avatar
    Add a state for the new ball removal · 416c2951
    Terence Martin authored
    Adds in a new state for the purposes of handling when we are removing
    all blocked balls from the maze.
    416c2951
  • Terence Martin's avatar
    Implement ball removal state · cacdab8a
    Terence Martin authored
    This hooks into the previously created method and will continuously
    try to remove blocked balls from the maze until the method tells it
    that there are no further balls to remove and all that were removed
    are now done with.
    
    We skip to this state when all plays are exhausted and then to the
    remove gray bricks state once this is completed.
    cacdab8a
  • Terence Martin's avatar
    Fix bugs in blocked ball removal · b7594275
    Terence Martin authored
    This code went through several iterations, and so some things were not
    in the correct order (e.g. null test AFTER other tests).
    
    There was also an issue where a vanished ball would trigger the  ball
    drop complete method and then throw an error because there is no
    dropped ball, which I have currently patched away but this needs to be
    handled better.
    b7594275
  • Terence Martin's avatar
    Tweak the ball drop event · e71e3ed4
    Terence Martin authored
    It no longer gets the boolean indication; this can be determiend by
    the caller based on the map position of the ball when it stopped.
    e71e3ed4
  • Terence Martin's avatar
    Add a new event for removing blocked ball · f3d4974f
    Terence Martin authored
    This adds in a new event that tells us when a blocked ball is being
    removed (happens once when the ball is told to vanish).
    
    This can be used to add blocked balls to the final score when that
    happens.
    f3d4974f
This diff is collapsed.
......@@ -61,10 +61,18 @@ module nurdz.game
BALL_DROPPING,
/**
* All of the possible plays have been made. In this state we are
* removing all of the gray bricks that are in the maze by vanishing
* them away. Once that is done we transition to the state where we
* start dropping the final balls.
* ALl of the possible plays have been made. In this state we are
* finding and removing all balls that can't possibly move any farther
* because they are not sitting on top of a gray brick that will vanish
* and allow them to fall.
*/
REMOVE_BLOCKED_BALLS,
/**
* All of the possible plays have been made and all blocked ball have
* beem removed. In this state we are removing all of the gray bricks
* that are in the maze by vanishing them away. Once that is done we
* transition to the state where we start dropping the final balls.
*/
REMOVE_GRAY_BRICKS,
......
......@@ -26,17 +26,31 @@ module nurdz.game
/**
* A ball drop that was in progress has now finished. The event features
* the ball that was dropped and also an indication as to whether the
* ball reached the goal or not.
* the ball that was dropped.
*
* This gets triggered once the ball comes to a rest and before it is
* vanished away (if it should be).
*
* @param {Ball} ball the ball that stopped dropping
* @param {boolean} reachedGoal true if the ball reached the goal, false
* if it stopped in the maze somewhere.
* This is triggered for any ball drop; human or computer, during the
* regular game or as the final ball drop.
*
* @param {Ball} ball the ball that stopped dropping
*/
ballDropComplete (ball : Ball, reachedGoal : boolean) : void;
ballDropComplete (ball : Ball) : void;
/**
* A ball that is blocked has been told that it's being removed from
* the maze during the final part of the round just prior to the gray
* bricks being removed and the final ball drop.
*
* This gets triggered once the ball has been told to vanish away but
* before the vanish starts.
*
* This is triggered for both human and computer balls.
*
* @param {Ball} ball the ball that being removed
*/
blockedBallRemoved (ball : Ball) : void;
/**
* This will get invoked every time we're told to generate a maze and
......@@ -865,6 +879,82 @@ module nurdz.game
return sawBrick;
}
/**
* Scan through the maze from the bottom to the top looking for balls
* that we need to vanish away because there is no possibility of them
* moving further.
*
* Primarily this is a ball that is either directly resting on an arrow
* or a ball that is resting on a ball that is an arrow.
*
* In practice since we are scanning from the bottom up, we remove a
* ball in the situations mentioned above as well as when the cell below
* a ball is either empty or a hidden ball, both of which being a
* consequence of a previous call to this method having been invoked.
*
* The return value is false in the exact situation where there are no
* balls at all in the maze that require being removed or true if we
* told a ball to vanish or there is at least still one ball waiting to
* finish vanishing.
*
* This should be called repeatedly (over time) until it returns false.
*
* @returns {boolean} true if there are still balls to remove/waiting to
* be removed or false when no balls need to be removed any longer.
*/
removeNextBlockedBall () : boolean
{
let sawBall = false;
// Scan from the bottom up.
for (let row = MAZE_HEIGHT - 2 ; row >= 0 ; row--)
{
for (let col = 1 ; col < MAZE_WIDTH - 1 ; col++)
{
// Get the cell that we're searching for as a ball and the
// cell below it.
let cell = <Ball> this._contents.getCellAt (col, row);
let below = this._contents.getCellAt (col, row + 1);
// Skip this cell if it is empty or not a ball.
if (cell == null || cell.name != "ball")
continue;
// This is a ball; if it has already been hidden we can skip
// any further checks, but set our flag to indicate that we're
// still waiting for this ball to be removed.
if (cell.isHidden == true)
{
sawBall = true;
continue;
}
// This is a ball that is not already hidden. The criteria
// for hiding a ball during this call are that it is not
// already hidden (not already selected) and:
//
// 1) The cell below is a blank space (has to be a ball
// that we previously vanished with a call like this)
// 2) What is below is a ball that is hidden (will soon
// become #1, just not there yet)
// 3) The cell below is an arrow
if (below == null ||
below.name == "arrow" ||
(below.name == "ball" && (<Ball>below).isHidden == true))
{
// Tell our listener (if any) that this is happening
if (this._listener != null)
this._listener.blockedBallRemoved (cell);
cell.vanish ();
return true;
}
}
}
// Return if we saw a ball waiting to vanish or not.
return sawBall;
}
/**
* This is called every frame update (tick tells us how many times this
* has happened) to allow us to update ourselves.
......@@ -894,10 +984,14 @@ module nurdz.game
// Reap any dead balls; these are balls which are currently
// invisible but still alive; they can be removed from the grid now.
//
// When this happens, we can set the flag that indicates that the
// ball move is finalized, so that we can tell our listener that the
// move is done now.
if (this.clearHiddenBalls () > 0)
// When this happens and we are dropping a ball, then we can set the
// flag that indicates that the ball movement is finalized, so that
// we can tell our listener that the move is done now.
//
// This also gets triggered during non-dropped ball removal, such
// as vanishing blocked balls, but in that case we don't set the
// flag because the appropriate handling has already been done.
if (this.clearHiddenBalls () > 0 && this._droppingBall != null)
this._ballMoveFinalized = true;
// Reap any dead gray bricks; these are the gray bricks that have
......@@ -980,8 +1074,7 @@ module nurdz.game
// If there is a listener, tell it that this ball has stopped
// moving now.
if (this._listener != null)
this._listener.ballDropComplete (this._lastDroppedBall,
this._lastDroppedBall.mapPosition.y == MAZE_HEIGHT - 2);
this._listener.ballDropComplete (this._lastDroppedBall);
// Done with the value now.
this._lastDroppedBall = null;
......
module nurdz.game
{
/**
* When we are in the state that we're removing blocked balls from the maze,
* this is the delay (in ticks) for telling the next ball when it should
* start to vanish.
*/
const ROUND_BALL_VANISH_TIME = 3;
/**
* When we are in the state that we're removing gray bricks from the maze,
* this is the delay (in ticks) for telling the next brick when it should
......@@ -489,20 +496,21 @@ module nurdz.game
/**
* A ball drop that was in progress has now finished. The event features
* the ball that was dropped and also an indication as to whether the
* ball reached the goal or not.
* the ball that was dropped.
*
* This gets triggered once the ball comes to a rest and before it is
* vanished away (if it should be).
*
* @param {Ball} ball the ball that stopped dropping
* @param {boolean} reachedGoal true if the ball reached the goal, false
* if it stopped in the maze somewhere.
* This is triggered for any ball drop; human or computer, during the
* regular game or as the final ball drop.
*
* @param {Ball} ball the ball that stopped dropping
*/
ballDropComplete (ball : Ball, reachedGoal : boolean) : void
ballDropComplete (ball : Ball) : void
{
// Did the ball reach the goal? This is good enough for testing.
if (reachedGoal)
if (ball.mapPosition.y == MAZE_HEIGHT - 2)
console.log ("GOOOOOAL!");
// Now that the ball is done, where we go depends on where we came
......@@ -534,6 +542,23 @@ module nurdz.game
}
}
/**
* A ball that is blocked has been told that it's being removed from
* the maze during the final part of the round just prior to the gray
* bricks being removed and the final ball drop.
*
* This gets triggered once the ball has been told to vanish away but
* before the vanish starts.
*
* This is triggered for both human and computer balls.
*
* @param {Ball} ball the ball that being removed
*/
blockedBallRemoved (ball : Ball) : void
{
console.log("Removing blocked ball at " + ball.mapPosition.toString ());
}
/**
* The Maze is telling us that it is now empty of gray bricks because it
* has just reaped the last fully hidden gray brick.
......@@ -632,7 +657,7 @@ module nurdz.game
if (this._maze.contents.hasPlayableComputerBall ())
this.state = GameState.COMPUTER_TURN;
else
this.state = GameState.REMOVE_GRAY_BRICKS;
this.state = GameState.REMOVE_BLOCKED_BALLS;
}
break;
......@@ -650,6 +675,20 @@ module nurdz.game
if (this._maze.contents.hasPlayableHumanBall ())
this.state = GameState.PLAYER_TURN;
else
this.state = GameState.REMOVE_BLOCKED_BALLS;
}
break;
// When we are in the remove blocked balls state, use the state
// timer to remove a blocked ball every so often, until we
// determine that there are none left.
case GameState.REMOVE_BLOCKED_BALLS:
if (this._state.timerTrigger (ROUND_BALL_VANISH_TIME))
{
// Try to remove a ball; this returns false when there
// are no more balls to remove AND all balls we were
// waiting for are now gone.
if (this._maze.removeNextBlockedBall () == false)
this.state = GameState.REMOVE_GRAY_BRICKS;
}
break;
......