Using Entities in a Tetris-style game


(Scott Thiessen) #1

Hi all. I’m new to FlashPunk and trying to get my head around The FlashPunk Way here.

I’m working on a Tetris-style game, and I’m having trouble figuring out how to use the Entity class.

I imagined I could make an Entity composed of other Entities (e.g., in Tetris, a Piece could be composed of multiple Blocks), but it doesn’t seem Entities can contain other Entities. Is that right?

I then just figured I’d just redraw my Piece Entity each time I needed to (e.g., when you rotate the piece) using blocks as graphics. However, I’m not really finding a good way to redraw an Entity either, other than using a sprite-sheet. And putting all the rotations of all the possible pieces in a sprite-sheet seems pretty cumbersome compared to just arranging the blocks in code.

Because the falling piece is not a character or static object but rather a kind of amorphous and changing group of blocks, I’m not sure how to set it up in the context of FlashPunk.

Any thoughts? Is an Entity the right way to go for this, or am I missing something else?

Cheers and thanks! Scott


(Scott Thiessen) #2

I’m just noticing the Tilemap class. Would this maybe be the way to go for something like this?


(Jacob Albano) #3

Tilemaps can’t be rotated, so if you decided to use them you’d have to redraw them each time the object updated.

I would personally approach this as you said first; as a group of entities that are positioned by a parent/manager entity. Flashpunk doesn’t have support for this directly, but you can always work around that:

public class GroupEntity extends Entity
{
    public var subEntities:Array;
    public function GroupEntity()
    {
        subEntities = [];
    }

    override public function added():void
    {
        world.addList(subEntities);
    }

    override public function removed():void
    {
        world.removeList(subEntities);
    }
}

I have something like this in a tiny framework I hacked together on a project where I have to use the display list. I have functions to add and remove sub-entities, with a parameter to determine whether they are also removed from the world, so I can effectively detach entities from their parent without removing them from the world.

e.removeSubEntity(something, false); // don't remove it from the world

It sounds like something like that might be helpful for you, especially if you’ll have blocks separating from the main body.


(Scott Thiessen) #4

That sounds like a great solution. Then, I’d be able to pull the blocks out of the piece when they hit the bottom.

That code will help get me going. Thanks!


(Zachary Lewis) #5

I feel like using entities for the pieces is not the right technique to solve this problem. I’d use an Entity to represent each block.

Thinking of Tetris, pieces are groups of four blocks, and the field is a grid. Each of the seven pieces has a unique block color.

The only control is moving the active piece left and right or rotating it. Blocks cannot leave the grid.

When a piece lands, if a row is full, all the blocks in that row are removed and the row is removed.

When abstracted out, all of the gameplay takes place in a 2-dimensional array. Each element of the array is either null or contains a Block. A GameWorld should supply the input handling and game loop logic. I’d recommend a few helper functions in GameWorld to help you manage blocks, such as createBlock, removeBlock and clearRow.

Here’s an example of the functionality that would be ideal to consolidate.

public class GameWorld extends World
{
  /**
   * Create a block at the grid location.
   * @param   x The column to create the block in.
   * @param   y The row to create the block in.
   * @param   type The type of block to create.
   */
  public function createBlock(x:uint, y:uint, type:uint)
  {
    // Perform error checking to make sure x and y are within bounds.
    if (x < gameField.length && y < gameField[x].length)
    {
      // Get a fresh block.
      var freshBlock:Block = Block(create(Block, true));

      /* Set new block properties.
       * blockWidth and blockHeight are the dimensions of the blocks.
       * columnOffset and rowOffset are the offset of the game field on the screen.
       */
      freshBlock.x = x * blockWidth + columnOffset;
      freshBlock.y = y * blockHeight + rowOffset;
      freshBlock.setType(type);

    // If a stale block exists at the grid location, remove it.
    if (gameField[x][y] != null)
    {
      recycle(gameField[x][y]);
    }

    // Store the fresh block in the grid.
    gameField[x][y] = freshBlock;
  }
}

I believe this is the best approach to creating a Tetris-style game.


(Scott Thiessen) #6

That makes sense, yeah. Much simpler. I could just keep track of the ‘active piece’ with an array of four of the blocks. Thanks @zachwlewis.