t2dTileLayer loaded by script in Tetris game
by Pedro Vicente · in Torque Game Builder · 01/17/2010 (11:33 pm) · 9 replies
Hello everyone
I am building a Tetris game and in the process learning TGB.
I started by defining the tetrominoes (the tetris shapes) in the TGB editor as a 4X4 matrix of tiles, by filing only some matrix positions with frames from an image, for example, for the "I" tetrominoe
0 2 0 0
0 2 0 0
0 2 0 0
0 2 0 0
this generates the following code in the .t2d level file
On start I have this tilemap loaded on my scene

Then I added a class for this definition
and an onAdd function to that class
so that I can have control over this object in the main game class TetrisGame, like defining functions.
Then I tried instead of having the t2dTileLayer defined on the scene, having it defined by script on the main class
I got some tips from this forum
www.torquepowered.com/community/forums/viewthread/78502
and based on this, I moved the t2dTileLayer definition from the level file .t2d to the main class (and removed the OnAdd call)
One thing to notice is that the tilemap appears now in another position.

I then defined a Draw() function
The shapes are drawn by iterating over the 4X4 array and calling setStaticTile for the positions that are "filled" (the blue tile drawn at [0,0] is only for debugging purposes)
Calling this on the main class
The shape is drawn at the position I defined ,
but the one created in TetrisGame::CreateShape is *also* drawn

So, my question is: How can I get rid of the "first" shape?
It seems that this call
should "point" only to the shape drawn relative to the WallTileMap map (that defines the walls)
I am constructing my game based in an old tutorial, but experimenting with other solutions in the way
tdn.garagegames.com/wiki/Torque_2D/Getting_Started/T2DTetrisTutorial
Thanks for reading
I am building a Tetris game and in the process learning TGB.
I started by defining the tetrominoes (the tetris shapes) in the TGB editor as a 4X4 matrix of tiles, by filing only some matrix positions with frames from an image, for example, for the "I" tetrominoe
0 2 0 0
0 2 0 0
0 2 0 0
0 2 0 0
this generates the following code in the .t2d level file
new t2dTileLayer() {
LayerFile = "~/RewardGames/TetrisGame/tilemaps/red_I.lyr";
canSaveDynamicFields = "1";
Position = "-22.000 -27.000";
size = "16.000 16.000";
CollisionCallback = "1";
CollisionMaxIterations = "1";
mountID = "3";
};On start I have this tilemap loaded on my scene

Then I added a class for this definition
new t2dTileLayer() {
...
class = "Shape";
...
};and an onAdd function to that class
function Shape::onAdd(%this )
{
TetrisGame.shape = %this;
}so that I can have control over this object in the main game class TetrisGame, like defining functions.
Then I tried instead of having the t2dTileLayer defined on the scene, having it defined by script on the main class
I got some tips from this forum
www.torquepowered.com/community/forums/viewthread/78502
and based on this, I moved the t2dTileLayer definition from the level file .t2d to the main class (and removed the OnAdd call)
function TetrisGame::CreateShape( %this )
{
%shape = new t2dTileLayer() {
LayerFile = "~/RewardGames/TetrisGame/tilemaps/red_I.lyr";
canSaveDynamicFields = "1";
class = "Shape";
Position = "-4.930 -26.937";
size = "16.000 16.000";
CollisionCallback = "1";
CollisionMaxIterations = "1";
mountID = "3";
};
sceneWindow2D.getSceneGraph().getGlobalTileMap().addTileLayer( %shape );
%shape.loadTileLayer( %shape.layerFile );
%shape.position = TetrisGame.ShapeStartingPosition;
%shape.Define();
%this.shape = %shape;
}One thing to notice is that the tilemap appears now in another position.

I then defined a Draw() function
The shapes are drawn by iterating over the 4X4 array and calling setStaticTile for the positions that are "filled" (the blue tile drawn at [0,0] is only for debugging purposes)
function Shape::Draw(%this)
{
%xPos = getWord(%this.position,0);
%yPos = getWord(%this.position,1);
// draw a blue tile at matrix (0,0)
WellTileMap.setStaticTile( %xPos, %yPos, TetrisBlocksImageMap, 1 );
// call setStaticTile for every array position that is filled
for ( %x = 0; %x < %this.sizex; %x++ )
{
for ( %y = 0; %y < %this.sizex; %y++ )
{
if( %this.block[ %x , %y] != 0 )
{
%frame = %this.block[ %x ,%y ];
//setStaticTile parameters
// tileX: The X coordinate of the tile to set
// tileY: The Y coordinate of the tile to set
// imageMapName: The imagemap to set the tile to frame:
// The frame of the imagemap to use
%tileX = %x + %xPos;
%tileY = %y + %YPos;
WallTileMap.setStaticTile( %tileX, %tileY, TetrisBlocksImageMap, %frame );
}
}
}
}Calling this on the main class
function TetrisGame::onLevelLoaded( %this, %scenegraph )
{
%this.CreateShape();
%this.shape.Draw();
}The shape is drawn at the position I defined ,
%shape.position = TetrisGame.ShapeStartingPosition;
but the one created in TetrisGame::CreateShape is *also* drawn

