1

I have a little Android game I've been working on and have also implemented some pixel perfect collision checking based on code here (I say based on, the only thing I changed was the class name). This used to work fine a few months ago but I stopped development for a while, came back and had to rebuild a lot of code including that. Now when I implement it to collisions seem horribly off. If the large weight is on the left of the player, there's a significant distance and yet it still counts as a collision. I have also noticed that the player can pass through some of the smaller weights but not all the way through. I know the player has some non-transparent white pixels which don't help, but I tried with a transparent smaller image and the same thing happened. I edited the player image to remove the white pixels, but I'm still getting the odd collision detection. Any ideas?

The second issue, when the player collides with a weight, it goes to the next activity (which it does) however it jerks all the objects on screen for about a second, and then proceeds to the next activity. Any ideas on this? I have a feeling it's to do with the way I handle the threads, or the way I close them. Check GitHub link below for the GameThread class which handles the main operations on my surface thread.

Collision code can be found in above link, my calling of the class can be found below:

// handles game over circumstances
                if (CollisionUtil.isCollisionDetected(player.getBitmap(), player.getX(), player.getY(), weight.getBitmap(), weight.getX(), weight.getY())) {
                    Intent gameOverIntent = new Intent(this.getContext(), GameOverActivity.class);
                    player.setTouched(false);
                    this.getContext().startActivity(gameOverIntent);
                    ((Activity) this.getContext()).finish();
                    save(score, time);
                    try {
                        gameTimers.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    gameOver = true;
                }

The rest of the classes and all my other code can be found here: https://github.com/addrum/Francois/tree/master/src/com

Thanks for your help in advance.

Edit: Forgot to mention that if you need to test it (you probably will to see what I'm talking about) you can download it here: https://play.google.com/store/apps/details?id=com.main.francois

Edit: I've now uploaded a short recording on YouTube to make it easier to see what I'm talking about: http://youtu.be/vCjKmTmhabY

Community
  • 1
  • 1
Adam Short
  • 498
  • 7
  • 28
  • If you have a device with Android 4.4, you can grab a recording with `screenrecord` and post it on youtube. Might help to explain the "it jerks all the objects on screen" part. – fadden Apr 23 '14 at 16:59
  • Added a link: http://youtu.be/vCjKmTmhabY – Adam Short Apr 24 '14 at 09:13

1 Answers1

2

Thanks for the video; now I understand the "jerk" part.

The explanation for that is simple: your code is doing this (simplified):

while (running) {
    canvas = this.surfaceHolder.lockCanvas();
    this.gameLogic.update();
    this.gameLogic.render(canvas);
    surfaceHolder.unlockCanvasAndPost(canvas);
}

public void render(Canvas canvas) {
    if (!gameOver) {
        ...draw...
    }
}

If gameOver is true, your render() function doesn't draw anything, so you get the previous contents of the buffer.

You might expect this to show whatever was drawn from the frame just before this one. However, the SurfaceView surface is double- or triple-buffered. So if you just keep calling lock/post without drawing anything, you'll cycle through the last two or three frames.

Simple rule: if you lock the surface, you need to draw. If you don't want to draw when the game is over, you need to put your "game over" test back before you lock the canvas.

fadden
  • 51,356
  • 5
  • 116
  • 166
  • Okay, I understand what you're saying but don't really know how to proceed. If I remove the game over check I don't get the "jerkiness" but everything keeps being rendered (which is what I'd expect as there's no restriction). What I'd like to happen, is on a collision, stop rendering with no jerkiness and proceed to game over. Do I need to add in game over again after rendering or call unlockandpost? I'm unsure. – Adam Short Apr 24 '14 at 15:04
  • Either you need to pull the game-over check up above the lockCanvas() call, so you skip it entirely, or you need to push the lockCanvas() call down into render() so you skip it with the existing game-over check. Or maybe eliminate the `!gameOver` test and instead draw the scene and then plaster a big "GAME OVER" message across the middle of the screen on top of everything else. – fadden Apr 24 '14 at 17:34
  • Okay, I managed to reduce the "jerk" to a single buffer (I think I'm right in saying that) by surrounding lockCanvas part in my GameThread class with an if (!gameLogic.isGameOver()) check and it now jerks once! Now I'm going to be perfectionist and ask how can I remove this last "jerk"? – Adam Short Apr 25 '14 at 14:11
  • Did you remove the game-over check from render()? Make sure that, if you call lockCanvas(), you always draw. – fadden Apr 25 '14 at 14:33
  • I hadn't. Works perfect now! Cheers. – Adam Short Apr 25 '14 at 14:38