PDA

Просмотр полной версии : Управление в игре на клавиатуре.как справиться с .onKeyUp .onKeyDown?


Badim
12.01.2006, 13:19
Здравствуйте.
пишу(точнее уже почти доделал) игру скролер(типа марио).
Игра придназначаеться для web.
для управления с клавиатуры след код:

var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
switch (Key.getCode()) {
case Key.RIGHT :
_root.main.game.move(1);
break;
case Key.LEFT :
_root.main.game.move(-1);
break;
case Key.SPACE :
_root.main.game.jump_char();
break;
}
};
keyListener.onKeyUp = function() {
switch (Key.getCode()) {
case Key.RIGHT :
_root.main.game.shar_stop();
break;
case Key.LEFT :
_root.main.game.shar_stop();
break;
}
};
Key.addListener(keyListener);

И возникла проблема:
что если бежать, потом прыгнуть, а потом отпустить влево(или право), то персонаж бежит дальше. Вроде как пробел вызывает onKeyUp, и после этого, отпускание другой клавиши - onKeyUp уже не работает.

сама игра:
http://ya-zvezda.ru/turtle/main.html
200кб

motor4ik
12.01.2006, 13:22
а че так тормозит бешенно?

Badim
12.01.2006, 13:23
а какой комп?
З.Ы. на 1.2 ГГерца и 256 оперативки - идет так как надо.
=)
З.Ы.Ы.
пожалуста, игра не для обсуждения, она не доделана, хотелось бы решить вопрос по коду.

nyctota
12.01.2006, 13:31
А не пробовал 2 Listener'a для движения и прыжка создавать?

motor4ik
12.01.2006, 13:33
ну да я тоже думаю что эта проблема не так сложна...просто нужно подумать...:=)

Badim
12.01.2006, 13:55
да
пробывал.
проблема осталась

silin
12.01.2006, 15:15
по ходу получается, что onKeyUp генерится когда все клавиши отпущены, т.е. отследить с его помощбю последовательное отжатие не судьба..
как вариант: заставить мувик следить за нажатием/отжатием, ну и сообщать об изменениях:
import mx.events.EventDispatcher;
//сщздаем мувик, который будет следить за клавишами RIGHT, LEFT & SPACE
this.createEmptyMovieClip('keyDispatcher',this.getNextHighestDepth());
keyDispatcher.keys={r:false,l:false,s:false};//для контроля
EventDispatcher.initialize(keyDispatcher);//копируем в него методы диспатчера

keyDispatcher.onEnterFrame=function(){
var k=this.keys;
//если состояние клавиши меняется, то рапортуем (вещаем событие 'key')
if(k.r!=Key.isDown(Key.RIGHT)){
this.dispatchEvent({type:'key',what:k.r ? 'up' : 'down',key:'right',time:getTimer()});
}
if(k.l!=Key.isDown(Key.LEFT)){
this.dispatchEvent({type:'key',what:k.l ? 'up' : 'down',key:'left',time:getTimer()});
}
if(k.s!=Key.isDown(Key.SPACE)){
this.dispatchEvent({type:'key',what:k.s ? 'up' : 'down',key:'space',time:getTimer()});
}
this.keys={r:Key.isDown(Key.RIGHT),l:Key.isDown(Key.LEFT),s:Key.isDown(Key.SPACE)};
}
//подписываем функцию onKey, на прослушку события 'key'
keyDispatcher.addEventListener('key',onKey);
//теперь всегда знаем когда, какую и что сделали(нажали/отпустили)...
function onKey(e){
trace('________');
trace('when :'+e.time);
trace('key :'+e.key+' ('+e.what+')');

}

silin
12.01.2006, 15:36
в догонку: как отследить тоже самое для всех клавиш
import mx.events.EventDispatcher;
this.createEmptyMovieClip('keyDispatcher',this.getNextHighestDepth());
//пихаем в массив все коды (вообще-то это лишнее: зачем перебирать то, что не нужно..
for(var i=0,k=keyDispatcher.keys=[];i<255;i++)k.push(false);
EventDispatcher.initialize(keyDispatcher);//копируем в него методы диспатчера
keyDispatcher.onEnterFrame=function(){
var k=this.keys;
for(var i in k){
//если состояние клавиши меняется, то рапортуем (вещаем событие 'key')
if(k[i]!=Key.isDown(i)) this.dispatchEvent({type:'key',what:k[i] ? 'up' : 'down',key:i,time:getTimer()});
k[i]=Key.isDown(i);
}
}
keyDispatcher.addEventListener('key',onKey);
function onKey(e){
trace('________');
trace('when :'+e.time);
trace('key# :'+e.key+' ('+e.what+')');
}

Badim
12.01.2006, 16:45
Это тоже хороший код.
но у него есть проблема - во первых какието странные баги =)
а во вторых, что очень важно, в Броузере он не работает(в дебагере рабоатет, а вот в броузере ну ни как) =(((
или я что то забыл сделать еще?

silin
12.01.2006, 17:00
какие баги ? ,ну кроме того, что странные..
в браузере там и нечему работать..,
собственно это только способ решения твоей проблемы, как ты его применишь вопрос другой..
зы: еще, не пиши так
switch (Key.getCode()) {
case Key.RIGHT :
_root.main.game.shar_stop();
break;
case Key.LEFT :
_root.main.game.shar_stop();
break;
}будь проще : _root.main.game.shar_stop(); :)

Badim
12.01.2006, 17:07
какие баги ? ,ну кроме того, что странные..
в браузере там и нечему работать..,
собственно это только способ решения твоей проблемы, как ты его применишь вопрос другой..
зы: еще, не пиши так
switch (Key.getCode()) {
case Key.RIGHT :
_root.main.game.shar_stop();
break;
case Key.LEFT :
_root.main.game.shar_stop();
break;
}будь проще : _root.main.game.shar_stop(); :)
всмысле где зедсь проще то?
вообщето, лучше писать так:
switch (Key.getCode()) {
case Key.RIGHT :
case Key.LEFT :
_root.main.game.shar_stop();
break;
}
но если сделать как ты сказал, то чар будет останавливаться после отжатия пробел.
...
Проблема осталась кстати =)
З.Ы. Если, хочешь я могу выложить версию с твоим кодом. он рабоает в плеере, но в браузере не очень.

silin
12.01.2006, 17:18
>>но если сделать как ты сказал, то чар будет останавливаться после отжатия пробел.
ОК, согласен, но switch вместо if все равно не смотрится..
>>Если, хочешь я могу выложить версию с твоим кодом. он рабоает в плеере, но в браузере не очень.
если честно: не хочу..
соображения: диспатчер висит на onEnterFrame, стало быть реагирует не мгновенно, а только при смене кадра, возможно отсюда траблы..(попробовать увеличить фпс, или на setInterval это добро повесить..)

Antares
12.01.2006, 17:30
Написал во Flashcoders -- посмотрим, что делают люди в таких случаях. Спасибо за первую интересную тему за неделю.

Badim
12.01.2006, 17:49
http://www.actionscript.org/forums/showthread.php3?t=93745
-
этот же пост. могу перевести кому надо.
...
сетИнтервалы тоже пробывал, тоже не помогли.
..
>ОК, согласен, но switch вместо if все равно не смотрится..
ИМХО это holy wars, поэтому отвечать не буду.
>соображения: диспатчер висит на onEnterFrame, стало быть реагирует >не мгновенно, а только при смене кадра, возможно отсюда траблы..>(попробовать увеличить фпс, или на setInterval это добро повесить..)
ни то не то не помогло.
как я сказал, в первом посте, необходима, чтобы игра работа в Броузере.

silin
12.01.2006, 18:19
Badim, а можешь сгенерить показательный примерчик (не надо всю игру) с проблемой?

Badim
12.01.2006, 18:30
ну вот пример в аттаче исходник проблемы.

silin
12.01.2006, 20:07
вобщем я так и не понял, что за проблема с браузером: у меня одинаково работает как в IDE так и браузере(FF1.5)..
решение с глобальным вещанием события:
import mx.events.EventDispatcher;
var xspeed = 0, yspeed = 0;
var kd=[{state:false,code:Key.RIGHT},{state:false,code:Key.LEFT},{state:false,code:Key.SPACE}];
EventDispatcher.initialize(kd);
kd.addEventListener('key',onKey);
setInterval(function(){
for(var i in kd){
if(kd[i].state!=Key.isDown(kd[i].code)) kd.dispatchEvent({type:'key',what:!kd[i].state ,code:kd[i].code});
kd[i].state=Key.isDown(kd[i].code);
}
},10);

function onKey(e){
switch(e.code){
case Key.LEFT : xspeed=-1*e.what;break;
case Key.RIGHT: xspeed=1*e.what;break;
case Key.SPACE: yspeed=10*e.what;
}
}

