8
\$\begingroup\$

I have recently been pursuing game development as a hobby, and decided that in order to learn the in's and out's of game development, that I should create a game and render everything myself (without the use of a game engine). This has proven rather complicated, however I am making great progress. I did, however, run in to an issue that I think might be related to the way Android phones render their graphics and will need some clarification on this issue.

The Problem

My game contains a series of balls in a cannon; when the user presses the screen, the cannon launches the balls and the engine (that I am implementing) handles the updates to the location information and collision detection from there. Now, before I had implemented collision detection my game ran very smoothly and responsively, however when I told the engine to only draw the bead if it is within the bounds, and "bounce" it off the wall otherwise, it would seem that the engine loop now takes a significantly longer amount of time to run.

This would be fine, if it were not for the latency it is providing to the user experience. For example, when the screen is touched now, it takes ~2 seconds for the ball to be displayed as moving around the screen, and sometimes it does not appear at all. Previously, the reaction was instantaneous.

Further, when I comment out the collision detection portion of my physics engine, it resumes its usual responsive behavior.

What I Think Is Causing This Behavior

Note: I have recanted this assumption (see 'Debugging Information' below)

I think that since I do not have a frame limiter implemented for my game, and that it is rendering as fast as the hardware will allow it, that it is drawing so many old frames (in some buffer, maybe?) to the screen that it is busy drawing while it should be updating physics. Although my debugging thus far has not indicated that this is the case, I cannot seem to reach any other conclusion.

Some Code

Note that this code is going to be rather confusing to understand not knowing what everything does. I simply included it in case anyone was particular about having some code to work with. The variables are clarified below the excerpt.

PhysicsEngine.updateBeadPositions(float):

private void updateBeadPositions(float delta){

    //Update all of the beads currently on the board.
    beads = control.getBoard().getValues();

    temp_x = 0.0f;
    temp_y = 0.0f;

    //For each row...
    for(Bead[] row : beads){

        //For each bead...
        for(Bead bead : row){

            //If this bead exists...
            if(bead != null){

                temp_y = (float) (bead.getYCoordinate() * bead.getYVelocity() * delta);

                //If the coordinates are within the bounds of the game
                if(outwithVerticalBounds(temp_y, control.getBoard())){

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    bead.setXCoordinate(temp_x);

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    bead.setYCoordinate(temp_y);
                }
            }
        }
    }

    //If the cannon Bead has been set...
    if(control.getCannon().getReleased() != null){

        //Update the cannon bead
        if(control.getCannon().getReleased().getXVelocity() == PhysicsEngine.VELOCITY_STATIC && control.getCannon().getReleased().getYVelocity() == PhysicsEngine.VELOCITY_STATIC){

            control.getCannon().getReleased().setXCoordinate(control.getCannon().getX());
            control.getCannon().getReleased().setYCoordinate(control.getCannon().getY() - Cannon.PIVOT_Y_OFFSET);
        }
        else{

            temp_x = control.getCannon().getReleased().getXCoordinate() + (control.getCannon().getReleased().getXVelocity() * delta);
            temp_y = control.getCannon().getReleased().getYCoordinate() + (control.getCannon().getReleased().getYVelocity() * delta);

            //TODO: Commented out collision checkers!

            //If the horizontal coordinates are within the bounds of the game
            if(!outwithHorizontalBounds(temp_x, control.getBoard())){

                //If the vertical coordinates are within the bounds of game
                if(!outwithVerticalBounds(temp_y, control.getBoard())){

                    //Set the X coordinate equal to the distance * the time differential (delta).       
                    control.getCannon().getReleased().setXCoordinate(temp_x);

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    control.getCannon().getReleased().setYCoordinate(temp_y);
                }
                //Otherwise...
                else{

                    //Bounds off the wall in the y direction
                    control.getCannon().getReleased().setYVelocity(-1.0f * control.getCannon().getReleased().getYVelocity());
                }
            }
            //Otherwise...
            else{

                //Bounce off the wall in the x direction (flip the x velocity)
                control.getCannon().getReleased().setXVelocity(-1.0f * control.getCannon().getReleased().getXVelocity());
            }
        }
    }
}

Here, the variables are defined as:

  • control is a reference to my game controller. It packages the majority of the game code.

  • beads is a reference to the 2D array that contains the beads on the board currently (excluding the one that is moving)

  • delta is the time differential between previous calls to the physics engine, and the current call

