Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   www.boolean.name > Программирование игр для мобильных телефонов > MidletPascal > Проекты на MidletPascal

Ответ
 
Опции темы
Старый 20.02.2011, 20:50   #1
YellowAfterlife
ПроЭктировщик
 
Аватар для YellowAfterlife
 
Регистрация: 19.02.2011
Сообщений: 134
Написано 81 полезных сообщений
(для 219 пользователей)
Радость Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

Как вам, возможно, известно, MidletPascal не поддерживает одновременного определения нескольких нажатий кнопок. То есть, вы не можете поймать одновременно нажатые кнопки Вверх + Вправо, или Выбор + Вниз (к примеру). Это явно сужает диапазон игр, которые можно реализовать на MP (как факт, сразу выпадают платформеры и практически все динамические игры). Но есть очень милая библиотека Lib_keys, позволяющая получить целочисленную (точнее сказать, набор битов), определяющую текущее состояние кнопок. Эта тема посвящена работе с данной библиотекой.
Установка
Для того чтобы использовать Lib_keys, нужно проделать несколько простых шагов:
1. Скачать Lib_keys (ссылка в предыдущем параграфе), и скопировать содержимое zip-папки в под-папку Libs в основной папке MidletPascal.
2. Для проэкта, которому предстоит использовать данную библиотеку, выставить тип MIDlet'а на MIDP2.0 Fullscreen. Это делается следующим образом:
Для MP 2.*, в Properties\Build configurations изменить MIDlet type для всех активных конфигураций.
Для MP 3.3, в панели Project Manager поочередно для всех элементов в папке Configurations изменить MIDlet type
3. Добавить "keys" в список используемых библиотек (uses). Обычно это вторая строка программы. Если таковой нет, просто добавьте
uses keys
после строки 'program *;' .
Константы
Основная тема библиотеки предлагает нам использовать набор констант из Lib_game, то есть:
const
  
UP_PRESSED 2;
  
DOWN_PRESSED 64;
  
LEFT_PRESSED 4;
  
RIGHT_PRESSED 32;
  
FIRE_PRESSED 256;
  
GAME_A_PRESSED 512;
  
GAME_B_PRESSED 1024;
  
GAME_C_PRESSED 2048;
  
GAME_D_PRESSED 4096
Как вариант, можно использовать и свой набор констант, до тех пор пока вы понимаете что они значат, и у них правильное значение. К примеру, я использовал более короткие имена констант с одинаковым префиксом:
const
  
key_up 2;
  
key_down 64;
  
key_left 4;
  
key_right 32;
  
key_fire 256;
  
key_game_a 512;
  
key_game_b 1024;
  
key_game_c 2048;
  
key_game_d 4096

Переменная » Кнопки
В данном случае, лучшим вариантом будет использовать AND (И) для битового сравнения переменных. Работает это следующим образом:
5 and 4 = 1, поскольку 5 = 4 + 1, 4 есть в обоих числах, 1 есть лишь в одном числе.
6 and 9 = 0, поскольку 6 = 4 + 2, 9 = 8 + 1, совпадений нет.

То есть, чтобы проверить, есть ли константа кнопки в полученной переменной состояний, нам нужно проделать следующее:
var ijinteger;
// ...
:= get_key_states;
:= and key_down// если зажата кнопка "вниз", j = 64 
Но это не очень близко к тому что (скорее всего) нам нужно, поскольку переменная не логическая, и к тому же разная по велечине для всех кнопок. Поэтому нужно, как минимум, преобразовать ее в логическую. Сделать это можно с помощью обыкновенного оператора > (больше):
var iintegerbboolean;
// ...
:= get_key_states;
:= ((and key_down) > 0); // b = true, если кнопка нажата 
Используя немного знаний о приоритетах операторов в MP, или же простой метод тыка, можно обнаружить, что скобки не влияют ни на что кроме внешнего вида кода. То есть последнюю строку можно сократить до:
:= and key_down 0
Если же нам для каких-то целей нужно состояние кнопки в виде 0\1, то можно добавить следующую функцию:
function iand(abinteger): integerbegin
  
