[Android] Help Syncing Game Thread with Renderer Thread

Started by
2 comments, last by robobrain 12 years, 5 months ago
The program is pretty simple right now. I have a triangle that I want to bounce around the screen. I have a moveTo(x,y) function in the triangle class. The triangle moves if the function is called on the Renderer thread but the screen is blank if I try to use the function on another thread. This is the first time I've dealt with threading, I'll be honest. I figure I need to use a Lock but I don't really know how to go about doing it...

When I comment out running the game thread from the activity, the triangle is drawn and even moves around as I touch the screen as input is received on the rederer's thread. When I let it run, I get a black screen.

public class GLView extends GLSurfaceView {
private StateManager _manager;
private GLRenderer _renderer;

public GLView(Context context, StateManager m) {
super(context);
_manager = m;
_renderer = new GLRenderer(_manager);
setRenderer(_renderer);
}

public boolean onTouchEvent(final MotionEvent event){
queueEvent(new Runnable() {
public void run() {
_manager.Input(event.getX(), event.getY());
}
});

return true;
}

}


public class GLRenderer implements GLSurfaceView.Renderer {
private StateManager _manager;

public GLRenderer(StateManager m){
_manager = m;
}

public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
_manager.Draw(gl);
}

public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);

gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0, width, height, 0);

gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glShadeModel(GL10.GL_FLAT);

gl.glDisable(GL10.GL_DEPTH_BUFFER_BIT);
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glDisable(GL10.GL_CULL_FACE);
gl.glDisable(GL10.GL_DITHER);
gl.glDisable(GL10.GL_LIGHTING);

//gl.glEnable(GL10.GL_TEXTURE_2D);

//gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
}

}



public class GameThread implements Runnable {
private StateManager _manager;
private GLView glV;

private boolean paused = false;


public GameThread(State firstState){
_manager = new StateManager(firstState);
}

public void setView(Activity main){
glV = new GLView(main, _manager);
main.setContentView(glV);
}

public void pause(){paused = true; glV.onPause();}
public void resume(){paused = false; glV.onResume();};

public void run() {
while(_manager.IsRunning()){
if(!paused){
_manager.Update();
}
}

}

}




(I'm aware that dx doesn't change, I made it static in case the screen was just blank because the triangle moved off the screen before being drawn)
public final class TestGL extends State {
private Triangle triangle;

private float dx, dy;

public TestGL(){
triangle = new Triangle();

dx = 100;
dy = 0;
}

@Override
public void Input(float x, float y) {
triangle.moveTo(x, y);
}

@Override
public void Update() {
triangle.moveTo(dx, dy);
}

@Override
public void Draw(GL10 gl) {
triangle.draw(gl);
}

}
Advertisement
Hmm. I'm a little closer... I added a ReentrantLock to the statemanager. Then in the update method I try to lock the state manager before updating it. Same for on the Renderer thread. Now the triangle flickers occasionally onto the screen. lol

I assume the problem is that the draw thread isn't guaranteed a lock. How do I guarantee it a lock?
I tried looping in the draw thread until it locks... this... works but it's not smooth. I'd like the draw thread to be guaranteed a lock when it wants it. Anyone know how I'd go about this?

The program is pretty simple right now. I have a triangle that I want to bounce around the screen. I have a moveTo(x,y) function in the triangle class. The triangle moves if the function is called on the Renderer thread but the screen is blank if I try to use the function on another thread. This is the first time I've dealt with threading, I'll be honest. I figure I need to use a Lock but I don't really know how to go about doing it...

When I comment out running the game thread from the activity, the triangle is drawn and even moves around as I touch the screen as input is received on the rederer's thread. When I let it run, I get a black screen.



It might be easier if you do all of your input handling, physics calculations, etc in the main thread then bundle every renderable object into an array (display list) and pass it off to the render thread. Then you only have to synchronize one function instead of worrying about so many objects. Like this:


class MyRenderer {
...
public function updateDisplayList(DisplayObjects[] displayList) {
synchronize (displayList) {
mDisplayList = displayList; // Update internal display list.
}
}
...
}


this is more or less what games like Replica Island do.
Want to make Android Games?
Then check out the free RoboBrain SDK.
[size="2"][url="http://www.robobrain.org"]www.robobrain.org[/url]

This topic is closed to new replies.

Advertisement