So, I've been working on a Breakout game based on this.

Here is a screenshot of a decent-working version:


And here is a screenshot of one that freezes on a white screen when exiting and then resets the calc:


I would like some help as to why it is freezing. Also, it sometimes replaces the first few colors of the side bars with bright red, if that info helps any.

You can find my source here.

Also, if you notice, the flashing tiles are supposed to explode all the ones surrounding it, and if it explodes another flashing one, it's supposed to continue until it runs out of flashing tiles. Every time I try to implement this, though, it just freezes the calc and I'm forced to exit CEmu altogether. Any advice on this would be nice as well.

All help is appreciated! Very Happy

Edit:
Here's a gif with the red lines and resetting at the end:


I'm pretty sure my errors have to do with my function to "explode" the surrounding tiles. I'm just not sure why. Confused
The first main problem I see is in this function:


Code:
void TileExplode(int i, int j){
   for( k = 0; k < 3; k++ ) {
      for( l = 0; l < 3; l++ ) {
         Tiles[(i - 1) + k][(j - 1) + l] = 0;
      }
   }
}


There's no bounds checking. Razz Thus you will be writing random data to who knows where.

That's probably what is causing all the issues, so if you fix that, it should be fine. Good luck, this is looking really cool Smile Also, it might be better to have the sides colors be a global or declared as static, as it has to allocate room for it on the stack which is kind of wasteful Razz
Looks pretty good! It's really smooth. Very Happy
MateoConLechuga wrote:
The first main problem I see is in this function:


Code:
void TileExplode(int i, int j){
   for( k = 0; k < 3; k++ ) {
      for( l = 0; l < 3; l++ ) {
         Tiles[(i - 1) + k][(j - 1) + l] = 0;
      }
   }
}


There's no bounds checking. Razz Thus you will be writing random data to who knows where.

That's probably what is causing all the issues, so if you fix that, it should be fine. Good luck, this is looking really cool Smile Also, it might be better to have the sides colors be a global or declared as static, as it has to allocate room for it on the stack which is kind of wasteful Razz


Thanks! Very Happy I got it fixed now (also updated the code on github):


Dudeman313 wrote:
Looks pretty good! It's really smooth. Very Happy


Thanks! Razz

I tried getting the chain reaction thing working, but I couldn't do it. It either just wouldn't happen, or it would freeze the calc (no debug menu, though). I tried nesting the function inside istelf, which I don't even know if that's allowed. If anyone could help with that, it would be cool. Smile

Edit: Also, if you guys have any suggestions for better ball/tile collision (with detecting each side and changing velocity accordingly), I'm all ears. Razz
Oh, DX-Ball!! This is a very nice game, and in the past I played it too much Razz
I remember me that I once made this in Processing, but without colors.
Anyway, ball/tile collision was the hardest part for me, and that is why I don't succeeded it. An idea for the chain reaction is this in pseudocode. Use a very simple stack:

Code:
If ball hit tile {
  array explodes[] = tile_positions.
  while array!=empty {
    var first_tile = explodes[0];
    if first_tile == exploder {
      for all the 8 neighbors {
        if neighbor exists: explodes.push(neighbor.position)
      }
    }
    remove first_tile
  }
}

I hope this works and good luck on finishing this! Smile
PT_ wrote:
Oh, DX-Ball!! This is a very nice game, and in the past I played it too much Razz
I remember me that I once made this in Processing, but without colors.
Anyway, ball/tile collision was the hardest part for me, and that is why I don't succeeded it. An idea for the chain reaction is this in pseudocode. Use a very simple stack:

Code:
If ball hit tile {
  array explodes[] = tile_positions.
  while array!=empty {
    var first_tile = explodes[0];
    if first_tile == exploder {
      for all the 8 neighbors {
        if neighbor exists: explodes.push(neighbor.position)
      }
    }
    remove first_tile
  }
}

I hope this works and good luck on finishing this! Smile


Thanks! But I'm not quite sure how I could implement this in my code. Razz Could you explain how it works for me? What is "explodes.push(neighbor.position)" and what is the purpose of the "explodes[]"?
Ok, I will try it in more pseudocode Razz

