Android SurfaceHolder unlockCanvasAndPost benötigt zu viel Zeit

Faberix

Mitglied
Hallo Forum

Ich schreibe gerade mein Java-Spiel für Android um. Es funktioniert schon ganz ordentlich, aber es ruckelt immer ein Wenig. Ich habe mal in der LogCat geschaut und festgestellt, dass es die Funktion "SurfaceHolder.unlockCanvasAndPost(Canvas)" ist. Sie benötigt meist zwischen 40 und 100 Millisekunden, das ist einfach zu viel.

Hier mein Code:
Java:
public void repaint() {
            if(!surfaceHolder.getSurface().isValid())
                return false;
            long start = System.currentTimeMillis();
            Canvas canvas = surfaceHolder.lockCanvas();
            System.out.println("lockCanvasTime: " + (System.currentTimeMillis() - start));
            paint(canvas);
            start = System.currentTimeMillis();
            surfaceHolder.unlockCanvasAndPost(canvas);
            System.out.println("unlockCanvasTime: " + (System.currentTimeMillis() - start));
        }

Java:
protected void paint(Canvas canvas) {
            long start = System.currentTimeMillis();
            canvas.drawBitmap(background, new Rect(backgroundX,(int)(screenHeight), backgroundX + width, (int) (screenHeight + height)), new Rect(0, 0, width, height), null);
            level.drawLevel(new Rect(strecke, (int)(screenHeight), strecke + width, (int)(screenHeight + height)), canvas);
           
            for(EntityMonster monster : level.activeMonsters) {
                monster.draw(canvas, strecke, (int)screenHeight);
            }
           
            if(equiptedPowerUp != null) {
                if(!equiptedPowerUp.isDrawAfterCharacter())
                    equiptedPowerUp.draw(canvas, strecke, (int)screenHeight);
            }
           

            if(isGhost)
                canvas.drawBitmap(currentCharacter, playerRelativePosX , PlayerRelativeHeight, ghostPaint);
            else
                canvas.drawBitmap(currentCharacter, playerRelativePosX, PlayerRelativeHeight, null);
           
           
            for(EntityCoin coin : level.activeCoins) {
                if(coin.isCollected) {
                    coin.draw(canvas, strecke, (int)screenHeight);
                }
                else {
                    canvas.drawBitmap(coinImgs[coinImgNum], coin.getRelativePositionX(strecke), coin.getRelativePositionY((int)screenHeight), null);
                }
            }
           
            for(EntityPowerUp powerUp : level.activePowerUps) {
                powerUp.draw(currentScreenGraphics, strecke, (int)screenHeight);
            }
            if(equiptedPowerUp != null) {
                if(equiptedPowerUp.isDrawAfterCharacter())
                    equiptedPowerUp.draw(currentScreenGraphics, strecke, (int)screenHeight);
            }
           
            for(EntityFlyPlatform platform : level.activeMovingSolids) {
                platform.draw(currentScreenGraphics, strecke, (int)screenHeight, flyPlatformImgNum);
            }

            canvas.drawBitmap(healthImages[Health], width - healthImageWidth, 4, null);
            canvas.drawBitmap(coinImgs[0], 4, coinImgPosY, null);
            canvas.drawText(collectedCoins + "", collectedCoinsTextX, collectedCoinsTextY, textPaint);
            canvas.drawBitmap(powerUpDisplay[powerUpFuel], 10, height - powerUpDisplay[0].getHeight() - 10, null);

           
            if(isPaused){
                Paint pausePaint = new Paint();
                pausePaint.setColor(Color.BLACK);
                pausePaint.setAlpha(100);
                pausePaint.setStyle(Style.FILL);
                canvas.drawRect(new Rect(0,0,width,height), pausePaint);
                canvas.drawText("Pausiert", (float)(width/2 - (90 * GameActivity.scaleFactorX)), (float)(height/2 - (200 * GameActivity.scaleFactorY)), textPaint);
            }
            else if(isDead) {
                Paint deathPaint = new Paint();
                deathPaint.setColor(Color.RED);
                deathPaint.setAlpha(100);
                deathPaint.setStyle(Style.FILL);
                canvas.drawRect(new Rect(0,0,width,height), deathPaint);
                canvas.drawText("Du bist gestorben", (float)(width/2 - (200 * GameActivity.scaleFactorX)), (float)(height/2 - (200 * GameActivity.scaleFactorY)), textPaint);
            }
            System.out.println("paintTime: " + (System.currentTimeMillis() - start));
        }

