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
(C++) Foxi 2D-s programozás leckéi 5. - Egér 2007.08.13 15:00


Üdvözöllek!

Egér kezelése hasonló a billentyűzethez. A már létrejött Directx input objektumon keresztül hozzuk létre az egeret, vagy ha még nincs objektum, azt is létrehozzuk az initmouse() -ban.
Dekraláció:

public:
    INPUT();
    ~INPUT();
    LPDIRECTINPUTDEVICE8 bill;
    LPDIRECTINPUTDEVICE8 mouse;
    LPDIRECTINPUTDEVICE8 joy;
    bool init_key();
    bool init_mouse();
    bool init_joy();
    bool get_key(unsigned char,bool frissit=false);
    DIMOUSESTATE* get_mouse();//a kitöltött struktúra mutatójával tér vissza

    LPDIJOYSTATE get_joy(); //a kitöltött struktúrával tér vissza

protected:
    LPDIRECTINPUT8 lpDI; //input objektum ezen keresztül hozzuk létre a többit
    BYTE key_buf[256];
    DIMOUSESTATE mouse_buf;//egér adatainak puffer
    DIJOYSTATE joy_buf;
    DIDEVICEINSTANCE eszk_info; //struktúra rendelkezésre álló eszköz adatainak.(joy,botkormány,stb.)
    LPDIRECTINPUTDEVICE2 dev2;
    bool joy_ok;

A megvalósítás:
Először is inicializáljuk,majd törüljük az új objektumot a konstruktorban és a destruktorban:

INPUT::INPUT()
{
    bill=NULL;mouse=NULL;joy=NULL;joy_ok=false;
}
//
INPUT::~INPUT()
{
    if(bill){bill->Release();bill=NULL;}
    if(mouse){mouse->Release();mouse=NULL;}
    lpDI->Release();lpDI=NULL;
};

Bár a fordító garantálja a statikus lefoglalt területek (mutatók) 0-val való feltöltését, azért ha a konstruktorban inicializáljuk a pointert, abból nem lesz baj.
Az init függvény:

bool INPUT::init_mouse()
{
    BOOL inf; //infó,hogy sikerült- e a függvény
    if( !lpDI)//ha még más nem hozta létre az objektumot
    {
        inf=DirectInput8Create( hinstance, DIRECTINPUT_VERSION, IID_IDirectInput8A, (VOID**)&lpDI, NULL);
        if (inf !=DI_OK)return false;//ha nem sikerült
    }
    if(mouse){mouse->Release();mouse=NULL;}
    inf=lpDI->CreateDevice(GUID_SysMouse, &mouse, NULL);//kerálunk egeret
    if(inf !=DI_OK)return false;
    inf=mouse->SetDataFormat(&c_dfDIMouse);//egér forma az adat
    if(inf !=DI_OK)return false;
    inf=bill->SetCooperativeLevel(hwnd,DISCL_FOREGROUND | DISCL_EXCLUSIVE);
    //aktiv=true;
    mouse->Acquire();//aktiváljuk

    return true;
}

Mint látható szinte azonos a billentyűzettel, csak az adatformátum más (szép lenne 105 gomb az egeren)
Nézzük az adatok elérését:

DIMOUSESTATE* INPUT:: get_mouse()
{

    if(mouse->GetDeviceState(sizeof(mouse_buf),&mouse_buf)==DIERR_INPUTLOST)
        mouse->Acquire();
    return &mouse_buf;
}

Menj a Main .cpp-be!
A szokásos módon csatoljuk az új headert, és adjunk a proginkhoz egy új osztályt, ha még nem adtál volna az előző leckében (más billentyűkezelés miatt):

#include <windows.h>
#include <Rajz.hpp>
#include <Dx_input.hpp>
#include <Sprite.hpp>

//
//
//dekralációk

HINSTANCE hinstance;
RAJZ rajz;
INPUT input;
SPRITE sprite;

Az inicializálást most is végre kell hajtani:

    if(!rajz.init())MessageBox(NULL,"directdraw nem oké","",0);
    input.init_key();
    input.init_mouse();
    sprite.sp_init();
    while (fut)
    .......

És az üzenetkezelőben, ha az alkalmazásunk félre lesz téve, vagy előtérbe kerül akkor kell aktiválni, vagy elengedni az input eszközöket. Tehát:

    .........
    ........
    switch (message) /* vizsgáljuk az üzenet tipusát */
    {
        case WM_ACTIVATE: //ha az alkalmazás előtérbe került
            switch(wParam)
            {
                case WA_ACTIVE:
                case WA_CLICKACTIVE:
                    aktiv=true; //az más olytályok innen tudják,hogy az ablak aktív-e
                    if(input.bill) input.bill-> Acquire();//aktiváljuk a billentyűzetet ha létezik
                    if(input.mouse)input.mouse->Acquire();//egér ha létezik
                    break;
                case WA_INACTIVE:
                    aktiv=false;
                    if(input.bill) input.bill ->Unacquire();
                    if(input.mouse)input.mouse->Unacquire();
                    break;
            }
            break;

Menj a Sprite.hpp-be!

A DIMOUSESTATE* egy mutató ezt az adatot fogja szolgáltatni a függvény, mert így nem csak egy x vagy y elmozdulást vagy egy gomb lenyomását, hanem az összes adatot megkapjuk.
Abban az osztályban ahol használni akarjuk az INPUT osztályunkat, szükség van a DIMOUSESTATE struktúra dekralációjára is, tehát csatoni kell a Dinput.h headert is. A headerhez pedig "jár" egy előfordító utasítás:

#ifndef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x800
#endif
#include "dinput.h"

Kell még nekünk a Main .cpp-ben létrejött input osztály is:

extern INPUT input;

És egy új függvényt, ami a bábut mozgatja:

void babu_mozgat_m();

A megvalósítása:

void SPRITE::babu_mozgat_m()
{
    DIMOUSESTATE* adat;
    adat=input.get_mouse();
    if(adat->lX!=0) sp[0].SP_X+=adat->lX;
    if(adat->lY!=0) sp[0].SP_Y+=adat->lY;
    if(adat->lZ!=0) {sp[0].SP_X+=(int)adat->lZ/10;sp[0].SP_Y+=(int)adat->lZ/10;}//görgő
    //MOST NINCS KORLÁTOZVA A KÉPERNYŐ TERÜLETÉRE


}

Az egér használata meglehetősen egyszerű, hozzárendelsz egy sprite-ot, ezáltal lesz képe, animálható, stb. kirajzolhatod, vagy nem, ha kattintasz kezedben van az aktuális koordináta, "tudod" hol jár az egér a képernyőn csak programozás dolga, hogy mire használod!
Még bővítsd a frissít() függvényt.:

    .........
    if(sp_utk(0))rajz.kiirbetu("ÜTKÖZÉS TÖRTÉNT",10,10);//golyót vizsgáljuk
    DIMOUSESTATE* info1;
    info1=input.get_mouse();
    rajz.kiirszam(info1->lX,30,30);
    rajz.kiirszam(info1->lY,30,50);
    rajz.kiirszam(info1->lZ,30,70);
    rajz.kiirszam(info1->rgbButtons[0],30,90);
    rajz.kiirszam(info1->rgbButtons[1],30,110);
    rajz.kiirszam(info1->rgbButtons[2],30,130);

    rajz.flip();
    ........

fordít futtat.

itt a kód:

Foxi


Kapcsolódó linkek:

A cikksorozat további részei:

Értékelés: 5.50

Új hozzászólás
ktom88          2009.03.21 05:21
Ha Release()-t használsz eszközre előtte Unacquire()-t érdemes használni.

SetCooperationLevel()-nél bill van írva nem mouse.

inf ellenőrzésekre pedig ajánlom a FAILED() makró használatát.

Pl.: inf=mouse->SetDataFormat(&c_dfDIMouse);//egér forma az adat
if(inf !=DI_OK)return false;

Helyett:
if(FAILED(mouse->SetDataFormat(&c_dfDIMouse)))
{
return false;
}

Jó a cikk.
Dookle          2007.08.21 05:12


de pls már az első cikkben is a deklarációt dekralációnak írtad ami egy ilyen részletes cikk esetén elég ciki

amúgy
kiskami          2007.08.17 01:05
Nem olvastam az előző cikkeket, de van valami különleges oka, hogy protected-be raktad és nem private-ba a belső használatú adattagokat? Lesznek ennek az osztálynak leszármazottjai vagy barátai?
Látom a sprite is ilyen, miért jó ez?
Sedrien          2007.08.14 00:45
10/10