Question

Ok, so I've been working on a little game, and there's a problem in the rendering code. So, I tried to follow a tutorial for working with the SurfaceView, and so this is what I have so far:

GameSurface.java

package com.spng453.afirelitroom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {

private GameThread thread;
public SurfaceHolder surfaceHolder;



DisplayMetrics metrics = GameActivity.metrics;
final private int sX = metrics.widthPixels;
final private int sY = metrics.heightPixels;
private Paint mainBTheme = new Paint();
Rect fireButton = new Rect(0, sY/2+50, sX, sY/2-50);

public GameSurface(Context context) {
    super(context);
    surfaceHolder = getHolder();
    surfaceHolder.addCallback(this);
    this.setWillNotDraw(false);
    thread = new GameThread(surfaceHolder, this);
    this.setFocusable(true);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread.setRunning(true);
    thread.run();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean done = false;
    while(!done) {
        try {
            thread.join();
            done = true;
        } 
        catch (InterruptedException e) {
        }
    }
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawRGB(255, 255, 0);
}

@Override 
public boolean onTouchEvent(MotionEvent event) {
    return true;
}
}

and the code in

GameThread.java:

package com.spng453.afirelitroom;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;

public class GameThread extends Thread {

DisplayMetrics metrics = GameActivity.metrics;
final private int sX = metrics.widthPixels;
final private int sY = metrics.heightPixels;
private int FPS = 30;
private boolean running;
public SurfaceHolder surfaceHolder;
public GameSurface gameSurface;
public Canvas canvas;
private long firstTime = 0L, secondTime = 0L; //fps stuff

private Paint mainBTheme = new Paint();


//fire page
Rect fireButton = new Rect(0, sY/2+50, sX, sY/2-50);
Rect leftButton = new Rect();
Rect rightButton = new Rect();


//city/resources page


public void setRunning(boolean running) {
    this.running = running;
}

public GameThread(SurfaceHolder surfaceHolder, GameSurface gameSurface) {
    super();
    this.surfaceHolder = surfaceHolder;
    this.gameSurface = gameSurface;
    mainBTheme.setColor(Color.BLACK);
}

@Override
public void run() {
    while (running) {
        //hey i guess i have to cap fps :(
        firstTime = System.nanoTime();
        //do the game here
        canvas = null;
        canvas = surfaceHolder.lockCanvas();
        gameSurface.onDraw(canvas);
        surfaceHolder.unlockCanvasAndPost(canvas);


        secondTime = System.nanoTime();
        if (secondTime/1000000 - firstTime/1000000 < 1000/FPS) { //the if the lag is less than the distance between frames at 30 fps
            try {
                Thread.sleep(1000/FPS - (secondTime/1000000 - firstTime/1000000));
            } catch (InterruptedException e) {
            }
        }
    }
}
}

So, my problem is that when I try to call onDraw in the GameThread here:

canvas = null;
canvas = surfaceHolder.lockCanvas();
gameSurface.onDraw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);

it does absolutely nothing. It doesn't draw whatever I put in onDraw, though if I put a Log call in the onDraw I know it executes. It doesn't produce an error message, either. Thanks for help in advanced!

Was it helpful?

Solution

Try this:

Change your method:

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRGB(255, 255, 0);
    }

By this:

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRGB(255, 255, 0);
        super.onDraw(canvas);
    }

Also, try change this lines:

    //do the game here
    canvas = null;
    canvas = surfaceHolder.lockCanvas();
    gameSurface.onDraw(canvas);
    surfaceHolder.unlockCanvasAndPost(canvas);

By this ones:

    Canvas canvas = null;

    try {
        canvas = surfaceHolder.lockCanvas();
        synchronized (surfaceHolder) {
            gameSurface.onDraw(canvas);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (canvas != null)
            surfaceHolder.unlockCanvasAndPost(canvas);
    }

Also keep note that the while loop it's running really fast no giving chance to draw the canvas. The thread sleep isn't working very well. Look at this resources, there is explained how do the game loop properly. And if you wanna test it right now, just erase the while.

Android game loop explained Android game basic structure

Hope this helps :]

OTHER TIPS

Okay, so it turns out that it was a problem with the FPS code executing too fast. I solved it by doing this:

@Override
public void run() {
    // TODO Auto-generated method stub
    final int fps = 30;
    Timer fpsTimer = new Timer();
    fpsTimer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            Canvas canvas;
            canvas = null;
            try {
                canvas = surfaceHolder.lockCanvas(null);
                synchronized (surfaceHolder) {
                    onDraw(canvas);
                }
            } finally {
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }

    }, 0, 1000/fps);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top