Code:
If the ball hits a tile {
  define an array/list with one element: the position of that tile
  while that array/list is not empty {
    get the first element of our array/list
    If ^ is an exploder {
      Check for all neighbors if they exists, and if so, add them to the array/list
    }
    remove the first element and overdraw it
  }
}

Hope this is better Razz
Okay, I'm still having trouble, though I do understand it now.

Here's my function in C so far:

Code:
void TileExplode(int i, int j){
   int m = 0, n = 0, o = 0;
   int TilePos[2] = {99, 99};
   int TilePosX[50][9];
   int TilePosY[50][9];
   int TileX, TileY;
   TilePos[0] = i;
   TilePos[1] = j;
   while(TilePos[0] != 99 && TilePos[1] != 99 && n < 9){
      TileX = TilePos[0];
      TileY = TilePos[1];
      if(Tiles[TileX][TileY] == 4){
         for( k = 0; k < 3; k++ ) {
            for( l = 0; l < 3; l++ ) {
               if((((TileX - 1) + k) <= 17 && ((TileY - 1) + l) <= 19 && ((TileX - 1) + k) >= 0 && ((TileY - 1) + l) >= 0)) {
                  TilePosX[n][m++] = (TileX - 1) + k;
                  TilePosY[n][m++] = (TileY - 1) + l;
                  Tiles[(TileX - 1) + k][(TileY - 1) + l] = 0;         
               }
            }
         }
      }   
      Tiles[TileX][TileY] = 0;
      TileX = TilePosX[o][n];
      TileY = TilePosY[o][n];
      n++;
   }
}


The problem is that with what you're suggesting, it would involve adding values to the array and making the array bigger, which, in c, is a pain in the butt. If anyone who's good with C could point me in the right direction with this function, it would be greatly appreciated.
*bump*

Could someone help me figure out how to make this recursive:


Code:
void TileExplode(int i, int j){
   for( k = 0; k < 3; k++ ) {
      for( l = 0; l < 3; l++ ) {
         if((((i - 1) + k) <= 17 && ((j - 1) + l) <= 19 && ((i - 1) + k) >= 0 && ((j - 1) + l) >= 0)) {
            Tiles[(i - 1) + k][(j - 1) + l] = 0;         
         }
      }
   }
}


Everything I try seems to freeze the calc. :/
That section of code works, though? How deeply are you recursing? Is it possible you were overflowing the stack?
KermMartian wrote:
That section of code works, though? How deeply are you recursing? Is it possible you were overflowing the stack?


Yeah, probably.
Well, this is how I'm implementing the chain reaction:

Code:

void TileExplode(int i, int j){
   for( k = 0; k < 3; k++ ) {
      for( l = 0; l < 3; l++ ) {
         if((((i - 1) + k) <= 17 && ((j - 1) + l) <= 19 && ((i - 1) + k) >= 0 && ((j - 1) + l) >= 0)) {
            if(Tiles[(i - 1) + k][(j - 1) + l] == 4)
                TileExplode((i - 1) + k, (j - 1) +l);
            Tiles[(i - 1) + k][(j - 1) + l] = 0;         
         }
      }
   }
}


Or something like that. I don't expect that implementation to work super correctly, but I still cannot get it to keep from freezing the calc.
I wonder if you could have an array somewhere with a list of tiles to explode, each frame you'd run through the array once adding the next set of tiles to explode. This way they wouldn't all explode at once and it'd have a chain reaction sort of feeling to it. It'd also be a bit lighter on the stack. Also, should setting the tile to zero be included in the innermost if statement? It should probably also be done before the call to TileExplode, otherwise the tile isn't reset until you've finished running through the entire board, and it's probably getting stuck in a loop as it checks one tile then the next then the original tile and the next tile, since they're never set to 0.
chickendude wrote:
I wonder if you could have an array somewhere with a list of tiles to explode, each frame you'd run through the array once adding the next set of tiles to explode. This way they wouldn't all explode at once and it'd have a chain reaction sort of feeling to it. It'd also be a bit lighter on the stack. Also, should setting the tile to zero be included in the innermost if statement? It should probably also be done before the call to TileExplode, otherwise the tile isn't reset until you've finished running through the entire board, and it's probably getting stuck in a loop as it checks one tile then the next then the original tile and the next tile, since they're never set to 0.


Seems like this did the trick! Big thanks to you! Very Happy

I guess there are some issues with my implementation, but it's a start:


