játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5448
FZoli:    4892
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2520

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2188
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1625
syam:    1491
Xna 02 2010.10.14 17:28


Üdv mindenkinek!

Az input kezelése elengedhetetlen egy játékban, így ez lenne a cikk témája.

Input, mint beviteli eszköz, billentyűzet, egér (illetve az XNA lehetőséget ad Xbox360 game controller feldolgozására is). Ezt a kettőt szeretnénk figyelni, és ezek segítségével végrehajtani bizonyos feladatokat, minél egyszerűbben.

Billentyűzet

Hozzunk létre az engine-n belül egy Input nevű osztályt.

Mind a billentyűzet, mind az egér esetén szükség lesz ún. state-kre. Billentyűzet esetén ez a következő (Szükségünk lesz az előző frame state-jére is) :
Kód:
private KeyboardState m_CurrKeyState;
private KeyboardState m_LastKeyState;

Ezeket nekünk minden frameben figyelni kell, le kell kérnünk, hogy melyik billentyű lett lenyomva. Ezt nagyon egyszerűen meg is tehetjük.
Kód:
public void Update()
{
    m_LastKeyState = m_CurrKeyState;
    m_CurrKeyState = Keyboard.GetState();
}

Ezután következhetnek a mi bool "típusú" metódusaink, amik igencsak meg tudják könnyíteni az ember életét :)
Előszőr is a legegyszerűbb, derítsük ki, hogy egy adott key le van-e nyomva. A billentyűkre van egy struktúra az XNA-ban, meglepő módon Keys a neve :)
Kód:
public bool KeyIsPress(Keys p_Key)
{
    if (m_CurrKeyState.IsKeyDown(p_Key))
        return true;

    return false;
}

Paraméterként megkapja, hogy melyik keyről szeretnénk tudni, hogy le van-e nyomva. Ez minden frame-ben true-val tér vissza, amég nyomjuk a billentyűt. Néha azonban nem árt, ha csak egyszer lesz true, bármeddig is taposunk az adott billentyűn (pl. ESC-re menü megnyitása / bezárása). Ha elképzeljük, ez csak egyszer lehetséges:
Kód:
előző frame:
- last: nincs lenyomva
- curr: nincs lenyomva
jelenlegi frame:
- last: nincs lenyomva
- curr: le van nyomva
következő frame:
- last: le van nyomva
- curr: le van nyomva / nincs lenyomva

Mint láthatjuk akkor következik be, ha a currKeystate szerint le van nyomva, a lastKeystate szerint pedig nincs:
Kód:
public bool KeyIsPressed(Keys p_Key)
{
    if (m_CurrKeyState.IsKeyDown(p_Key) && !m_LastKeyState.IsKeyDown(p_Key))
        return true;

    return false;
}

Ezekhez hasonlóan néha arra van csak szükség, hogy az adott műveletet akkor hajtsa végre, ha le van nyomva és előzőleg is le volt nyomva, vagy előzőleg le volt nyomva, de már nincs :
Kód:
public bool KeyLastIsPress(Keys p_Key)
{
    if (m_LastKeyState.IsKeyDown(p_Key))
        return true;

    return false;
}

public bool KeyLastIsPressed(Keys p_Key)
{
    if (m_LastKeyState.IsKeyDown(p_Key) && !m_CurrKeyState.IsKeyDown(p_Key))
        return true;

    return false;
}


Egér

A billentyűkezeléshez nagyon hasonlít az egéré is. Eltárolom emellett az egér jelenlegi, és előző pozícióját is.
Kód:
private MouseState m_CurrMouseState;
private MouseState m_LastMouseState;

private Vector2 m_CurrMousePosition;
private Vector2 m_LastMousePosition;

Amit szeretném, ha kívülről csak olvasni tudnának:
Kód:
public Vector2 MouseCurrentPosition
{
    get { return m_CurrMousePosition; }
}
public Vector2 MouseLastPosition
{
    get { return m_LastMousePosition; }
}

Az egeret is, a billentyűzethez hasonlóan minden frameben célszerű figyelni, és lekérdezni az állapotát:
Kód:
m_LastMouseState = m_CurrMouseState;
m_CurrMouseState = Mouse.GetState();

m_LastMousePosition.X = m_CurrMousePosition.X;
m_LastMousePosition.Y = m_CurrMousePosition.Y;

m_CurrMousePosition.X = m_CurrMouseState.X;
m_CurrMousePosition.Y = m_CurrMouseState.Y;

Itt is ugyan úgy szükségünk lesz funckiókra. Kettőt bemutatok, a többi megírását az olvasóra bízom :)
Kód:
public bool MouseLeftPress()
{
    if (m_CurrMouseState.LeftButton == ButtonState.Pressed)
        return true;

    return false;
}
public bool MouseLeftPressed()
{
    if (m_CurrMouseState.LeftButton == ButtonState.Pressed && m_LastMouseState.LeftButton == ButtonState.Released)
        return true;

    return false;
}

Az egérnél egy plusz dolog: szükség lehet a pozíciójának megadására. Erre is van egy nagyon egyszerű megoldás:
Kód:
public void SetMousePosition(Vector2 p_Position)
{
    m_CurrMousePosition = p_Position;
    m_LastMousePosition = p_Position;
    Mouse.SetPosition((int)p_Position.X, (int)p_Position.Y);
}

Ezt akár Property-n keresztül is megtehetnénk, de nekem így kényelmesebb :)

Használata

A Game osztályban deklaráljunk egy új változót:
Kód:
protected Input m_Input;

Amit szeretnénk, ha kívülről látnának
Kód:
public Input Input
{
    get { return m_Input; }
}