So, my question is: How can I get rid of the "first" shape?
It seems that this call
%this.shape.Draw();
should "point" only to the shape drawn relative to the WallTileMap map (that defines the walls)
I am constructing my game based in an old tutorial, but experimenting with other solutions in the way
tdn.garagegames.com/wiki/Torque_2D/Getting_Started/T2DTetrisTutorial
Thanks for reading
#2
TetrisGame.ShapeStartingPosition is defined at the upper middle of the wall. The wall is 12X18, so the blue tile of the shape is drawn at (6,0)
01/17/2010 (11:39 pm)
TetrisGame.ShapeStartingPosition is defined at the upper middle of the wall. The wall is 12X18, so the blue tile of the shape is drawn at (6,0)
#3
01/18/2010 (9:01 am)
Hey, pedro, I'm still processing your post, but first, you can edit your forum posts by clicking the icon that resembles a pencil in the upper right of the post to edit
#4
2) In "CreateShape" you are loading in a t2dTileLayer which is displayed by TGB
then in "Draw" you are modifying your wall layer to have tiles that resemble the "Shape" you loaded in as a t2dTileLayer, so in screen shot 4, the top image is merely tiles on the "wall tile layer", while the layer you loaded in is at position 0,0 (which is the center of the screen)

3) Are you intending for the motion to be smooth or are you intending for the shape to move by having the tiles change on the wall tile layer?
01/18/2010 (9:13 am)
1) what is the definition of TetrisGame.ShapeStartingPosition2) In "CreateShape" you are loading in a t2dTileLayer which is displayed by TGB
then in "Draw" you are modifying your wall layer to have tiles that resemble the "Shape" you loaded in as a t2dTileLayer, so in screen shot 4, the top image is merely tiles on the "wall tile layer", while the layer you loaded in is at position 0,0 (which is the center of the screen)

