Просмотр полной версии : Управление в игре на клавиатуре.как справиться с .onKeyUp .onKeyDown?
Здравствуйте.
пишу(точнее уже почти доделал) игру скролер(типа марио).
Игра придназначаеться для 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
а че так тормозит бешенно?
а какой комп?
З.Ы. на 1.2 ГГерца и 256 оперативки - идет так как надо.
=)
З.Ы.Ы.
пожалуста, игра не для обсуждения, она не доделана, хотелось бы решить вопрос по коду.
А не пробовал 2 Listener'a для движения и прыжка создавать?
motor4ik
12.01.2006, 13:33
ну да я тоже думаю что эта проблема не так сложна...просто нужно подумать...:=)
да
пробывал.
проблема осталась
по ходу получается, что 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+')');
}
в догонку: как отследить тоже самое для всех клавиш
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+')');
}
Это тоже хороший код.
но у него есть проблема - во первых какието странные баги =)
а во вторых, что очень важно, в Броузере он не работает(в дебагере рабоатет, а вот в броузере ну ни как) =(((
или я что то забыл сделать еще?
какие баги ? ,ну кроме того, что странные..
в браузере там и нечему работать..,
собственно это только способ решения твоей проблемы, как ты его применишь вопрос другой..
зы: еще, не пиши так
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 :
_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;
}
но если сделать как ты сказал, то чар будет останавливаться после отжатия пробел.
...
Проблема осталась кстати =)
З.Ы. Если, хочешь я могу выложить версию с твоим кодом. он рабоает в плеере, но в браузере не очень.
>>но если сделать как ты сказал, то чар будет останавливаться после отжатия пробел.
ОК, согласен, но switch вместо if все равно не смотрится..
>>Если, хочешь я могу выложить версию с твоим кодом. он рабоает в плеере, но в браузере не очень.
если честно: не хочу..
соображения: диспатчер висит на onEnterFrame, стало быть реагирует не мгновенно, а только при смене кадра, возможно отсюда траблы..(попробовать увеличить фпс, или на setInterval это добро повесить..)
Написал во Flashcoders -- посмотрим, что делают люди в таких случаях. Спасибо за первую интересную тему за неделю.
http://www.actionscript.org/forums/showthread.php3?t=93745
-
этот же пост. могу перевести кому надо.
...
сетИнтервалы тоже пробывал, тоже не помогли.
..
>ОК, согласен, но switch вместо if все равно не смотрится..
ИМХО это holy wars, поэтому отвечать не буду.
>соображения: диспатчер висит на onEnterFrame, стало быть реагирует >не мгновенно, а только при смене кадра, возможно отсюда траблы..>(попробовать увеличить фпс, или на setInterval это добро повесить..)
ни то не то не помогло.
как я сказал, в первом посте, необходима, чтобы игра работа в Броузере.
Badim, а можешь сгенерить показательный примерчик (не надо всю игру) с проблемой?
ну вот пример в аттаче исходник проблемы.
вобщем я так и не понял, что за проблема с браузером: у меня одинаково работает как в 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;
}
};
silin
...
ты решил проблему, изменив условие =)
ты изменил архитектуру этого примера, хоть оно и работает, но оно не подходит =((((
Обязательное условие - то что персонаж перестает бегать ИМЕННО при отпускании клавиши, а не каждый фрейм.
и рад бы помочь, но уже не понимаю о чем речь:
ты спрашивал как отловить отпускание всех клавиш,
а уж как он там перестает бегать, 'ИМЕННО при отпускании клавиши или каждый фрейм' (?), дело хозяйское..
к слову, в моем примере ИМЕННО при отпускании клавиши он и перестает..
первый код из 17 поста, отлично смотриться.
у меня он работает в onproblem.fla, но в игре отрубаеться управление в броузере.
моэет это из за того что теряеться фокус?
тереятся или изначально не дается ?
фокус по любому нужен :кликни по флешке..
да на флэшку кликаю конечно.
тама есть кнопочки, при клике на них фокус флэшка полюбому получает.
А есть ли способ вызвать фокус на флэшку? =) из самой флэшки= 0
имхо нет, это ведь фокус системы/браузера..
но утверждать не берусь
Нашел интересную вещь.
Если в publish settings поставить flash player 7 или 6,
то код в первом посте работает правильно!
Столкнулся с такой же проблемой, у меня в арканоиде был такой же глюк, нашёл эту тему в поиске.
Действительно, и это очень странно, под 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 получается.
тереятся или изначально не дается ?
фокус по любому нужен :кликни по флешке..
В вот как сделать так чтобы не надо было кликать мышкой по флэшке... если ты гуляешь между окнами броузерами... и когда вернулся обратно, то чтобы все onKeyDown работали :)
никто не знает... я уже сам сижу и немогу понять что за фигня
по идее надо в цикле явой выставлять фокус на флэшку... но я в яве не силен, и фокус выставлялся только при загрузке. цикчиски это делать не получилось. сделали проще - если нету действия от игрока - то пауза через секудн 10.
Badim, не путай java & javascript
Badim, не путай java & javascriptв обиходе явой часто называют яваскрипт.
< **** > упс, поспешил ))
Вот заморачиветесь а
onClipEvent (enterFrame) {
if(Key.isDown(Key.RIGHT)) {
_root.main.game.move(1);
}
if(Key.isDown(Key.LEFT)) {
_root.main.game.move(1);
}
и т.д.
так не проще...
BABU, так медленнее. Если у тебя десяток разных кнопок, и все их проверять каждый фрейм, это отнимает ресурсов. Поэтому и есть на свете модель событий, чтобы не poll-ить по сто раз в секунду какие-то переменные, а сидеть и спокойно получать сообщения... но - глючит.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.