TGB/Tutorials/Fill Battle/Creating The Game
From TDN
[edit] Defining the Game Flow, Part 1To make the game, we’ll need to start thinking about what happens. When the user selects a color, we need to change the upper left-hand corner to that color and all other tiles adjacent to it that also match the color. This logic is a little tricky. What we are going to use here is a stack. [edit] What Is A Stack?(You can skip this section if you don’t care about what a stack is and does.) A stack is a data structure where the last thing put on it is the first thing that comes off. (You can go to Wikipedia to learn gory details.) Imagine it as a stack of note cards. We can write on a note card and put it on the stack. We can also take a note card off the stack and read it. In TorqueScript, you can write it like this:
function Stack::onAdd( %this )
{
%this.len = 0;
}
function Stack::push( %this, %val )
{
%this.v[%this.len] = %val;
%this.len++;
}
function Stack::pop( %this )
{
if( %this.len == 0 )
{
error( "Stack Underflow." );
return "";
}
%this.len--;
return %this.v[%this.len];
}
Whenever we create a new stack, the “::onAdd” function gets called. So if we did this: %locations = new Stack(); Then “::onAdd” would get called where “%this” would be equal to “%locations”. It would then set the length of the stack (or height) to zero. We can then “push” a card onto the top of the stack or we can “pop” the top-most card off of the stack and read what’s on it. So if we did this: %locations = new Stack(); %locations.push( 1 ); %locations.push( 2 ); %a = %locations.pop(); %b = %locations.pop(); Then “%a” would equal “2” and “%b” would equal “1”. We’re using some TorqueScript magic here by dynamically creating variables. “len” is the size of the stack. “v” is an array that has the cards. So “v[0]” is the bottom card, “v[1]” is on top of that, “v[2]” is on top of “v[1]”, and so on. When we “push” a card onto the stack, we put it at “v[0]” and then increase the length/height of the stack by 1. The next push will then put the card at “v[1]” and then increase the length/height by 1. “pop” does the opposite. It reduces the length/height by 1 and returns the top-most card. So if our height was 1 and we called “pop”, we’d reduce the length/height to 0 and return “v[0]”. We do a little error checking in “pop”. If our length/height is zero, we return a blank string and print out an error message into the console. [edit] Defining the Game Flow, Part 2Here’s the general flow we’re trying to create:
[edit] Scripting the Game FlowSo how does that look in code? Look at the modified Button code below (read the comments carefully):
function Stack::onAdd( %this )
{
%this.len = 0;
}
function Stack::push( %this, %val )
{
%this.v[%this.len] = %val;
%this.len++;
}
function Stack::pop( %this )
{
if( %this.len == 0 )
{
error( "Stack Underflow." );
return "";
}
%this.len--;
return %this.v[%this.len];
}
function Button::onMouseUp( %this, %modifier, %worldPosition, %clicks )
{
// Used to check the boundaries of the tile map
%width = TileBoard.getTileCountX();
%height = TileBoard.getTileCountY();
// Read the button to get the color that the user clicked on.
%newColor = %this.getFrame(); // or use %this.color;
// This returns the string "static IMAGEMAP FRAME#".
// Word 0 is "static".
// Word 1 is the ImageMap.
// Word 2 is the frame number.
%upperLeftTileType = TileBoard.getTileType( 0, 0 );
%oldColor = getWord( %upperLeftTileType, 2 );
// Create the stack.
%locStack = new ScriptObject() { class = Stack; };
// Put the upper left-hand corner onto the stack.
%locStack.push( "0 0" );
while( %locStack.len > 0 ) // While there are ANY cards on the stack
{
// Remove and read the top card.
%topCard = %locStack.pop();
// Get the x-coordinate and y-coordinate off the text on that card.
%xCoord = getWord( %topCard, 0 );
%yCoord = getWord( %topCard, 1 );
// Change that location to the new color.
TileBoard.setStaticTile( %xCoord, %yCoord, SixColorsImageMap, %newColor );
// If we aren't on the left-hand side of the board
if( %xCoord > 0 )
{
// Look at the tile to the left of us.
%leftTileType = TileBoard.getTileType( %xCoord - 1, %yCoord );
%leftColor = getWord( %leftTileType, 2 );
// If it matches the old color, put it's location on the stack.
if( %leftColor == %oldColor )
{
// If %xCoord were 5 and %yCoord were 7, then we'd create a new
// string by putting together the number 4 with a space (SPC) and
// the number 7. This would result in "4 7" to be written on the card.
%locStack.push( (%xCoord - 1) SPC %yCoord );
}
}
// If we aren't on the right-hand side of the board
if( %xCoord < %width - 1 )
{
// Look at the tile to the right of us.
%rightTileType = TileBoard.getTileType( %xCoord + 1, %yCoord );
%rightColor = getWord( %rightTileType, 2 );
// If it matches the old color, put it's location on the stack.
if( %rightColor == %oldColor )
{
%locStack.push( (%xCoord + 1) SPC %yCoord );
}
}
// If we aren't at the top of the board...
if( %yCoord > 0 )
{
%upTileType = TileBoard.getTileType( %xCoord, %yCoord - 1 );
%upColor = getWord( %upTileType, 2 );
if( %upColor == %oldColor )
{
%locStack.push( %xCoord SPC (%yCoord - 1) );
}
}
// If we aren't at the bottom of the board...
if( %yCoord < %height - 1 )
{
%downTileType = TileBoard.getTileType( %xCoord, %yCoord + 1 );
%downColor = getWord( %downTileType, 2 );
if( %downColor == %oldColor )
{
%locStack.push( %xCoord SPC (%yCoord + 1) );
}
}
}
%locStack.delete();
}
That’s it! Save, run, and play! The game’s complete! [edit] Complete! |