if and 0 then iand := else iand := 0;
end
Теперь мы можем, к примеру, сформировать вектор "направления" кнопок-стрелок, используя следующий код:
var ixyinteger;
// ...
:= get_key_states;
:= iand(ikey_right) - iand(ikey_left);
:= iand(ikey_down) - iand(ikey_up); 
После его выполнения, x будет указывать на смещение по горизонтали (-1..1), а y - на смещение по вертикали. То есть после этого мы можем просто домножить x и y на скорость передвижения, и прибавить их к координатам контроллируемого обьекта. Итого, для создания типичной игры, где стрелочки служат исключительно для перемещения игрока, поможет следующий код (с примером):
program keys1;
// Код системы:
uses keys// используется lib_keys
const // константы кнопок:
  
key_up 2;
  
key_down 64;
  
key_left 4;
  
key_right 32;
  
key_fire 256;
  
key_game_a 512;
  
key_game_b 1024;
  
key_game_c 2048;
  
key_game_d 4096;
var
  
key_xkey_ykey_vinteger;
  
key_akey_bkey_ckey_dkey_fboolean;
// iand - битовое И (возращает 1 или 0):
function iand(abinteger): integerbegin
  
if and 0 then iand := else iand := 0;
end;
// getkeys - процедура обновления переменных состояний кнопок.
procedure getkeysbegin
  key_v 
:= get_key_states;
  
key_x := iand(key_vkey_right) - iand(key_vkey_left);
  
key_y := iand(key_vkey_down) - iand(key_vkey_up);
  
key_a := key_v and key_game_a 0;
  
key_b := key_v and key_game_b 0;
  
key_c := key_v and key_game_c 0;
  
key_d := key_v and key_game_d 0;
  
key_f := key_v and key_fire 0;
end;

// -- Ниже идет код примера --
var xysinteger;
procedure mainDrawbegin
  setColor
(239235231);
  
fillRect(00getWidthgetHeight);
  
setColor(000);
  
fillEllipse(881616);
  
drawText(integerToString(key_v), 22);
  
rePaint;
end;
begin
  x 
:= getwidth div 2// X круга
  
:= getheight div 2// Y круга
  
:= 4// скорость передвижения
  
mainDraw;
  
repeat
    getkeys
;
    if 
true then begin
      x 
:= key_x s;
      
:= key_y s;
      if 
key_f then begin
        x 
:= random(getwidth);
        
:= random(getheight);
      
end;
      while 
do := getwidth 16;
      while 
>= getwidth do := getwidth 16;
      while 
do := getheight 16;
      while 
>= getheight do := getheight 16;
      
mainDraw;
    
end;
    
delay(32);
  
until false;
end
Итого...

У нас теперь есть игра с мячиком, который можно передвигать по экрану, оборачивать вокруг краев экрана и даже телепортировать!
Невиданный список возможных взаимодействий с игроком, не так ли?

Нажата, зажата, отпущена - определение состояний кнопок по одной переменной
Казалось бы, как можно отловить событие нажатия или отпускания кнопки, если мы знаем лишь то, нажата ли она на данный момент? Но это можно, и более того, несложно сделать. Логика для данного алгоритма выглядит следующим образом:
Если кнопка нажата:
  
Если ранее кнопка не была нажата:
    
Кнопку нажали только что.
  
Теперь кнопка нажата.
Иначе(если кнопка не нажата):
  
Если ранее кнопка была нажата:
    
Кнопку только что отпустили.
  
Теперь кнопка не нажата
А код, соответсвенно:
:= get_key_states;
    if 
and key_code 0 then begin
      
if not b then begin
        
// только что была нажата кнопка
      
end;
      
:= true;
      
// сейчас кнопка нажата
    
end else begin
      
if b then begin
        
// только что была отпущена кнопка
      
end;
      
:= false;
      
// сейчас кнопка отпущена
    
end
Ну и программа-пример, куда ведь без нее:
program keys2;
uses keys;
const
  
key_up 2;
  
key_down 64;
  
key_left 4;
  
key_right 32;
  
key_fire 256;
  
key_game_a 512;
  
key_game_b 1024;
  
key_game_c 2048;
  
key_game_d 4096;
var 
kintegerkey_fkey_fpkey_frboolean;
begin
  key_f 
