Sunday, 25 August 2013

Tetris-like wall-kicking not working

Tetris-like wall-kicking not working

So I'm making a falling-block puzzle game. It's not a Tetris clone, but
the block clusters move in a similar fashion. I want to make it so that if
you rotate against a wall, or against another piece, it pushes you back
and rotates the cluster if it's possible, or does nothing if not. This is
called wall-kicking in Tetris, I think. Problem is, I can't seem to get it
to work. The simplest algorithm I've heard of is to check if it's possible
to move left or right. If you can do either, then rotate the block. But
then I can't rotate at the edge of the grid.
I have the rotation itself working (both on-screen and the grid position
representation), and I can stop a cluster from moving if it's at the edge
of the grid. It's rotating at the edges that gets me.
These are the assumptions my game makes;
There are many types of individual blocks, so hard-coding anything
probably isn't an option.
Each block cluster has exactly three connected blocks, with two possible
configurations (assuming rotations are considered equal); I-like and
J-like.
For each block cluster, there is one block in the center that the other
two rotate around. Assuming no wall-kicking, this one never moves when the
cluster is rotated.
The playing field is eight blocks wide and thirteen blocks tall.
After the cluster lands, the blocks will fall down Puyo-Puyo style, i.e.
you won't have to navigate around hanging pieces like in Tetris.
This is my code, written in Haxe;
class BlockMovementSystem extends System {
private var cluster : BlockCluster;
private var delay : TimeDelay;
private var grid : EntityGrid;
private var nextAction : NextAction;
public function new(grid:EntityGrid, cluster:Entity) {
super();
this.cluster = cluster.get(BlockCluster);
this.delay = cluster.get(TimeDelay);
this.grid = grid;
this.nextAction = NextAction.None;
}
public override function update(time:Float) : Void {
var center : Entity = this.cluster.blocks[1];
var blockSize : GridMotion = center.get(GridMotion);
switch (this.nextAction) {
case MoveLeft:
if (this.canMoveLeft()) {
for (i in this.cluster.blocks) {
var gpos : GridPosition = i.get(GridPosition);
var block_left : Entity = {
if (gpos.x > 0)
this.grid.entities.get(gpos.x - 1, gpos.y)
else
null;
};
if (gpos.x > 0 || block_left != null) {
var pos : Positionable = i.get(Positionable);
pos.position.x -= blockSize.cell_size.x;
gpos.x -= 1;
}
}
}
case MoveRight:
if (this.canMoveRight()) {
for (i in this.cluster.blocks) {
var gpos : GridPosition = i.get(GridPosition);
var block_right : Entity = {
if (gpos.x < Constants.GRID_WIDTH - 1)
this.grid.entities.get(gpos.x + 1, gpos.y)
else
null;
};
if (gpos.x < Constants.GRID_WIDTH - 1 &&
block_right == null) {
var pos : Positionable = i.get(Positionable);
pos.position.x += blockSize.cell_size.x;
gpos.x += 1;
}
}
}
case Rotate:
if (this.canMoveRight() || this.canMoveLeft()) {
var origin : Vector = center.get(Positionable).position;
var origincell : GridPosition = center.get(GridPosition);
for (i in this.cluster.blocks) {
if (i != center) {
var p : Vector = i.get(Positionable).position;
var x : Float = origin.x - (origin.y - p.y);
var y : Float = origin.y - (p.x - origin.x);
p.x = x;
p.y = y;
var g : GridPosition = i.get(GridPosition);
var gx : Int = origincell.x - (origincell.y -
g.y);
var gy : Int = origincell.y - (g.x -
origincell.x);
g.x = gx;
g.y = gy;
}
}
}
}
}
private function canMoveLeft() : Bool {
for (i in this.cluster.blocks) {
var gpos : GridPosition = i.get(GridPosition);
var block_left: Entity = {
if (gpos.x > 0)
this.grid.entities.get(gpos.x - 1, gpos.y)
else
null;
};
if (gpos.x <= 0 || block_left != null) {
//If the edge of the grid or another block is to the left of
this block...
return false;
}
}
return true;
}
private function canMoveRight() : Bool {
for (i in this.cluster.blocks) {
var gpos : GridPosition = i.get(GridPosition);
var block_right : Entity = {
if (gpos.x < Constants.GRID_WIDTH - 1)
this.grid.entities.get(gpos.x + 1, gpos.y)
else
null;
};
if (gpos.x >= Constants.GRID_WIDTH - 1 || block_right != null) {
//If the edge of the grid or another block is to the right of
this block...
return false;
}
}
return true;
}
}
Any tips?

No comments:

Post a Comment