I've been learning (slowly) how to program Android games using Java and Android Studio. My main source of learning was following the tutorials that are located on the Kilobolt Tutorial Website. I have found these extremely helpful, but because they are tutorials on Android ADT for Eclipse, and they are 3 years old, I have had to do a lot learning with each section to learn Android Studio (a huge process).
I have found that, mostly, that the logic on the tutorial has been solid. My issue is that in the SingleTouchHandler class of the framework provided by Kilobolt, ACTION_UP does not seem to work. Here is the Input Class:
public interface Input {
public static class TouchEvent {
public static final int TOUCH_DOWN = 0;
public static final int TOUCH_UP = 1;
public static final int TOUCH_DRAGGED = 2;
public static final int TOUCH_HOLD = 3;
public int type;
public int x, y;
public int pointer;
}
public boolean isTouchDown(int pointer);
public int getTouchX(int pointer);
public int getTouchY(int pointer);
public List<TouchEvent> getTouchEvents();
}
and here is it's implementation:
public class SingleTouchHandler implements TouchHandler {
boolean isTouched;
int touchX;
int touchY;
Pool<TouchEvent> touchEventPool;
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>();
float scaleX;
float scaleY;
public SingleTouchHandler(View view, float scaleX, float scaleY) {
PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() {
@Override
public TouchEvent createObject() {
return new TouchEvent();
}
};
touchEventPool = new Pool<TouchEvent>(factory, 100);
view.setOnTouchListener(this);
this.scaleX = scaleX;
this.scaleY = scaleY;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
synchronized(this) {
TouchEvent touchEvent = touchEventPool.newObject();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchEvent.type = TouchEvent.TOUCH_DOWN;
isTouched = true;
break;
case MotionEvent.ACTION_MOVE:
touchEvent.type = TouchEvent.TOUCH_DRAGGED;
isTouched = true;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touchEvent.type = TouchEvent.TOUCH_UP;
isTouched = false;
break;
}
touchEvent.x = touchX = (int)(event.getX() * scaleX);
touchEvent.y = touchY = (int)(event.getY() * scaleY);
touchEventsBuffer.add(touchEvent);
return true;
}
}
@Override
public boolean isTouchDown(int pointer) {
synchronized(this) {
if(pointer == 0)
return isTouched;
else
return false;
}
}
@Override
public int getTouchX(int pointer) {
synchronized(this) {
return touchX;
}
}
@Override
public int getTouchY(int pointer) {
synchronized(this) {
return touchY;
}
}
@Override
public List<TouchEvent> getTouchEvents() {
synchronized(this) {
int len = touchEvents.size();
for( int i = 0; i < len; i++ )
touchEventPool.free(touchEvents.get(i));
touchEvents.clear();
touchEvents.addAll(touchEventsBuffer);
touchEventsBuffer.clear();
return touchEvents;
}
}
}
Again, these are a framework provided by the good man James Cho from Kilobolt and readily available on the Kilobolt website if wanted.
In my implementation: TOUCH_DOWN, a variable used to represent any ACTION_DOWN usage, work fine. However, TOUCH_UP (for ACTION_UP) doesn't work at all. Here is a block of code where I use it in my games Update Function:
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = (TouchEvent) touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_DOWN) {
}
if (event.type == TouchEvent.TOUCH_UP) {
if (inBounds(event, 190, 350, 100, 100)) {
game.setScreen(new Menu(game));
}
}
}
In my code above, when the touch is lifted off the screen, TOUCH_UP should allow my game state to change to the Menu Screen. However, nothing happens.
If I placed game.setScreen(new Menu(game));
in the if statement:
if (event.type == TouchEvent.TOUCH_DOWN)
it works fine.
Is it an error in the code or do I have a misunderstanding of how ACTION_UP and the other actions work? I test using a Samsung Galaxy S5.
Thanks for any help. Learning Android Studio and game development has been one heck of a process, but I'm definitely getting better.
答案 0 :(得分:1)
您可能会在false
上返回ACTION_DOWN
。
ACTION_UP
仅在您true
事件返回ACTION_DOWN
时有效。
答案 1 :(得分:0)
你好像在这里重新发明轮子。你尝试过一种更简单的方法吗?
首先,实现实际的侦听器,如View.OnTouchListener。它很简单,在API级别1中引入,并且运行良好。
事实上,我甚至不会有一个SingleTouchHandler类(除非您计划在多个视图上设置此触摸侦听器。在这种情况下,实现OnTouchListener而不是TouchHandler)。我只是在OnTouchListener的构造函数中初始化onTouch方法,如下所示:
view.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event){
//Synchronize if you wish
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
//Press code
break;
case MotionEvent.ACTION_MOVE:
//Move code
break;
case MotionEvent.ACTION_UP:
//release code
break;
}
return true;
}
});
根本不需要额外的课程。只需将它包含在View子类的构造函数中即可。这已经过测试,并且在SurfaceViews上按预期工作,如果您正在编写动态游戏,那么您应该正在使用它。其次,如上所述,如果您希望在多个视图上设置此OnTouchListener,那么您需要将其设置为自己的类,如您已有的类(SingleTouchHandler)并使其实现View.OnTouchListener(而不是TouchHandler) )。然而,再次假设您正在编写动态游戏,所有图形很可能都是在一个SurfaceView上绘制的,这意味着只有一个View可以在其上分配这个OnTouchListener,从而无需一个类一起使用(使用上面显示的方法。)