1

Im trying to start a new intent from my gameView using this method:

    if(happy.getHP() <= 0){ //if my main-character dies
            thread.setRunning(false);
            Context context = getContext();
            Intent intent = new Intent("nielsen.happy.activities.ENDSCREEN");
            context.startActivity(intent);

}

If I do it without thread.setRunning(false);, the endScreen comes up but its buttons wont work, but if i stop my mainThread they do work.

Anyway, the problem with this code is that when my character dies, it freezes for 3-4 seconds, then the endscreen flickers for a sec, then the gameView flickers for a sec, THEN the endscreen comes up for real and the buttons work.

When I start an Activity from another activity, like when I press "Start Game" in my menu, I dont get this problem. I really dont understand what happens here that makes it lag like this.

adding my thread below:

    public void run() {
    Canvas canvas;
    Log.d(TAG, "Starting game loop");
    // initialise timing elements for stat gathering
    initTimingElements();

    long beginTime;     // the time when the cycle begun
    float time1 = System.currentTimeMillis();
    float time2;
    //long timeDiff;        // the time it took for the cycle to execute
    int sleepTime;      // ms to sleep (<0 if we're behind)
    int framesSkipped;  // number of frames being skipped 

    sleepTime = 0;

    while (running) {
        canvas = null;
        // try locking the canvas for exclusive pixel editing
        // in the surface
        try {
            canvas = this.surfaceHolder.lockCanvas();
            synchronized (surfaceHolder) {
                beginTime = System.currentTimeMillis();
                framesSkipped = 0;  // resetting the frames skipped
                // update game state 
                this.gamePanel.update();
                // render state to the screen
                // draws the canvas on the panel
                this.gamePanel.render(canvas);              
                // calculate how long did the cycle take
                timeDiff = System.currentTimeMillis() - beginTime;
                // calculate sleep time
                sleepTime = (int)(FRAME_PERIOD - timeDiff);

                if (sleepTime > 0) {
                    // if sleepTime > 0 we're OK
                    try {
                        // send the thread to sleep for a short period
                        // very useful for battery saving
                        Thread.sleep(sleepTime);    
                    } catch (InterruptedException e) {}
                }

                while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
                    // we need to catch up
                    this.gamePanel.update(); // update without rendering
                    sleepTime += FRAME_PERIOD;  // add frame period to check if in next frame
                    framesSkipped++;
                }

                // for statistics
                framesSkippedPerStatCycle += framesSkipped;
                // calling the routine to store the gathered statistics
                storeStats();
            }
        } finally {
            // in case of an exception the surface is not left in 
            // an inconsistent state
            if (canvas != null) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }   // end finally
    }
}

adding whole method below:

    private void checkCollision(Canvas canvas) {
    Rect h1 = happy.getBounds();
    for (int i = 0; i < enemies.size(); i++) {
        Rect e1 = enemies.get(i).getBounds();
        if (h1.intersect(e1)){
            if(enemies.get(i).getX() < controls.pointerPosition.x){
                enemies.get(i).setX(-20);
            }else if (enemies.get(i).getX() > controls.pointerPosition.x){
                enemies.get(i).setX(20);
            }else if(enemies.get(i).getY() < controls.pointerPosition.y){
                enemies.get(i).setY(-20);
            }else if(enemies.get(i).getY() > controls.pointerPosition.y){
                enemies.get(i).setY(20);
            }
            if(enemies.get(i).getCooldown() <= 0){
            happy.damageHP(10);
            score.incScore(-10);
            enemies.get(i).setCooldown();
            }
        }
        if(happy.getHP() <= 0){

            thread.setRunning(false);
            try {
                thread.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Context context = getContext();
            Intent intent = new Intent("nielsen.happy.activities.ENDSCREEN");
            context.startActivity(intent);
            //end-screen                           !!!!!!!
        }
        if(enemies.get(i).getHP() <= 0){
            enemies.get(i).death(canvas, enemies);
            score.incScore(5);
            break;
        }   
        for (int j = 0; j < bullets.size(); j++) {
            Rect b1 = bullets.get(j).getBounds();
            if (b1.intersect(e1)) {
                enemies.get(i).damageHP(5);
                bullets.remove(j);
            }
        }
    }
}
Green_qaue
  • 3,561
  • 11
  • 47
  • 89

1 Answers1

1

I would have to see what your thread is doing to be sure, but I'm pretty sure something like this is happening:

  • You call setRunning(false) which sets some flag in the thread class.

  • You start the new intent but the thread hasn't stopped yet because it hasn't gotten to the part where it checks the running flag

  • The thread (which hasn't paused yet) starts making changes to the gui, this confuses the android UI which thinks that view should be inactive

  • The thread gets to the point where it's waiting for setRunning(true), and everything is happy again.

If this is true, you can fix by waiting until the thread is blocked on setRunning(true), then creating the new intent.

DigitalGhost
  • 773
  • 1
  • 5
  • 14
  • Alright, now that I see your thread I have a better answer: Right after thread.setRunning(false);, add "thread.join()". This will block until the thread is finished. – DigitalGhost Sep 05 '12 at 00:25
  • I've alrdy tried this aswell, this just freezes the game at the point its supposed to put up the end-screen. =/ – Green_qaue Sep 05 '12 at 00:32
  • Can you post the entire method that is calling setRunning(false)? You probably has synchronized(surfaceHolder) and, as a result, the thread is waiting for you to release the synchronized, and you waiting for the thread to finish, which results in deadlock. – DigitalGhost Sep 05 '12 at 00:36
  • it does indeed, trying without synchronized right now. Will add method to question if it dosnt work :) – Green_qaue Sep 05 '12 at 00:41
  • sigh, still dosnt work =/ just freezes like it did before I removed synchronized. Added entire method to question – Green_qaue Sep 05 '12 at 00:45
  • does it matter that my surfaceDestroyed(SurfaceHolder holder) - method for my view dosnt override? Cant add override to it for some reason, but hasnt mattered before. Also my View implements SurfaceHolder.Callback, probably dosnt matter but might aswell mention it. – Green_qaue Sep 05 '12 at 00:51
  • Who calls checkCollision? Is the gamePanel.update() function calling it? If so, then the thread is joining to itself, which is bad. You could fix it by doing the join and the new intent on the UI thread: runOnUiThread(new Runnable() { public void run() { thread.setRunning(false); Context context = getContext(); Intent intent = new Intent("nielsen.happy.activities.ENDSCREEN"); context.startActivity(intent); } }); – DigitalGhost Sep 05 '12 at 00:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16270/discussion-between-ique-and-digitalghost) – Green_qaue Sep 05 '12 at 01:00