...
 
Commits (13)
  • Terence Martin's avatar
    Fix drop ball bug introduced yesterday · 5e7cb088
    Terence Martin authored
    Yesterday I introduced some new code where we could detect a vanished
    ball but not trigger the notification that a ball drop was complete if
    the ball was being vanished due to it being a blocked ball.
    
    This was a bit flawed but unfortunatey I didn't notice it until it was
    too late. Basically it would not trigger for a ball that vanished
    because it got to the goal, because I used the wrong variable to track
    if the event should trigger or not (_droppedBall instead of
    _lastDroppedBall) and since _droppedBall gets cleared as soon as the
    vanish is called, such a ball is treated like a blocked ball.
    
    This has been fixed by using the correct variable.
    5e7cb088
  • Terence Martin's avatar
    Refactor final ball drop flag setting · 0d43c88a
    Terence Martin authored
    Instead of code needing to remeber to set the flag to some value, we
    now just make it a parameter to the drop function.
    0d43c88a
  • Terence Martin's avatar
    Make maze regeneration a debug key · ff660aec
    Terence Martin authored
    This should only happen while in debug mode, not during game mode. If
    you're trying to play a game to test and you press the key by mistake,
    it's the sad maker.
    ff660aec
  • Terence Martin's avatar
    Include KenVector font · 1e2b7768
    Terence Martin authored
    This is freely available and my font of choice for nice looking
    monospace text.
    
    This font is set as the default font at a set size upon activation of
    the game scene, so that we don't have to keep swapping it into the
    context.
    1e2b7768
  • Terence Martin's avatar
    Include code for tracking and rendering score · 2dc295c4
    Terence Martin authored
    This includes the global game state routines and values that will be
    used to track the score, alter it, and render it to the screen.
    2dc295c4
  • Terence Martin's avatar
    Render scores and reset on maze generation · 9aed72e4
    Terence Martin authored
    This will need to be tweaked when we have multiple rounds, but it's
    good enough for now.
    
    The scores are unadorned, but are enough for us to be able to track
    what is going on.
    9aed72e4
  • Terence Martin's avatar
    Add player property to Ball · 91733a2c
    Terence Martin authored
    This gives the Ball the ability to return what player owns it based on
    its own type. This will be used during the score modifications to
    determine who gets the points.
    91733a2c
  • Terence Martin's avatar
    Update ball drop finished event handler · 9c54b987
    Terence Martin authored
    The ballDropComplete() handler now takes a boolean flag that indicates
    if this ball drop was finalized as part of a regular ball drop (false)
    or a final ball drop (true).
    
    This allows us to apply score to the ball when it stops, if we need
    to.
    9c54b987
  • Terence Martin's avatar
    Score for bonus bricks · 831ec388
    Terence Martin authored
    When a ball passes through a bonus brick during the regular game,
    apply a score change to the owner of that ball.
    831ec388
  • Terence Martin's avatar
    Score for balls at the goal line · 9213c393
    Terence Martin authored
    When a ball reaches the goal at the bottom of the screen (regardless
    of when this happens), score points for that ball.
    9213c393
  • Terence Martin's avatar
    Score for blocked balls at round end · 6f1de1c6
    Terence Martin authored
    Score partial points based on ball position whenever a ball is
    vanished during the game without it having reached the goal line. This
    can happen when a ball is blocked and removed before the final ball
    drop, or when the final ball drop does not end the ball at the goal
    line.
    6f1de1c6
  • Terence Martin's avatar
    Update Ball API to use new scores · 2e2bb546
    Terence Martin authored
    Now that the values for the scores are in place, the AI code has been
    modified to use the proper values during it's evaluation process.
    2e2bb546
  • Terence Martin's avatar
    Update game thumbnail · b6433ae9
    Terence Martin authored
    b6433ae9
This diff is collapsed.
images/game_thumbnail.png

41.4 KB | W: | H:

images/game_thumbnail.png

39.1 KB | W: | H:

images/game_thumbnail.png
images/game_thumbnail.png
images/game_thumbnail.png
images/game_thumbnail.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -108,7 +108,7 @@
<dd>Rotate player to facing; walk in direction</dd>
<dt>Spacebar</dt>
<dd>Push ball</dd>
<dt>? (on player's turn)</dt>
<dt>? (on player's turn, debugging off)</dt>
<dd>Get AI suggestion of ball to play</dd>
<dt>F12</dt>
<dd>Toggle debug/editing mode</dd>
......
This diff is collapsed.
......@@ -71,12 +71,12 @@ module nurdz.game
// If the position where this ball stopped is the bottom of the maze,
// it gets a bonus score.
if (storedPos.y == MAZE_HEIGHT - 2)
ball.score += 100;
ball.score += GOAL_BALL_SCORE;
// Return the final score, which is the number of bonus bricks that this
// ball passed through, plus getting to the bottom (if it did), plus points
// for each row it made it through the maze.
return ball.score + (storedPos.y * 5);
return ball.score + (storedPos.y * BALL_POSITION_MULTIPLIER);
}
/**
......
module nurdz.game
{
/**
* The number of points that a bonus brick is worth.
*/
export const BONUS_BRICK_SCORE = 10;
/**
* The number of points that it's worth to get a ball all the way to the
* bottom of the screen, where the goal line is.
*/
export const GOAL_BALL_SCORE = 60;
/**
* The number of points scored per row of advancement of a ball. This is
* applied at the end of the round when the final balls are removed.
*/
export const BALL_POSITION_MULTIPLIER = 2;
/**
* The number of points the human player has.
*/
let humanScore : number = 0;
/**
* The number of poitns the computer player has.
*/
let computerScore : number = 0;
/**
* Reset the score values for both players.
*/
export function resetScores () : void
{
humanScore = 0;
computerScore = 0;
}
/**
* Update the score for the designated player by adding or subtracting the
* provided point value from the score.
*
* @param {PlayerType} player the player to adjust the score for
* @param {number} value the adjustment value; can be positive or
* negative
*/
function adjustScore (player : PlayerType, value : number) : void
{
// Update the correct score.
if (player == PlayerType.PLAYER_HUMAN)
humanScore += value;
else
computerScore += value;
}
/**
* Score points due to touching a bonus brick for the owner of the ball
* provided.
*
* @param {Ball} ball the ball that touched the bonus brick
*/
export function bonusBrickScore (ball : Ball) : void
{
adjustScore (ball.player, BONUS_BRICK_SCORE);
}
/**
* Score points due to a ball reaching the goal line (the bottom of the
* maze).
*
* @param {Ball} ball the ball that reached the score line
*/
export function goalBallScore (ball : Ball) : void
{
adjustScore (ball.player, GOAL_BALL_SCORE);
}
/**
* Score partial points for a ball based on its final resting position in
* the maze.
*
* @param {Ball} ball the ball to score partial points for
*/
export function partialBallScore (ball : Ball) : void
{
adjustScore (ball.player, ball.mapPosition.y * BALL_POSITION_MULTIPLIER);
}
/**
* Render the scores of the two players to the screen. This renders the
* scores to a known position on screen.
*
* @param {Renderer} renderer the renderer to use to blit the text.
*/
export function renderScores (renderer : Renderer) : void
{
renderer.drawTxt (humanScore+"", 16, 32, "white");
renderer.drawTxt (computerScore+"", STAGE_WIDTH - (5 * 32), 32, "yellow");
}
}
\ No newline at end of file
......@@ -158,6 +158,19 @@ module nurdz.game
get isHidden () : boolean
{ return this._hidden; }
/**
* Return the type of player that owns this ball. This is derived from
* the current ball type, and is read-only.
*
* @returns {PlayerType} the type of player that owns this ball. ball.
*/
get player () : PlayerType
{
if (this._ballType == BallType.BALL_PLAYER)
return PlayerType.PLAYER_HUMAN;
return PlayerType.PLAYER_COMPUTER;
}
/**
* Construct a new ball entity that will render on the stage provided.
*
......
......@@ -34,11 +34,15 @@ module nurdz.game
* This value only tracks if you use the methods on the Ball entity to
* vanish or appear it; if you modify it's animation yourself, this will
* get out of sync.
*
* @type {boolean}
*/
private _hidden : boolean;
/**
* This flag is used during the simulation and is used to track if we
* have already been collected or not. This allows the AI to not
* prioritize a move that passes through the same bonus brick twice for
* some reason higher than other paths.
*/
private _simulationCollected : boolean;
/**
......@@ -287,6 +291,9 @@ module nurdz.game
// ourselves collected.
if (this._hidden == false)
this.vanish ();
// Score points for the owner of the ball as well.
bonusBrickScore (ball);
}
else
{
......@@ -294,7 +301,7 @@ module nurdz.game
// saying we are collected, update the score in the ball that
// touched us.
if (this._simulationCollected == false)
ball.score += 10;
ball.score += BONUS_BRICK_SCORE;
// We are collected now, no matter what.
this._simulationCollected = true;
......
......@@ -34,9 +34,15 @@ module nurdz.game
* 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
* The owner of the ball can be determined from the ball entity itself
* while isFinal tells you if the ball finished dropping as part of a
* regular or final ball drop.
*
* @param {Ball} ball the ball that stopped dropping
* @param {boolean} isFInal true if this ball was part of a final ball
* drop
*/
ballDropComplete (ball : Ball) : void;
ballDropComplete (ball : Ball, isFinal : boolean) : void;
/**
* A ball that is blocked has been told that it's being removed from
......@@ -474,7 +480,7 @@ module nurdz.game
if (entity != null && entity.name == "ball" && this._droppingBall == null)
{
// Drop it and leave.
this.dropBall (<Ball> entity, NORMAL_DROP_SPEED);
this.dropBall (<Ball> entity, NORMAL_DROP_SPEED, false);
return true;
}
......@@ -520,7 +526,7 @@ module nurdz.game
if (entity.name == "ball" && this._droppingBall == null)
{
// Drop it and leave.
this.dropBall (<Ball> entity, NORMAL_DROP_SPEED);
this.dropBall (<Ball> entity, NORMAL_DROP_SPEED, false);
return true;
}
......@@ -564,16 +570,18 @@ module nurdz.game
* its map position must accurately reflect the position it is stored
* in, since that position will be cleared when the ball starts moving.
*
* @param {Ball} ball the ball to drop
* @param {number} speed the number of ticks between ball step stages
* When isFinal is true, this ball will be vanished as soon as it stops
* moving, even if it doesn't reach the goal.
*
* @param {Ball} ball the ball to drop
* @param {number} speed the number of ticks between ball step stages
* @param {boolean} isFinal true if this is a final ball drop or false
* otherwise
*/
private dropBall (ball : Ball, speed : number) : void
private dropBall (ball : Ball, speed : number, isFinal: boolean) : void
{
// At least during development, reset the flag that indicates the
// reason for this ball push to indicate that this is not the final
// ball. In practice this is not needed as long as this value gets
// reset on maze generation.
this._droppingFinalBall = false;
// Set the flag that indicates if this drop is a final drop or not.
this._droppingFinalBall = isFinal;
// Get the maze contents to mark this ball as played. If this is
// one of the generated human or computer balls from the top row,
......@@ -803,16 +811,7 @@ module nurdz.game
if (cell != null && cell.name == "ball")
{
// Start this ball dropping.
this.dropBall (<Ball> cell, FINAL_DROP_SPEED);
// Set the flag indicating that we are dropping a final
// ball. This allows us to make sure that this ball
// always vanishes when it is finished dropping, even if
// it doesn't reach the goal.
//
// This has to happen here because (for safety) the
// above method sets the value to false.
this._droppingFinalBall = true;
this.dropBall (<Ball> cell, FINAL_DROP_SPEED, true);
return true;
}
}
......@@ -991,7 +990,7 @@ module nurdz.game
// 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)
if (this.clearHiddenBalls () > 0 && this._lastDroppedBall != null)
this._ballMoveFinalized = true;
// Reap any dead gray bricks; these are the gray bricks that have
......@@ -1074,7 +1073,8 @@ 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._listener.ballDropComplete (this._lastDroppedBall,
this._droppingFinalBall);
// Done with the value now.
this._lastDroppedBall = null;
......@@ -1231,6 +1231,9 @@ module nurdz.game
// Now generate the contents of the maze.
this._generator.generate ();
// Reset the scores
resetScores ();
// If there is a listener, tell it now that the generation has
// completed.
if (this._listener != null)
......
......@@ -22,6 +22,11 @@ module nurdz.game
implements StateMachineChangeListener,
MazeEventListener
{
/**
* Override the type of our renderer to be a canvas renderer.
*/
protected _renderer : CanvasRenderer;
/**
* Our state machine; this controls what we're doing at any given time.
*/
......@@ -148,6 +153,9 @@ module nurdz.game
// Let the super work its magic.
super.activating (previousScene);
// Set up what our font should be while this screen is active.
this._renderer.context.font = '30px kenvector_futureregular';
// Set the reference position of the player and computer entities
// to that of the maze, shifted up some cell so that they appear in
// the virtual cell on top of the maze.
......@@ -254,7 +262,7 @@ module nurdz.game
case 191:
// If we're in debugging mode, don't handle the key here and
// let the debug code handle it instead.
if (this._maze.debugger.debugTracking)
if (this._debugger.debugTracking)
return false;
// Get the AI to select a ball. If one was selected, jump
......@@ -308,8 +316,12 @@ module nurdz.game
// Trigger a new maze generation.
case KeyCodes.KEY_G:
this._maze.generateMaze ();
return true;
if (this._debugger.debugTracking)
{
this._maze.generateMaze ();
return true;
}
return false;
// Toggle mouse tracking of the debug location, then update the
// tracking with the last known mouse location.
......@@ -430,7 +442,7 @@ module nurdz.game
// If we're tracking a debug location, tell the maze about this
// point.
if (this._maze.debugger.debugTracking)
if (this._debugger.debugTracking)
this._maze.setDebugPoint (this._mouse);
// We handled it.
......@@ -465,6 +477,9 @@ module nurdz.game
// entities get painted.
this._renderer.fillRect (0, 0, this._stage.width, this._stage.height, '#000');
super.render ();
// Now render the score.
renderScores (this._renderer);
}
/**
......@@ -504,14 +519,24 @@ module nurdz.game
* 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
* The owner of the ball can be determined from the ball entity itself
* while isFinal tells you if the ball finished dropping as part of a
* regular or final ball drop.
*
* @param {Ball} ball the ball that stopped dropping
* @param {boolean} isFInal true if this ball was part of a final ball
* drop
*/
ballDropComplete (ball : Ball) : void
ballDropComplete (ball : Ball, isFinal : boolean) : void
{
// Did the ball reach the goal? This is good enough for testing.
// Did the ball reach the goal?
if (ball.mapPosition.y == MAZE_HEIGHT - 2)
console.log ("GOOOOOAL!");
goalBallScore (ball);
// The ball did not reach the goal, but if this is a final ball drop
// then score partial points for the ending position of the ball.
else if (isFinal == true)
partialBallScore (ball);
// Now that the ball is done, where we go depends on where we came
// from.
......@@ -556,7 +581,9 @@ module nurdz.game
*/
blockedBallRemoved (ball : Ball) : void
{
console.log("Removing blocked ball at " + ball.mapPosition.toString ());
// This is a blocked ball that can no longer move, so apply a
// partial score value now.
partialBallScore (ball);
}
/**
......