:= false;
  
repeat
    k 
:= get_key_states;
    
key_fp := false;
    
key_fr := false;
    if 
and key_fire 0 then begin
      
if not key_f then begin
        key_fp 
:= true;
      
end;
      
key_f := true;
    
end else begin
      
if key_f then begin
        key_fr 
:= true;
      
end;
      
key_f := false;
    
end;
    if 
key_fp then i := 2;
    if 
key_fr then i := 1;
    
setColor(239235231);
    
fillRect(00getWidthgetHeight);
    
setColor(000);
    if 
key_f then setColor(25500);
    
drawText(integerToString(i), 22);
    
rePaint;
    
delay(32);
  
until false;
end
Ну, в общем-то это и все по этому поводу.
Если есть вопросы, задавайте.
Удачного создания игр
(Offline)
 
Ответить с цитированием
Эти 5 пользователя(ей) сказали Спасибо YellowAfterlife за это полезное сообщение:
LTS (23.02.2011), m.ksy (21.02.2011), odd (22.02.2011), RblSb (06.07.2014), ViNT (20.02.2011)
Старый 20.02.2011, 22:14   #2
ViNT
Модератор
 
Регистрация: 03.04.2007
Сообщений: 2,252
Написано 597 полезных сообщений
(для 817 пользователей)
Ответ: Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

Хорошие примеры, полезные, так держать!

Подобные статьи рекомендую размещать в разделе Наше Open Source Software, предназначенном специально для подобных статей.

Завтра эту тему и тему про ввод тоже туда перенесу.
(Offline)
 
Ответить с цитированием
Старый 25.03.2011, 17:51   #3
LTS
Оператор ЭВМ
 
Регистрация: 05.09.2010
Сообщений: 26
Написано 5 полезных сообщений
(для 16 пользователей)
Ответ: Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

Спасибо за пример!
Вопрос: Можно ли сделать либу, которая возврвщает событие KeyUP в виде кода кнопки (мне кажется так проще проверять одновременное нажатие кнопок)

и сделать проверку кнопок примерно так

uses (к примеру)keyup;

var up,down,left,right:boolean;
pressed:integer;

begin

pressed:=keytoaction(Getkeypressed);
if pressed=ga_UP then up:=true;
if pressed=ga_DOWN then down:=true;
if pressed=ga_LEFT then left:=true;
if pressed=ga_RIGHT then right:=true;

pressed:=keyup.keyup;
if pressed=ga_UP then up:=false;
if pressed=ga_DOWN then down:=false;
if pressed=ga_LEFT then left:=false;
if pressed=ga_RIGHT then right:=false;

if up then begin
y:=y-1;
...
end;
if down then begin
y:=y+1;
...
end;
..
..
..
И.Т.Д

end;
(Offline)
 
Ответить с цитированием
Старый 25.03.2011, 21:12   #4
YellowAfterlife
ПроЭктировщик
 
Аватар для YellowAfterlife
 
Регистрация: 19.02.2011
Сообщений: 134
Написано 81 полезных сообщений
(для 219 пользователей)
Ответ: Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

Сообщение от LTS Посмотреть сообщение
Спасибо за пример!
Вопрос: Можно ли сделать либу, которая возврвщает событие KeyUP в виде кода кнопки (мне кажется так проще проверять одновременное нажатие кнопок)
Можно. Вложение.
На самом деле это вызывает одну проблему - если пользователь нажимает или отпускает две кнопки за раз, то ловится одна.
Поэтому кроме этого я добавил простую систему - GetKeyNum возращает количество нажатых в этот момент кнопок, GetKey(index) возращает индекс нажатой кнопки (index в диапазоне 1..GetKeyNum).
Библиотека не совместима с аналогичными ей (насколько я знаю, из таковых только Lib_sensor, и одна моего авторства... но я ее еще не выложил), поскольку перезаписываются события основного модуля.
Все функции:
KeyStart - инициализирует библиотеку. Желательно вставить в самое начало программы.
GetKeyLen:integer - возращает максимальное замеченное количество нажатых за раз кнопок. Оставлена в ознакомительных целях.
GetKeyNum:integer - возращает количество нажатых в данный момент кнопок.
GetKey(n:integer):integer - возращает n-ую нажатую кнопку. Если n < 1, возращается первая кнопка. Если n > GetKeyNum, возращается 0.
GetKeyPressed:integer - возращает последнюю нажатую кнопку, аналогично GetKeyClicked.
GetKeyReleased:integer - возращает последнюю отпущенную кнопку.
Пример кода:
program SampleProject;
uses ukey;
var
  