3) Are you intending for the motion to be smooth or are you intending for the shape to move by having the tiles change on the wall tile layer?
#5
2) that' right. Having the "shape" tiles drawn in the "wall tile layer" is convenient because I have a coordinate system relative to the wall, so I can do all the game logic based on that.
3) For the shape to move by having the tiles change on the wall tile layer. I intend the shapes to fall at every time step. For example, by a schedule function that moves it in the Y axis 1 position every second.
For this to work, the previous shape has to be erased
01/18/2010 (12:28 pm)
thanks, David. A reply to 1) is posted in #1 and #2.2) that' right. Having the "shape" tiles drawn in the "wall tile layer" is convenient because I have a coordinate system relative to the wall, so I can do all the game logic based on that.
3) For the shape to move by having the tiles change on the wall tile layer. I intend the shapes to fall at every time step. For example, by a schedule function that moves it in the Y axis 1 position every second.
For this to work, the previous shape has to be erased
function TetrisGame::Fall( %this )
{
%this.shape.Move( 0, 1);
%this.shape.Draw();
%this.schedule( 1000, Fall );
}
function Shape::Move(%this, %dx, %dy)
{
%x = getWord( %this.position, 0 );
%y = getWord( %this.position, 1 );
%this.position = %x + %dx SPC %y + %dy;
}
#6
that way you'll only see the Wall layer that'll display what you set in "Draw"
additionally, there's a lot of extra code and processing associated with tileLayers (since they can be displayed and such)
you may want to consider creating your shapes in text files that you read in and store as arrays rather than whole tile layers per shape
01/18/2010 (2:13 pm)
ah well, to remove the original shape layer, you can just set %shape.visible = false;whenever you create a shape
that way you'll only see the Wall layer that'll display what you set in "Draw"
additionally, there's a lot of extra code and processing associated with tileLayers (since they can be displayed and such)
you may want to consider creating your shapes in text files that you read in and store as arrays rather than whole tile layers per shape
#7
01/18/2010 (7:00 pm)
You could replace the Move code through a single line by the way:%this.position = t2dVectorAdd( %this.position, "0 1" );
#8
thanks, I could, but I am learning Torque Script, and I like to keep things simple, C/C++ like syntax. I defined the shape position with 2 variables for the (X,Y) position instead.
01/19/2010 (12:21 am)
@Markthanks, I could, but I am learning Torque Script, and I like to keep things simple, C/C++ like syntax. I defined the shape position with 2 variables for the (X,Y) position instead.
function Shape2::Move(%this, %dx, %dy)
{
%this.PositionX = %this.PositionX + %dx;
%this.PositionY = %this.PositionY + %dy;
}
#9
you are right on spot, I don't need my shapes to be t2dTileLayer instances at all, with the overhead that comes with it. I was doing so because I defined the shapes in the TGB editor as 4X4 tilemaps and saved them to tilemap files. The block matrix was being initiated for a shape by reading each frame from the file
but this matrix array information can be instead defined simply by script. This thread shows how to define a OOP style Torque Script class
www.torquepowered.com/community/forums/viewthread/27384
and based on this I defined a new class for the shapes, based in the ScriptObject class. Nice to know that there is a constructor/destructor mechanism in Torque
The shape instance is then initialized as
01/19/2010 (12:49 am)
@Davidyou are right on spot, I don't need my shapes to be t2dTileLayer instances at all, with the overhead that comes with it. I was doing so because I defined the shapes in the TGB editor as 4X4 tilemaps and saved them to tilemap files. The block matrix was being initiated for a shape by reading each frame from the file
%type = %this.getTileType(%x, %y); // index of frame in image map // format is "static imageMapName imageMap-Frame" %frame = getword( %type, 2); %this.block[%x, %y] = %frame;
but this matrix array information can be instead defined simply by script. This thread shows how to define a OOP style Torque Script class
www.torquepowered.com/community/forums/viewthread/27384
and based on this I defined a new class for the shapes, based in the ScriptObject class. Nice to know that there is a constructor/destructor mechanism in Torque
function Shape::onAdd(%this)
{
// set the starting position to the middle of the wall
%this.PositionX = WellTileMap.getTileCountX() / 2;
%this.PositionY = 0;
// size of each block
%this.SizeX = 4;
%this.SizeY = 4;
for( %x = 0; %x < %this.SizeX; %x++)
{
for( %y = 0; %y < %this.SizeY; %y++)
{
%this.block[%x, %y] = 0;
}
}
// red_I is defined as, 2 is the frame index in the blocks image
// 0 2 0 0
// 0 2 0 0
// 0 2 0 0
// 0 2 0 0
%this.block[1,0] = 2;
%this.block[1,1] = 2;
%this.block[1,2] = 2;
%this.block[1,3] = 2;
}
function Shape::onRemove(%this)
{
}
function Shape::Move(%this, %dx, %dy)
{
%this.PositionX = %this.PositionX + %dx;
%this.PositionY = %this.PositionY + %dy;
}
function Shape::Draw(%this)
{
// draw a blue tile at current position
WellTileMap.setStaticTile( %this.PositionX, %this.Positiony, TetrisBlocksImageMap, 1 );
// call setStaticTile for every array position that is filled
for ( %x = 0; %x < %this.SizeX; %x++ )
{
for ( %y = 0; %y < %this.SizeX; %y++ )
{
if( %this.block[ %x, %y ] != 0 )
{
%frame = %this.block[ %x, %y ];
//setStaticTile parameters
// tileX: The X coordinate of the tile to set
// tileY: The Y coordinate of the tile to set
// imageMapName: The imagemap to set the tile to frame:
// The frame of the imagemap to use
%tileX = %this.PositionX + %x;
%tileY = %this.PositionY + %y;
WellTileMap.setStaticTile( %tileX, %tileY, TetrisBlocksImageMap, %frame );
}
}
}
}The shape instance is then initialized as
function TetrisGame::onLevelLoaded( %this, %scenegraph )
{
// create a shape
%shape = new ScriptObject(Shape)
{
};
%shape.Draw();
%this.shape = %shape;
%this.Fall();
}
Torque 3D Owner Pedro Vicente
Space Research Software LLC
function TetrisGame::onLevelLoaded( %this, %scenegraph ) { // set the starting position to the middle of the wall %this.ShapeStartingPosition = WellTileMap.getTileCountX()/2 SPC 0; // create the tetromimoes %this.CreateShapes(); // draw a first shape in the wall %this.shape.Draw(); // start %this.Fall(); }