For some reason, it's also deleting some other tiles than the ones that it's supposed to.

Here is my implementation:

Code:
void getNewExpList(int ExpX, int ExpY) {
   if(((ExpX - 1) <= 17) && ((ExpY - 1) <= 19) && ((ExpX - 1) >= 0) && ((ExpY - 1) >= 0)) {
      ExpListX[p][0] = ExpX - 1;
      ExpListY[p][0] = ExpY - 1;
   }
   if((ExpX <= 17) && ((ExpY - 1) <= 19) && (ExpX >= 0) && ((ExpY - 1) >= 0)) {
      ExpListX[p][1] = ExpX;
      ExpListY[p][1] = ExpY - 1;
   }
   if(((ExpX + 1) <= 17) && ((ExpY - 1) <= 19) && ((ExpX + 1) >= 0) && ((ExpY - 1) >= 0)) {
      ExpListX[p][2] = ExpX + 1;
      ExpListY[p][2] = ExpY - 1;
   }
   if(((ExpX - 1) <= 17) && (ExpY <= 19) && ((ExpX - 1) >= 0) && (ExpY >= 0)) {
      ExpListX[p][3] = ExpX - 1;
      ExpListY[p][3] = ExpY;
   }
   if((ExpX <= 17) && (ExpY <= 19) && (ExpX >= 0) && (ExpY >= 0)) {
      ExpListX[p][4] = ExpX;
      ExpListY[p][4] = ExpY;
   }
   if(((ExpX + 1) <= 17) && (ExpY <= 19) && ((ExpX + 1) >= 0) && (ExpY >= 0)) {
      ExpListX[p][5] = ExpX + 1;
      ExpListY[p][5] = ExpY;
   }
   if(((ExpX - 1) <= 17) && ((ExpY + 1) <= 19) && ((ExpX - 1) >= 0) && ((ExpY + 1) >= 0)) {
      ExpListX[p][6] = ExpX - 1;
      ExpListY[p][6] = ExpY + 1;
   }
   if((ExpX <= 17) && ((ExpY + 1) <= 19) && (ExpX >= 0) && ((ExpY + 1) >= 0)) {
      ExpListX[p][7] = ExpX;
      ExpListY[p][7] = ExpY + 1;
   }
   if(((ExpX + 1) <= 17) && ((ExpY + 1) <= 19) && ((ExpX + 1) >= 0) && ((ExpY + 1) >= 0)) {
      ExpListX[p][8] = ExpX + 1;
      ExpListY[p][8] = ExpY + 1;
   }
}

void ExplodePrototype(){
   int ExplodeX, ExplodeY;
   if(sum_of_array(ExpListX[p], 9) != 0 && sum_of_array(ExpListY[p], 9) != 0) {
      for(i = 0; i < 9; i++){
         if(Tiles[ExpListX[p][i]][ExpListY[p][i]] == 10){
            ExplodeX = ExpListX[p][i];
            ExplodeY = ExpListY[p][i];
         }
         Tiles[ExpListX[p][i]][ExpListY[p][i]] = 0;
         ExpListX[p][i] = 0;
         ExpListY[p][i] = 0;
      }
      p = 1 - p;
      getNewExpList(ExplodeX, ExplodeY);
      ExplodePrototype();
   }
}


Also, there's a dramatic speed increase when a lot of the tiles have been destroyed. Any advice on how to regulate that speed?

Edit: Changed to better gif with less frame skipping.
Can you send me the download so I can try the game?
#Tankidaboss wrote:
Can you send me the download so I can try the game?


It's not really playable yet. Sorry. Wink

Now that I've got the SDK working again, I've looked at this again. I'm still looking for some help with collision detection (as in, which side of the block is the ball hitting?) if anyone has any input. Also, could anyone help me in regulating frame-rate? There's the animation that needs it and also when there are less blocks on the board, it starts getting faster. I appreciate any input. Razz
*bump*

In my quest to revive some of my old projects, I thought I could breathe some life into this one. This time, I'm using tilemaps for each level, and so far the performance is much better. I haven't implemented the animated blocks or the "explosions" yet because I'm trying to get the collision detection to work properly first. Right now, this is the behavior I am getting:



I've tried so many different ways of detecting collision, but I can't seem to get it to function as it should. Here is my current code:


Code:
// Check for collisions between the ball and the blocks
struct Block top, bottom, left, right, center;

center.row = (ball.y - Y_OFFSET) / TILE_HEIGHT;
center.col = (ball.x - X_OFFSET) / TILE_WIDTH;
center.value = gfx_GetTileMapped(&tilemap, center.row, center.col);

top.row = (ball.y - Y_OFFSET - ball.radius) / TILE_HEIGHT;
top.col = (ball.x - X_OFFSET) / TILE_WIDTH;
top.value = gfx_GetTileMapped(&tilemap, top.col, top.row);

bottom.row = (ball.y - Y_OFFSET + ball.radius) / TILE_HEIGHT;
bottom.col = (ball.x - X_OFFSET) / TILE_WIDTH;
bottom.value = gfx_GetTileMapped(&tilemap, bottom.col, bottom.row);

left.row = (ball.y - Y_OFFSET) / TILE_HEIGHT;
left.col = (ball.x - X_OFFSET - ball.radius) / TILE_WIDTH;
left.value = gfx_GetTileMapped(&tilemap, left.col, left.row);

right.row = (ball.y - Y_OFFSET) / TILE_HEIGHT;
right.col = (ball.x - X_OFFSET + ball.radius) / TILE_WIDTH;
right.value = gfx_GetTileMapped(&tilemap, right.col, right.row);

// Determine which side of the block the ball hit.
if (top.value) {
   // Top of ball, bottom of the block.
   switch (top.value) {
      case BLOCK_INVISIBLE:
         gfx_SetTileMapped(&tilemap, top.col, top.row, BLOCK_VISIBLE);
         break;
      case BLOCK_BUMPER_1:
         gfx_SetTileMapped(&tilemap, top.col, top.row, BLOCK_BUMPER_2);
         break;
      case BLOCK_BUMPER_2:
         break;
      default:
         gfx_SetTileMapped(&tilemap, top.col, top.row, BLOCK_EMPTY);
         break;
   }
   ball.vy = -ball.vy;
} else if (bottom.value) {
   // Bottom of ball, top of the block.
   switch (bottom.value) {
      case BLOCK_INVISIBLE:
         gfx_SetTileMapped(&tilemap, bottom.col, bottom.row, BLOCK_VISIBLE);
         break;
      case BLOCK_BUMPER_1:
         gfx_SetTileMapped(&tilemap, bottom.col, bottom.row, BLOCK_BUMPER_2);
         break;
      case BLOCK_BUMPER_2:
         break;
      default:
         gfx_SetTileMapped(&tilemap, bottom.col, bottom.row, BLOCK_EMPTY);
         break;
   }
   ball.vy = -ball.vy;
} else if (right.value) {
   // Right of ball, left side of the block.
   switch (right.value) {
      case BLOCK_INVISIBLE:
         gfx_SetTileMapped(&tilemap, right.col, right.row, BLOCK_VISIBLE);
         break;
      case BLOCK_BUMPER_1:
         gfx_SetTileMapped(&tilemap, right.col, right.row, BLOCK_BUMPER_2);
         break;
      case BLOCK_BUMPER_2:
         break;
      default:
         gfx_SetTileMapped(&tilemap, right.col, right.row, BLOCK_EMPTY);
         break;
   }
   ball.vx = -ball.vx;
} else if (left.value) {
   // Left of ball, right side of the block.
   switch (left.value) {
      case BLOCK_INVISIBLE:
         gfx_SetTileMapped(&tilemap, left.col, left.row, BLOCK_VISIBLE);
         break;
      case BLOCK_BUMPER_1:
         gfx_SetTileMapped(&tilemap, left.col, left.row, BLOCK_BUMPER_2);
         break;
      case BLOCK_BUMPER_2:
         break;
      default:
         gfx_SetTileMapped(&tilemap, left.col, left.row, BLOCK_EMPTY);
         break;
   }
   ball.vx = -ball.vx;
}


I've tried rearranging things, turning the 'else if's into just 'if's (which gave me other misbehavior), and adding other conditions to the if statements. Nothing I've tried gives me the right behavior, and now my brain is fried from all these attempts. If anyone could offer some help/advice, I would really appreciate it! While I cannot figure this out myself, I will be working on my other revived projects in my free time.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement