Here's the method I am using, and it works quite well for me. I'd assume that our entities (sprites) usually override
onAreaTouched
, and the events will be processed where the game logic resides (the Activity or the Scene).Let's define a class for our input events (borrowing from the widely used Command design pattern):
public class InputEvent {
public Sprite mSource;
public TouchEvent mTouchEvent;
public InputEvent(Sprite pSource, TouchEvent pTouchEvent) {
mSource = pSource;
mTouchEvent = pTouchEvent;
}
public Source getSource() {
return mSource;
}
public TouchEvent getTouchEvent() {
return mTouchEvent;
}
}
These objects will be communicated from the source entities (sprites) to the processing instance. I tend to use the Scene for game logic, but many prefer to use the Activity. Also, keep in mind that we may want to process several input events every time.
Let us define the input events queue in the processing class:
private Queue<InputEvent> mInputQueue = new LinkedBlockingQueue<InputEvent>();
And a publicly accessible method for posting input events to that queue:
public void queueInputEvent(InputEvent pInputEvent) {
mInputQueue.add(pInputEvent);
}
Please note that I opted to use a blocking queue - this implementation should be sufficient in most cases.
This method will be invoked from the sprite's touch event implementation:
@Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
mScene.queueInputEvent(new InputEvent(this, pSceneTouchEvent));
return true;
}
Where mScene is the parent scene which i save for each sprite. Other methods can be used - e.g. calling getParent() etc.
Now, lets implement the actual event processor:
private IUpdateHandler mInputProcessor = new IUpdateHandler() {
private List<Marble> mSelectedSequence = new ArrayList<Marble>();
@Override
public void onUpdate(float pSecondsElapsed) {
while(!mInputQueue.isEmpty()) {
InputEvent evt = mInputQueue.remove();
switch(evt.getTouchEvent().getAction()) {
case TouchEvent.ACTION_DOWN:
//
// Process your ACTION_DOWN events here
//
break;
case TouchEvent.ACTION_UP:
//
// Process your ACTION_UP events here
//
break;
//
// and process all other event type here
//
}
}
}
}
And lastly, lets register this update handler with the scene (usually in any of the initialization methods):
registerUpdateHandler(mInputProcessor);
And that's all - now all our input events will be processed on the update thread without crashing the application.
I hope this post helped someone!
No comments:
Post a Comment