tiinteger;
  
sstring;
function 
DrawTextBy(sstringxyinteger): integer;
begin
  DrawText
(sxy);
  
DrawTextBy := GetStringHeight(s);
end;
begin
  KeyStart
;
  
Debug('Start.');
  
repeat
    SetColor
(240240240);
    
FillRect(00GetWidthGetHeight);
    
SetColor(808080);
    
:= GetStringHeight('World.');
    
DrawText('Max keys: ' GetKeyLen00);
    
:= '';
    for 
:= 1 to GetKeyNum do := GetKey(i) + ';';
    
DrawText('Now keys: ' GetKeyNum0t);
    
DrawText('Key indexes: ' s02);
    
:= '';
    for 
:= 1 to GetKeyNum do := KeyToAction(GetKey(i)) + ';';
    
DrawText('Game indexes: ' s03);
    
RePaint;
  
forever;
end
Вложения
Тип файла: zip Lib_ukey.zip (1,018 байт, 285 просмотров)
__________________

Мой сайт-блог. Игры, обновления, примеры для Haxe, JavaScript(+HTML5), GameMaker, Love2d...
(Offline)
 
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо YellowAfterlife за это полезное сообщение:
DIMMON4IK (05.07.2011), LTS (26.03.2011), RblSb (01.09.2013)
Старый 26.03.2011, 11:48   #5
LTS
Оператор ЭВМ
 
Регистрация: 05.09.2010
Сообщений: 26
Написано 5 полезных сообщений
(для 16 пользователей)
Хорошо Ответ: Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

Спасибо!!
Отличная либа, как раз то что было нужно!!
(Offline)
 
Ответить с цитированием
Старый 14.09.2013, 19:04   #6
RblSb
Оператор ЭВМ
 
Аватар для RblSb
 
Регистрация: 25.08.2013
Адрес: Москва
Сообщений: 45
Написано 13 полезных сообщений
(для 28 пользователей)
Ответ: Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

а как же getkeyclicked в ukey?
(Offline)
 
Ответить с цитированием
Старый 19.09.2013, 22:07   #7
YellowAfterlife
ПроЭктировщик
 
Аватар для YellowAfterlife
 
Регистрация: 19.02.2011
Сообщений: 134
Написано 81 полезных сообщений
(для 219 пользователей)
Ответ: Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

Сообщение от RblSb Посмотреть сообщение
а как же getkeyclicked в ukey?
Можно, но зачем?
Если нужен эффект "пока не нажмут любую клавишу", это достигается условием рода
if (get_key_states <> 0) then
    // было что-либо нажато
end;
Как обстоят дела в Некропостии, кстати?
__________________

Мой сайт-блог. Игры, обновления, примеры для Haxe, JavaScript(+HTML5), GameMaker, Love2d...
(Offline)
 
Ответить с цитированием
Старый 22.09.2013, 16:12   #8
RblSb
Оператор ЭВМ
 
Аватар для RblSb
 
Регистрация: 25.08.2013
Адрес: Москва
Сообщений: 45
Написано 13 полезных сообщений
(для 28 пользователей)
Ответ: Пример использования lib_keys (отслеживание одновременного нажатия кнопок)

Сообщение от YellowAfterlife Посмотреть сообщение
Можно, но зачем?
Ну, отпускание клавиш использовать не очень-то удобно, например в играх на реакцию, да и в общем оно бесполезно, а писать и использовать алгоритм на основе getkeypressed нет особого желания... Не могли бы вы добавить getkeyclicked? Был бы благодарен

Сообщение от YellowAfterlife Посмотреть сообщение
Как обстоят дела в Некропостии, кстати?
Ну, если автор темы еще жив, почему бы не написать? МП тоже еще не умер.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +1, время: 02:48.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com