Az Initialize metódusban létrehozzuk
Kód:
m_Input = new Input();

Az Update-ben pedig a base.Update() előtt meghívjük az Update metódusát:
Kód:
protected override void Update(GameTime gameTime)
{
    m_Input.Update();

    base.Update(gameTime);
}

Kipróbálás céljából az m_Input.Update után beírhatjuk a következő sort:
Kód:
if (m_Input.KeyIsPressed(Microsoft.Xna.Framework.Input.Keys.Escape))
    Exit();

Az Exit metódus a Microsoft.Xna.Framework.Game osztály metódusa (azaz beépített).

Futtassuk a programot, és tapasztalhatjuk, hogy ha lenyomjuk az ESC-t, akkor bezárja az ablakot :)

A következő leckében egy kicsit látványosabb dolog fog következni, sprite-ok, avagy képek kirajzolása. :)

Üdv,
Pretender

Értékelés: 0

Új hozzászólás
Pretender          2012.02.10 17:02
Hehe, jókor olvastam a hozzászólást: minden esetre örülök
SANTANTICA          2011.06.18 19:33
Köszönet, nagyon hasznos volt és alkalmazni is tudtam.
Már egy régi problémámat oldotta meg a "tenyerelős" része
Pretender          2010.10.25 14:29
"Ez így egy az egyben benne van a API doksiban is. Később azért remélhetőleg lesznek bővebben kifejtett tutorok is. "
Csak en nem ertem, h ebben a ket mondatban mire vonatkozik a kovetkezo?
"sak próbáltam segíteni, meg tanácsot adni, amit én is látok a profiktól."
Pretender          2010.10.25 14:18
"de tényleg nyújtsanak többet, mint ami az API doksiban van" - Mutasd meg, hogy kell csinalni, my master!
mark576          2010.10.25 13:51
Jólvan mester csak próbáltam segíteni, meg tanácsot adni, amit én is látok a profiktól. Ezt lehet hülyeségnek is venni, mert még nem érted. Nah sok sikert a többi tutorhoz, de tényleg nyújtsanak többet, mint ami az API doksiban van, mert az alapvető, hogy egy fejlesztő a doksit bevágja elsőnek, ez van.
Pretender          2010.10.25 13:46
Koszi Kuz! Amugy a kovi 2 lecke varat magara, megirva mar megvan, csak a portalmotor x codeblocknal tobbet nem bir, igy vagy at kell fogalmaznom, vagy azt kell megoldani. A kovetkezo a sprite, az azt koveto az animalt sprite
Kuz          2010.10.25 13:37
Én is első sörben google-özök, valahogy azt szoktam meg. F1-et csak akkor ütök, ha valamiért mellémegy egy leütés.
A cikkek amúgy jók, ajánlom esetleg még source-nak a videoanyaggal teletömött xna tutorial sorozatot, ahol maya modelekkel csinál az oktató egy egyszerű kis tps shootert. Pont az inputkezelés az, amit egész érdekes old meg, érdemes ránézni.
Pretender          2010.10.22 15:53
Semmi baj^^
Mellesleg mar mondani is akartam, ha nem tetszik, ne olvasd el. Persze, ha valami ertelmes hozzaszolast is tudsz tenni, akkor ugy rendben van
mark576          2010.10.22 15:22
Ja értem, elnézést mester.
Pretender          2010.10.22 15:17
Google.hu, vagy kitalalom magamnak... ne legyel mar ennyire primitiv.
mark576          2010.10.22 15:14
Pretender
En nem tudom, sose neztem meg az API doksit

Akkor hogy a p*csába fejlesztesz? Ezt most komolyan kérdezem. Nálam már az F1 gomb ki van kopva kb ennyire használom a doksikat fejlesztgetés közben.
Matzi          2010.10.21 09:59
Nem célozgattam én senkire, ez csak a személyes tapasztalatom. Sajnos tényleg rengeteg tutorial van megkezdve és abbahagyva, mindenféle témában. A legtöbb eljut odáig, hogy kirajzol egy színes kockát (vagy ezzel megegyező szintre más rémávan), és mikor jönnének a szaftosabb témák, megszűnik.
Asylum          2010.10.21 06:54
Matzi-nak reagáltam.
Pretender          2010.10.20 21:09
Mire? Kitol?
Asylum          2010.10.20 20:29
Hmm ez ugye nem célzás volt?
Matzi          2010.10.19 15:42
Egy kezdőknek szóló cikkben szerintem nem gond, hogyha az API szükséges részeit érthetően és magyarul dolgozza fel. Kezdőként viszonylag kevesen tudják egyáltalán hol keressék a szükséges információt.
Szerintem jó, hogy születik ilyen tutorial, és remélem sok részt meg fog élni a sorozat, mert a net tele van 1-2 rész után megszakadt sorozatokkal.
Pretender          2010.10.19 13:36
En nem tudom, sose neztem meg az API doksit ezen tul sok mindent nem lehet kifejteni, ha jol tudom pont ez lenne a lenyege az xna-nak. Irtad az elozo leckenel is, hogy reszletezem-e a draw metodust. Nem. Mint mondtam, ez az xna lenyege, beirod, h kukorica.Draw(), es az megjeleniti neked, nem kell (persze nem tilos) ertened, hogy miert.
mark576          2010.10.19 09:05
Ez így egy az egyben benne van a API doksiban is. Később azért remélhetőleg lesznek bővebben kifejtett tutorok is.
Pretender          2010.10.18 15:37
Koszi, orulok, ha lehet erteni, a fogalmazas sosem volt az erossegem
robee00          2010.10.18 15:16
nagyon jó cikk lett, jól fogalmaztad meg a dolgokat, könnyen érthető