Java 尝试为onKeyDown事件(Android)创建自己的方法
我有两门课: 主面板(我在其中定义了一些方法) MainThread(我使用这些方法进行循环,以创建一个经典的游戏结构) 在MainPanel类中,如果按下一个键,我可以捕获这个方法Java 尝试为onKeyDown事件(Android)创建自己的方法,java,android,sdk,onkeydown,Java,Android,Sdk,Onkeydown,我有两门课: 主面板(我在其中定义了一些方法) MainThread(我使用这些方法进行循环,以创建一个经典的游戏结构) 在MainPanel类中,如果按下一个键,我可以捕获这个方法 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch(keyCode) { case KeyEvent.KEYCODE_DPAD_UP:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
return true;
}
return false;
}
它工作正常,我的问题是,是否可以创建onKeyDown作为一个合适的方法,并在循环中使用它来避免侦听器。我们的想法是在主面板中定义如下方法:
public void myOwnOnKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
}
}
然后,像这样在主线程类上调用它到我的循环中
public class MainThread extends Thread {
//...
public void loop() {
Canvas canvas;
KeyEvent event; Log.d(TAG, "Starting game loop");
while (running) {
this.MainPanel.MyOwnOnKeyDown(keyCode, event);
this.MainPanel.moveElements();
this.MailPanel.drawElements(canvas);
}
}
在下一行,我不知道如何传递参数keyCode
this.MainPanel.MyOwnOnKeyDown(keyCode, event);
有可能吗
提前感谢看起来您正在尝试编写游戏或其他类似类型的程序 在主循环中,当您试图调用自己的keydown方法时,您应该调用类似“handleInput()”的方法,然后真正的Android keydown方法的实现应该将事件信息(keycode等)添加到队列集合中。然后,handleInput()方法将处理自上次循环以来发生的所有按键(在队列中) 下面是一个游戏的主循环示例:
public void run() {
initializeState();
while (stillRunning) { // stillRunning is a flag that signals the user wants to exit
while(isPaused() && stillRunning) { // isPaused is a flag that is set in the if the user selects pause
try {
sleep(100);
} catch (InterruptedException e) {
}
}
if(!stillRunning)
break;
Canvas c = null;
try {
c = surfaceHolder.lockCanvas(null); // the game uses a Surface view for drawing
synchronized (surfaceHolder) {
updateState(); // update game entities - such as remove explosions that are finished, etc.
handleInput(); // handle user input (key presses, screen touches, etc.)
updatePhysics(); // collision detection, speed changes due to gravity, etc.
updateAnimations(); // update which frames need to draw for animating entities
updateSound(); // start/stop any sounds required by new game state/events
updateVideo(c); // draw the next frame of video
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
具有此循环的类还有一个队列,用于保存从播放机传入的所有事件:
private ConcurrentLinkedQueue<GameEvent> eventQueue = new ConcurrentLinkedQueue<GameEvent>();
然后,这些GameEvent类被实例化并放置在标准Android事件处理程序方法中的队列中,例如:
public boolean onKeyDown(int keyCode, KeyEvent event) {
KeyGameEvent kge = new KeyGameEvent(keyCode, false, evt);
eventQueue.add(kge);
return true;
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
KeyGameEvent kge = new KeyGameEvent(keyCode, true, evt);
eventQueue.add(kge);
return true;
}
public void onLongPress(MotionEvent evt) {
LongPressGestureGameEvent lpe = new LongPressGestureGameEvent(evt);
eventQueue.add(lpe);
}
最后,handleInput()方法如下所示:
private void handleInput() {
while(true) {
GameEvent evt = eventQueue.poll();
if(evt == null)
break;
if(evt instanceof KeyGameEvent) {
processKeyGameEvent((KeyGameEvent)evt);
}
else if(evt instanceof TouchGameEvent) {
processTouchGameEvent((TouchGameEvent)evt);
}
// ... etc. for the different types of events.
}
}
显然(我希望)在HandInput()调用的processKeyGameEvent()等方法中,您实际上检查了哪些键被按下/释放,并让您的游戏逻辑执行任何适合这种按键按下/释放的操作
如果您的游戏只对键盘输入事件(而不是触摸等)感兴趣,那么您可以放弃创建GameEvent类层次结构,只需将onKeyDown()接收到的KeyEvent放入队列。看起来您正在尝试编写游戏或其他类似类型的程序 在主循环中,当您试图调用自己的keydown方法时,您应该调用类似“handleInput()”的方法,然后真正的Android keydown方法的实现应该将事件信息(keycode等)添加到队列集合中。然后,handleInput()方法将处理自上次循环以来发生的所有按键(在队列中) 下面是一个游戏的主循环示例:
public void run() {
initializeState();
while (stillRunning) { // stillRunning is a flag that signals the user wants to exit
while(isPaused() && stillRunning) { // isPaused is a flag that is set in the if the user selects pause
try {
sleep(100);
} catch (InterruptedException e) {
}
}
if(!stillRunning)
break;
Canvas c = null;
try {
c = surfaceHolder.lockCanvas(null); // the game uses a Surface view for drawing
synchronized (surfaceHolder) {
updateState(); // update game entities - such as remove explosions that are finished, etc.
handleInput(); // handle user input (key presses, screen touches, etc.)
updatePhysics(); // collision detection, speed changes due to gravity, etc.
updateAnimations(); // update which frames need to draw for animating entities
updateSound(); // start/stop any sounds required by new game state/events
updateVideo(c); // draw the next frame of video
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
具有此循环的类还有一个队列,用于保存从播放机传入的所有事件:
private ConcurrentLinkedQueue<GameEvent> eventQueue = new ConcurrentLinkedQueue<GameEvent>();
然后,这些GameEvent类被实例化并放置在标准Android事件处理程序方法中的队列中,例如:
public boolean onKeyDown(int keyCode, KeyEvent event) {
KeyGameEvent kge = new KeyGameEvent(keyCode, false, evt);
eventQueue.add(kge);
return true;
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
KeyGameEvent kge = new KeyGameEvent(keyCode, true, evt);
eventQueue.add(kge);
return true;
}
public void onLongPress(MotionEvent evt) {
LongPressGestureGameEvent lpe = new LongPressGestureGameEvent(evt);
eventQueue.add(lpe);
}
最后,handleInput()方法如下所示:
private void handleInput() {
while(true) {
GameEvent evt = eventQueue.poll();
if(evt == null)
break;
if(evt instanceof KeyGameEvent) {
processKeyGameEvent((KeyGameEvent)evt);
}
else if(evt instanceof TouchGameEvent) {
processTouchGameEvent((TouchGameEvent)evt);
}
// ... etc. for the different types of events.
}
}
显然(我希望)在HandInput()调用的processKeyGameEvent()等方法中,您实际上检查了哪些键被按下/释放,并让您的游戏逻辑执行任何适合这种按键按下/释放的操作
如果您的游戏只对键盘输入事件感兴趣(而不是触摸等),那么您可以放弃创建GameEvent类层次结构,只需将onKeyDown()接收到的KeyEvent放入队列。我认为您要做的是为某个键是否处于活动状态以及在主循环中是否引用该键设置一个变量 例如:在主面板中有一些类字段,例如:
// some constants
static int NONE = 0;
static int UP = 1;
static int DOWN = 2;
static int LEFT = 3;
static int RIGHT = 4;
// state fields
private volatile int movement = NONE;
private volatile boolean jumping = false;
那么您的onKeyDown将类似于:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = UP;
return true;
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = NONE;
return true;
}
return false;
}
onKeyUp看起来类似于:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = UP;
return true;
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = NONE;
return true;
}
return false;
}
您的主循环看起来像:
while (running) {
if (this.movement == UP) {
// update stuff
} else if (this.movement == DOWN) {
// update other stuff
} // etc ...
this.MainPanel.moveElements();
this.MailPanel.drawElements(canvas);
}
您可能需要更复杂的逻辑来跟踪按键,但这会将按钮事件与更新分离,这样您就可以进行连续移动。我认为您要做的是设置一个变量,以确定某个键是否处于活动状态,以及在主循环中是否引用该键 例如:在主面板中有一些类字段,例如:
// some constants
static int NONE = 0;
static int UP = 1;
static int DOWN = 2;
static int LEFT = 3;
static int RIGHT = 4;
// state fields
private volatile int movement = NONE;
private volatile boolean jumping = false;
那么您的onKeyDown将类似于:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = UP;
return true;
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = NONE;
return true;
}
return false;
}
onKeyUp看起来类似于:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = UP;
return true;
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
Log.i(TAG,"key up was pressed");
movement = NONE;
return true;
}
return false;
}
您的主循环看起来像:
while (running) {
if (this.movement == UP) {
// update stuff
} else if (this.movement == DOWN) {
// update other stuff
} // etc ...
this.MainPanel.moveElements();
this.MailPanel.drawElements(canvas);
}
您可能需要更复杂的逻辑来跟踪按键,但这将按钮事件与更新分开,这样您就可以连续移动。我真的怀疑您的设计方法。我敢打赌,无论你想解决什么问题,都会有一个更优雅的解决方案。我真的怀疑你的设计方法。我敢打赌,无论你想解决什么问题,都会有一个更优雅的解决方案。你能举个例子吗?当然,让我试着包含足够的代码,让你能够理解它,但是足够小,不会太大…我上面的答案现在经过编辑,包含了一个相当详细的示例。您能给出一个这样的示例吗?当然,让我尝试包含足够多的代码,您可以理解它,但足够小,不会太大…我上面的答案现在经过编辑,包含了一个相当详细的示例。