Der Game-Loop:
Java:
while(running) {
                startTime = System.currentTimeMillis();
                while(!finished) {
                    System.out.println("waiting for game2");
                    try {
                        Thread.sleep(4);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
              
                repaint();
                System.out.println("gameTimeRepaint: " + (System.currentTimeMillis() - startTime));
                synchronized(game2) {
                    game2.notify();
                }
                synchronized(entityManager) {
                    entityManager.notify();
                }
                if(isPaused || isDead) {
                    synchronized(this) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    startTime = System.currentTimeMillis();
                }
                System.out.println("gameTime: " + (System.currentTimeMillis() - startTime));
                sleepTime = TPS - (System.currentTimeMillis() - startTime);
                if(sleepTime < 0)
                    sleepTime = 10;
                try {
                    if(pressedSpace) {
                        pressedSpaceTime += sleepTime;
                        if(pressedSpaceTime > maxPressedSpaceTime) {
                            pressedSpaceTime = 0;
                            pressedSpace = false;
                        }
                    }
                    System.out.println("sleepTime: " + sleepTime);
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
              
                if(strecke + characterWidth2 >= maxWidth)
                    running = false;
            }

Ausschnitt aus LogCat:
09-19 12:14:41.171: I/System.out(2259): lockCanvasTime: 1
09-19 12:14:41.224: I/System.out(2259): unlockCanvasTime: 51
09-19 12:14:41.272: I/System.out(2259): lockCanvasTime: 2
09-19 12:14:41.324: I/System.out(2259): unlockCanvasTime: 51
09-19 12:14:41.351: I/System.out(2259): lockCanvasTime: 1
09-19 12:14:41.406: I/System.out(2259): unlockCanvasTime: 52
09-19 12:14:41.437: I/System.out(2259): lockCanvasTime: 1
09-19 12:14:41.498: I/System.out(2259): unlockCanvasTime: 60
09-19 12:14:41.532: I/System.out(2259): lockCanvasTime: 2
09-19 12:14:41.583: I/System.out(2259): unlockCanvasTime: 50​

Weiss jemand, wie man dieses Problem beheben kann?

Mit freundlichen Grüssen, Faberix
 

Faberix

Mitglied
Nein, es ist in einem separaten Thread:

Java:
@Override
        public void run() {
            while(!started) {
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            last = System.currentTimeMillis();
            while(running) {
                startTime = System.currentTimeMillis();
                while(!finished) {
                    System.out.println("waiting for game2");
                    try {
                        Thread.sleep(4);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
               
                repaint();
                System.out.println("gameTimeRepaint: " + (System.currentTimeMillis() - startTime));
                synchronized(game2) {
                    game2.notify();
                }
                synchronized(entityManager) {
                    entityManager.notify();
                }
                if(isPaused || isDead) {
                    synchronized(this) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    startTime = System.currentTimeMillis();
                }
                System.out.println("gameTime: " + (System.currentTimeMillis() - startTime));
                sleepTime = TPS - (System.currentTimeMillis() - startTime);
                if(sleepTime < 0)
                    sleepTime = 5;
                try {
                    if(pressedSpace) {
                        pressedSpaceTime += sleepTime;
                        if(pressedSpaceTime > maxPressedSpaceTime) {
                            pressedSpaceTime = 0;
                            pressedSpace = false;
                        }
                    }
                    System.out.println("sleepTime: " + sleepTime);
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
               
                if(strecke + characterWidth2 >= maxWidth)
                    running = false;
            }
           
           
            synchronized(game2) {
                game2.notify();
            }
            synchronized(entityManager) {
                entityManager.notify();
            }
            clear();
            GameActivity.Instance.exitGameOnPause();
            if(toMainMenu)
                GameActivity.Instance.backToMainMenu();
            else
                GameActivity.Instance.backToLevelMenu();
        }
 

Neue Themen


Oben