See the comments within the code for any other explanations.

PhysicsEngine.outwithHorizontalBounds(float, Board):

private boolean outwithHorizontalBounds(float x, Board board){

    //If the horizontal values are within the bounds...
    if(x > (board.getRight() - bead_radius)){

        return true;
    }

    if(x < (board.getLeft() + bead_radius)){

        return true;
    }

    //Otherwise, it is not.
    return false;
}

The method outwithVerticalBounds(float, Board) is of equivalent functionality, but in the y-direction.


My Question

What about collision detection would cause screen rendering to be inhibited so drastically? I know it is a very intensive operation, but my debugging has shown that the physics updates are completing at the same times as the draws.

Debugging Information

Last Updated: 29 Jan 2013 4:27PM EST

Here is an aggregation of the debugging information that I have obtained thus far. I will update this as time progresses:

  • The update() method within my engine, takes, on average, only .018 ms to execute. Usually, the delay jumps up to 0.020 ms, when I tap the screen to release the bead.

  • After comparing the times of the draws and the game updates, it would appear that I was correct: they are occurring simultaneously. Thus, this could not be the issue, right?

  • The FPS of the game is roughly 87, it spikes randomly to (at the low end) 60 FPS, however this spike is not related to the releasing of the bead. There are no FPS drawbacks to doing this. This makes sense since the only part that increases its complexity after the bead is released is the update() call, drawing still happens as fast as possible.

  • After further testing, it has become apparent that this is not the case that the screen is lagging behind the physics. I tested this with a simple boolean flag wherein the screen background would become white when i touched it, and this happens immediately. Thus, there must be some other cause for the bead not drawing. I will update soon.

Supplemental Information

Here is some supplemental information that should help you understand my circumstances:

  • I am testing this on a Google Nexus 7.

  • There are quite a few beads on the map that are being updated at once (about 30), but only one of them is moving.

  • Usually, after the bead starts moving (after the initial delay and if it actually draws), is continues to move in a very smooth manner.

  • It is important to note that I have other UI elements on the screen that update in reaction to the touch event. For instance, the bead loaded in the cannon becomes a new bead when the screen is touched (signifying that it has been released), but the mobile bead is simply not drawn.

\$\endgroup\$
4
  • \$\begingroup\$ Think your debugging that shows the physics updates inline with the draws might be inaccurate? Have you done any other profiling with this code? \$\endgroup\$
    – House
    Jan 29, 2013 at 19:41
  • \$\begingroup\$ I have done some extensive debugging using outputs to the console (LogCat), however nothing more complicated than this. It could be the case that my debug statements are incorrect, I will review them now. \$\endgroup\$
    – Squagem
    Jan 29, 2013 at 19:47
  • \$\begingroup\$ Also interesting is if the FPS(Frames Per Second) changes when adding the bounding case, or that the problem is not related to how fast the program runs. \$\endgroup\$
    – Qqwy
    Jan 29, 2013 at 20:08
  • \$\begingroup\$ I have edited my question to answer the points you have raised. \$\endgroup\$
    – Squagem
    Jan 29, 2013 at 21:24

1 Answer 1

8
\$\begingroup\$

Frankly, I am rather embarrassed to announce the solution to my problem as I spent many hours in search of it, and it was so simple and could have been avoided so easily with a little less negligence on my behalf. On the bright side, I did end up finding a few other pieces of code that I can now optimize for even better performance!

The Solution

The cannon that was launching the bead was below the lower boundary of my playable area.

This was misleading because the lower boundary of my playing area is a little bit above the bottom of the actual screen of the phone. So, basically, the physics engine was bouncing it back and fourth ever so slightly (invisible to human inspection) for about 5 seconds before it was rendered on screen.

I moved the cannon 50 pixels higher and it works as intended now.


Thank you all for you help! I wouldn't have got here without your thoughtful suggestions.

\$\endgroup\$
2
  • 3
    \$\begingroup\$ +1 for a well formatted question and +1 for answering it yourself \$\endgroup\$
    – RoughPlace
    Mar 1, 2013 at 16:38
  • \$\begingroup\$ Whoops, forgot about this question! Thanks guys :) \$\endgroup\$
    – Squagem
    Mar 4, 2013 at 21:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .