0

I've been stuck on this problem for a very long time now, I've searched around alot and tried stuff, but nothing works. Some explanations are just very hard for me to understand as Im pretty new to programming overall and got alot to learn.

I have two problems

1: The ball wont collide with the bricks sometimes when the speed is too fast.

2: The ball is capable of hitting 2 bricks. Both problems is related to the fact that 60 fps isnt enough for my type of collision detection to work properly.

I just need someone to explain in a simple way as possible what I need to do to make a collision detection that will prevent this from happen.

Here's my current collision code:

private function checkCollision(): void {
  grdx = Math.floor((ball.x) / 28);
  grdy = Math.floor((ball.y) / 14);
  ngrdx = Math.floor((ball.x + dx) / 28);
  ngrdy = Math.floor((ball.y + dy) / 14);
  var flipX: Boolean = false;
  var flipY: Boolean = false;
  if ((grdy <= level.length - 1) && 
      (ngrdy <= level.length - 1) && 
      (grdy >= 0 && ngrdy >= 0)) {
    if (testBlock(grdx, ngrdy)) {
      flipY = true;
      paddleFlag = 1;
    }
    if (testBlock(ngrdx, grdy)) {
      flipX = true;
      paddleFlag = 1;
    }
    if (testBlock(ngrdx, ngrdy)) {
      flipX = true;
      flipY = true;
      paddleFlag = 1;
    }
    dx *= flipX ? -1 : 1;
    dy *= flipY ? -1 : 1;
  }
}
private function testBlock(xPos: int, yPos: int): Boolean {
  if (level[yPos][xPos] > 0 && level[yPos][xPos] != 13) {
    trace("hit on X,Y");
    level[yPos][xPos] = 0;
    breakBlock("Block_" + yPos + "_" + xPos);
    trace("Block: " + totalBreaks + " / " + totalBlocks);
    return true;
  }
  return false;
}
private function breakBlock(blockName: String): void {
  if (this.getChildByName(blockName)) {
    this.removeChild(this.getChildByName(blockName));
    totalBreaks++;
  }
}

Thank you and sorry for my bad english, its not my motherlanguage.

Ezhil V
  • 894
  • 5
  • 11
Leyon
  • 3
  • 1
  • 3
    There's a thing named "AABB sweeping algorithm", given your bricks are aligned horizontally and vertically, you can use that one to sweep a ball vs grid, then check those areas that overlap the path, starting with closest to ball. Once you encounter a collision, break that brick and calculate a new angle, speed and coordinates. – Vesper Apr 25 '13 at 17:12

2 Answers2

1

One solution is to move the ball in smaller iterations, multiple times in a given frame.

For example, and I am giving this solution assuming that you are moving the ball based on the time elapsed from the last frame.

Suppose that 30 milliseconds have elapsed since the last frame update. In that case you would update the movement/collision twice in that frame using 15 millisecond as your time elapsed.

The higher resolution of collision you want, the more iterations you would do.

Here's an example :

 // class declarations
 var lastFrame:Number;
 var iterationsPerFrame:int;

function startGame():void
{
     // lets specify 3 updates per frame
     iterationsPerFrame = 3;

     // save initial time
     lastFrame = getTimer();

     // create your listener
     addEventListener(Event.ENTER_FRAME, update);
}

function update(e:Event):void
{
     var currentFrame:Number = getTimer();
     var deltaTime:Number = (currentFrame - lastFrame)/1000;

     var iterationDelta:Number = deltaTime/iterationsPerFrame;

     for (var index:int = 0;index < iterationsPerFrame;index++)
     {
          // I'm assuming dx,dy are the velocity of the ball, in pixels per second
          ball.x += dx * iterationDelta;
          ball.y += dy * iterationDelta;
         // check collision
     }


     // set lastFrame to the currentFrame time, preparing for next frame
     lastFrame = currentFrame;

     // after this, your frame is going to render
}
prototypical
  • 6,731
  • 3
  • 24
  • 34
  • Thats exactly what i do, how would you do to iterate faster than 60fps? – Leyon Apr 25 '13 at 18:37
  • How many update/collision iterations are you doing per frame ? If it's not enough, you do more iterations. right ? The solution is not to iterate the game faster than 60fps, the goal is to iterate the movement/collision at a faster rate. Each division you make, is another iteration per frame. right ? – prototypical Apr 25 '13 at 18:39
  • My point is that if your game is running at 60fps and you are doing 2 iterations of your movement/collision, your movement and collision is running at 120fps. You need to ensure that the elapsed time you are using on your movement update is 1/2 for each iteration in that situation. – prototypical Apr 25 '13 at 18:55
  • I think I get what you're saying and yes, I put the CheckCollision funcion into onGametick(which is updating in 60 fps). So if I'm getting this right, the update for the ball should be half compared to the collision update? – Leyon Apr 25 '13 at 19:14
  • So, this is what i did. I put the moveBall function into a timer which ticks equall to 30 fps, and the collision ticks with 60fps. It worked pretty well, but when the ball moved with 30fps, it looked pretty hacky. So I have to try something else. Thank you for your time though, I appreciate it alot :) – Leyon Apr 29 '13 at 14:05
  • No,you misunderstood. There are three aspects - movement, collision, rendering. Rendering happens once per frame. What I am telling you is to do your movement/collision twice per frame. When you say "it looked pretty hacky", it's likely you implemented incorrectly. – prototypical Apr 29 '13 at 16:47
  • Okey, I think I understand it in theory, but how do i implement it? How can I execute collision detection twice per frame? – Leyon Apr 29 '13 at 17:00
  • If you want to email me at prototype.in.training@gmail.com, I can take a look at what you have and help you implement what I am talking about. – prototypical Apr 29 '13 at 17:07
0

You could work out how far the ball travels each frame (A) based on its speed, how far the ball is from the paddle (B) and if A > B manually trigger a collision that frame.

You're essentially checking every bricks X and Y coordinate to the balls X and Y coordinate, so if the bricks are stored in an array this becomes: Sqrt( Sqrd(p2.x - p1.x) + Sqrd(p2.y - p1.y))

for(var i=0; i<brickArray.length; i++)
{
    var distance:Number = Math.sqrt((brickArray[i].x - ball.x) * (brickArray[i].x - ball.x) +
                                    (brickArray[i].y - ball.y) * (brickArray[i].y - ball.y));
}

This is a very good tutorial on high speed collison detection: http://www.newgrounds.com/bbs/topic/1072673

Simon McArdle
  • 893
  • 6
  • 21
  • I've looked into your solution and i think it can work. I just need to figure out how to calculate every x and y coordinate for the bricks to compare the distance with the ball. – Leyon Apr 29 '13 at 13:59
  • This looks very promising. I'll check that tutorial out. I'll tell ya when I succeed :) – Leyon Apr 29 '13 at 14:26