mc.onEnterFrame = function() {//mc - управляемый мувик
this._x += xspeed*2;
this._y += yspeed;
yspeed /= 2;
if (yspeed<1) {
yspeed = 0;
}
};
если речь идет об управлении только одним мувиком (т.е. это событие больше никому и не нужно), то все может быть еще проще:
var xspeed = 0, yspeed = 0;
mc.onEnterFrame = function() {
if(Key.isDown(Key.SPACE)&& !yspeed)yspeed=10;
xspeed=0;
xspeed+=Key.isDown(Key.RIGHT)*2;
xspeed-=Key.isDown(Key.LEFT)*2;

this._x += xspeed*2;
this._y += yspeed;
yspeed /= 2;
if (yspeed<1) {
yspeed = 0;
}
};

Badim
13.01.2006, 11:30
silin
...
ты решил проблему, изменив условие =)
ты изменил архитектуру этого примера, хоть оно и работает, но оно не подходит =((((
Обязательное условие - то что персонаж перестает бегать ИМЕННО при отпускании клавиши, а не каждый фрейм.

silin
13.01.2006, 11:48
и рад бы помочь, но уже не понимаю о чем речь:
ты спрашивал как отловить отпускание всех клавиш,
а уж как он там перестает бегать, 'ИМЕННО при отпускании клавиши или каждый фрейм' (?), дело хозяйское..
к слову, в моем примере ИМЕННО при отпускании клавиши он и перестает..

Badim
13.01.2006, 12:10
первый код из 17 поста, отлично смотриться.
у меня он работает в onproblem.fla, но в игре отрубаеться управление в броузере.
моэет это из за того что теряеться фокус?

silin
13.01.2006, 12:22
тереятся или изначально не дается ?
фокус по любому нужен :кликни по флешке..

Badim
13.01.2006, 18:36
да на флэшку кликаю конечно.
тама есть кнопочки, при клике на них фокус флэшка полюбому получает.
А есть ли способ вызвать фокус на флэшку? =) из самой флэшки= 0

silin
13.01.2006, 19:06
имхо нет, это ведь фокус системы/браузера..
но утверждать не берусь

Swoo2n
24.03.2006, 15:19
Нашел интересную вещь.
Если в publish settings поставить flash player 7 или 6,
то код в первом посте работает правильно!

heilong
07.06.2006, 11:50
Столкнулся с такой же проблемой, у меня в арканоиде был такой же глюк, нашёл эту тему в поиске.
Действительно, и это очень странно, под 7 плеер работает как надо, а под 8 нет. Я использовал для теста такой код

var key_listener = new Object();
key_listener.onKeyDown = function() {
trace('down: ' + Key.getCode());
}
key_listener.onKeyUp = function() {
trace('up: ' + Key.getCode());
}
Key.addListener(key_listener)

Чтобы баг увидеть, достаточно нажать влево и держать, потом нажать и отпустить пробел. А потом отпустить влево - это событие не затрейсится, если publish под 8 плеер...

Я в итоге сделал интервал который проверяет все нужные кнопки Key.isDown(...), конечно это меня не радует... лишняя нагрузка всё-таки. И зачем тогда вся событийная архитектура, когда простой poll получается.

nouba
12.06.2006, 17:41
тереятся или изначально не дается ?
фокус по любому нужен :кликни по флешке..

В вот как сделать так чтобы не надо было кликать мышкой по флэшке... если ты гуляешь между окнами броузерами... и когда вернулся обратно, то чтобы все onKeyDown работали :)
никто не знает... я уже сам сижу и немогу понять что за фигня

Badim
13.06.2006, 18:37
по идее надо в цикле явой выставлять фокус на флэшку... но я в яве не силен, и фокус выставлялся только при загрузке. цикчиски это делать не получилось. сделали проще - если нету действия от игрока - то пауза через секудн 10.

heilong
13.06.2006, 19:41
Badim, не путай java & javascript

iNils
13.06.2006, 22:30
Badim, не путай java & javascriptв обиходе явой часто называют яваскрипт.

bbexp
13.06.2006, 23:36
< **** > упс, поспешил ))

BABU
14.06.2006, 00:28
Вот заморачиветесь а
onClipEvent (enterFrame) {
if(Key.isDown(Key.RIGHT)) {
_root.main.game.move(1);
}
if(Key.isDown(Key.LEFT)) {
_root.main.game.move(1);
}
и т.д.
так не проще...

heilong
14.06.2006, 11:38
BABU, так медленнее. Если у тебя десяток разных кнопок, и все их проверять каждый фрейм, это отнимает ресурсов. Поэтому и есть на свете модель событий, чтобы не poll-ить по сто раз в секунду какие-то переменные, а сидеть и спокойно получать сообщения... но - глючит.