deleting items from 2d arrays
Jarrett Billingsley
jarrett.billingsley at gmail.com
Thu Aug 13 20:52:50 PDT 2009
On Thu, Aug 13, 2009 at 10:59 PM, Michael P.<baseball.mjp at gmail.com> wrote:
> Okay, so I'm making a breakout type game in D. Using Derelict.
> I have a 2d array of Block type variables(not important what's in them) declared like this:
> Block[][] level;
> and later load into like this:
> level = loadLevel( "levels.txt", levelNumber );
> Anyways, what I want to do is that when the ball hits one of the blocks in the array, I remove it. When a line no longer has any blocks in it, I remove that line/row. When there are no more lines, I load the next level.
> Any ideas on how I could achieve this?
>
> foreach( Block[] ba; level )
> {
> foreach( Block b; ba )
> {
> if( checkCollision( ball, b.p ) )
> {
> //remove the block??
> }
> }
> }
>
> The level array has 12 lines of 'x' amount of bricks. x can be as great as 10.
Okay. First you need a remove function to take lines out of the
array. Here's a general one:
import std.c.string; // phobos
import tango.stdc.string; // tango
void remove(T)(ref T[] arr, size_t idx)
{
assert(arr.length > 0);
if(idx == 0)
arr = arr[1 .. $];
else if(idx == arr.length - 1)
arr = arr[0 .. $ - 1];
memmove(&arr[idx], &arr[idx + 1], T.sizeof * (arr.length - idx - 1));
arr = arr[0 .. $ - 1];
}
You use it like arr.remove(idx) (or alternately, remove(arr, idx)) and
the given element will be removed, everything after it will be shifted
down a slot, and the length of the array will be reduced by one.
Now you need to do collision with the blocks. If Block is a class, we
can use 'null' in the array to indicate that there is not block there;
if it's a struct, you'll have to keep an 'active' member in the struct
or somesuch. Either way, a quadratic algorithm for detecting
collision probably isn't necessary. You can calculate which blocks
the ball is near with a little math.
const BlockHeight = 24; // fill these in
const BlockWidth = 60; // with whatever you're using
void checkRemoveLine(int row)
{
foreach(ref b; level[row])
if(b.active)
return;
// none of the blocks were active
level.remove(row);
}
void removeBlock(int row, int col)
{
level[row][col].active = false;
checkRemoveLine(row);
}
void collidePoint(int x, int y)
{
auto row = y / BlockHeight;
auto col = x / BlockWidth;
// assuming Block is a struct..
if(row < level.length && level[row][col].active)
removeBlock(row, col);
}
const BallDiam = 10; // this makes the ball 10 pixels across
const HalfBallDiam = BallDiam / 2;
void collide(Ball ball)
{
// collide all four corners of the ball's colbox
collidePoint(ball.x + HalfBallDiam, ball. y + HalfBallDiam);
collidePoint(ball.x - HalfBallDiam, ball. y + HalfBallDiam);
collidePoint(ball.x - HalfBallDiam, ball. y - HalfBallDiam);
collidePoint(ball.x + HalfBallDiam, ball. y - HalfBallDiam);
}
Your main game loop would probably look something like this:
foreach(levelFile; levelFiles)
{
level = loadLevel(levelFile); // load the level array
// while there are still lines..
while(level.length > 0)
{
getUserInput();
updateStuff();
doCollision(); // ball runs into things yay
drawGraphics();
}
}
Well this has ended up being a bit long ;)
More information about the Digitalmars-d-learn
mailing list