-
OnPlayerKeyStateChange
Ez az eljárás akkor hívódik meg, mikor a játékos lenyom vagy elenged egy \"speciális (Kivéve a Fel-Le, Jobbra-Balra)\" gombot. Ezeket a gombokat a GetPlayerKeys() segítségével tudjuk ellenõrizni.
Paraméterek:
( playerid, newkeys, oldkeys )
playerid - Annak a játékosnak az azonosítója, aki megnyomta a gombot.
newkeys - A változó, ami a játékos által lenyomott gombok bitjeit tárolja.
oldkeys - A változó, amit azokat a biteket tárolja, amit a mostani gomb lenyomás elõtt tárolt. (Ha lenyomom az X betût, aztán Y-t, akkor amikor az Y-t lenyomta, akkor az X lesz az old keys)
Visszatérés 1 - Megengedi az eljárásnak hogy meghívódjon a többi scriptben. Ez mindig meghívódik a játékmódban, tehát a 0 visszatérés csak a filterscripteket akadályozza.
Információ
Ez az eljárás akkor hívódik meg, amikor a játékos lenyom, vagy elenged egy speciális gombot. Csakhogy nem minden gomb tartozik ide, csak azok a gombok, amik használva vannak alapból a játékban. Például ha az \"A\" betût akarod ellenõrizni, akkor azt nem lehet vele, de viszont azt igen, amikor lenyomja a sprint gombot. Azt a gombot fogja sprint gombnak venni, ami a játékosnak be van állítva. Ha SPACE, akkor SPACE, ha H, akkor azt, stb..
Paraméterek
A paraméterek az összes gomb száma, amit elengedtél, vagy amit épp lenyomtál. Ez az eljárás akkor hívódik meg, amikor valamilyen gomb státusz megváltozik. (Tehát ha lenyomtál egy gombot és azt elengetted, vagy csak simán lenyomtál egy gombot). Az információ, amit a paraméterek visszaadnak, az nem úgy van, mint a többi átlagos eljárásnál. Egy paraméterben adja vissza több gomb adatait. Ezt bitmûveletek segítségével tudjuk ellenõrizni. Minden gombnak megvan a saját bitje, és megnézzük, hogy a bit igaz-e, vagy hamis-e. Ha igaz, akkor levan nyomva, ellentétben nincs.
Hogy NE ellenõrizd a gombot
Ha le akarod ellenõrizni, hogy valaki lenyomta a lövés gombot, akkor azt nyilván valóan így csinálnád:
[pawn]if (newkeys == KEY_FIRE)[/pawn]
A kód mûködin fog, csak nem úgy, ahogy annak kéne. Próbálj meg legugolni és lenyomni a lövés gombot - a kód már nem is mûködik. Miért is?
Mivel a newkeys nem egyenlõ a \"KEY_FIRE\"-vel, hanem \"KEY_FIRE\" kombinálva a \"KEY_CROUCH\"-al.
Hogy ellenõrizd a gombot
Most már tudjuk, hogy a változó két gomb adatait tartalmazza, ezért csak azt kéne megnézni, hogy az a gomb benne-e van, amit lenyomtunk. Erre a bit maszkolás a megoldás. Minden gombnak van saját bitje a változóban (Bár pár gombnak ugyanaz a bitje, de azok kocsiban vagy gyalog vannak. Szóval nemfog keveredni, mert nem kerülhetnek egyszerre bele a változóba.)
Jelenleg csak egy bitet kell megnéznünk:
[pawn]if (newkeys & KEY_FIRE)[/pawn]
Az egy darab \'&\'-jel az a bitenkénti ÉS és nempedig a logikai ÉS.
Ha leteszteled a kódot, akkor fog mûködni. Gugolás vagy futás közben, az lényegtelen, akkor fog menni, amikor le van nyomva a lövés gombod. Csakhogy ezzel van egy kis probléma: Ez a kód akkor fog mûködni, amikor le van nyomva a lövés gombod. Így jó is lenne, csakhogy mint elõbb leírtak miatt akkor is menni fog, ha a lövés gombod le van nyomva (Tartod az egéren a kezed) és közben te lenyomsz egy gombot. (Legugolsz, felállsz, sprintelsz, stb...)
Hogy ellenõrizd ha lenyomják a gombot
Itt jön használatba az \"oldkeys\" paraméter is. Elõször meg kell nézni, hogy a \"newkeys\"-ben benne-e van, és hogy NINCS-e az oldkeys-ben. Mivel ha benne lenne ott is, akkor valószínûleg eddig is levont neki nyomva és közben lenyomott egy másik gombot.
A következõ kód megoldja ezt:
[pawn]if ((newkeys & KEY_FIRE) && !(oldkeys & KEY_FIRE))[/pawn]
Ez csak akkor fog meghívódni, amikor a KEY_FIRE megtalálható a \"newkeys\"-ben és nem pedig akkor, amikor ez le van nyomva és közben más gombokat nyomkálsz.
Hogy ellenõrizd ha elengedik a gombot
Ugyanaz a megoldás, mint a fentiben, csak fordítva.
[pawn]if ((oldkeys & KEY_FIRE) && !(newkeys & KEY_FIRE))[/pawn]
Hogy ellenõrizz több gombot
Ha azt akarod ellenõrizni, hogy a játékos lenyomja a lövés és a gugolás gombot, akkor a következõ kód mûködni fog.
[pawn]if ((newkeys & KEY_FIRE) && (newkeys & KEY_CROUCH))[/pawn]
De ha azt akarod ellenõrizni, hogy elõször lenyomta a lövés gombot, aztán pedig a gugolást, akkor ez a kód NEM FOG mûködni! Csak akkor fog mûködni, ha EGYSZERRE nyomja le azt a két gombot. A következõ megoldás sem fog rendesen mûködni:
[pawn]if ((newkeys & KEY_FIRE) && !(oldkeys & KEY_FIRE) && (newkeys & KEY_CROUCH) && !(oldkeys & KEY_CROUCH))[/pawn]
Miért nem? Mivel az OnPlayerKeyStateChange minden egyes gomb lenyomásnál/elengedésnél hívódik meg. Tehát ha õ lenyomja a \"KEY_FIRE\"-t, akkor meghívódik az OnPlayerKeyStateChange a \"KEY_FIRE\"-vel a \"newkeys\"-ben és nem az \"oldkeys\"-ben. Ekkor ha lenyomja a \"KEY_CROUCH\"-ot, akkor OnPlayerKeyStateChange meghívódik a \"KEY_CROUCH\"-al és a \"KEY_FIRE\"-vel a \"newkeys\"-ben, de közben a \"KEY_FIRE\" benen van az \"oldkeys\"-ben. Tehát itt hülyeséget csinál ez a megoldás: \"!(oldkeys & KEY_FIRE)\". A megoldás nagyon egyszerû:
[pawn]if ((newkeys & (KEY_FIRE | KEY_CROUCH)) == (KEY_FIRE | KEY_CROUCH) && (oldkeys & (KEY_FIRE | KEY_CROUCH)) != (KEY_FIRE | KEY_CROUCH))[/pawn]
Ez a megoldás elsõ ránézésre nagyon komplikáltnak tûnik, pedig nem az. A kód azt csinálja, hogy ellenõrzi, hogy mind a két gomb benne-e van a \"newkeys\"-ben, de nincs-e az \"oldkeys\"-ben.
Egyszerûsítés
Gomb lenyomva tartása
Definíció:
[pawn]
// HOLDING(keys)
#define HOLDING(%0) \\
((newkeys & (%0)) == (%0))
[/pawn]
Egy gomb lenyomva tartása:
[pawn]if (HOLDING( KEY_FIRE ))[/pawn]
Több gomb lenyomva tartása:
[pawn]if (HOLDING( KEY_FIRE | KEY_CROUCH ))[/pawn]
Gomb lenyomása
Definíció:
// PRESSED(keys)
[pawn]#define PRESSED(%0) \\
(((newkeys & (%0)) == (%0)) && ((oldkeys & (%0)) != (%0)))[/pawn]
Egy gomb lenyomása:
[pawn]if (PRESSED( KEY_FIRE ))[/pawn]
Több gomb lenyomása:
[pawn]if (PRESSED( KEY_FIRE | KEY_CROUCH ))[/pawn]
Gomb elengedése
Definíció:
[pawn]// RELEASED(keys)
#define RELEASED(%0) \\
(((newkeys & (%0)) != (%0)) && ((oldkeys & (%0)) == (%0)))[/pawn]
Egy gomb elengedése:
[pawn]if (RELEASED( KEY_FIRE ))[/pawn]
Több gomb elengedése:
[pawn]if (RELEASED( KEY_FIRE | KEY_CROUCH ))[/pawn]
Példák
Nitró amikor lenyomja a lövés gombot
[pawn]
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if (PRESSED(KEY_FIRE))
{
if (IsPlayerInAnyVehicle(playerid))
{
AddVehicleComponent(GetPlayerVehicleID(playerid), 1010);
}
}
return 1;
}
[/pawn]
Szuper ugrás
[pawn]
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if (PRESSED(KEY_JUMP))
{
new
Float:x,
Float:y,
Float:z;
GetPlayerPos(playerid, x, y, z);
SetPlayerPos(playerid, x, y, z + 10.0);
}
return 1;
}
[/pawn]
Halhatatlanság amíg az ENTER gombot nyomja
[pawn]
new
Float:gPlayerHealth[MAX_PLAYERS];
#if !defined INFINITY
#define INFINITY (Float:0x7F800000)
#endif
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if (PRESSED(KEY_ACTION))
{
// They just pressed the action key, save their
// old health for restoration.
GetPlayerHealth(playerid, gPlayerHealth[playerid]);
SetPlayerHealth(playerid, INFINITY);
}
else if (RELEASED(KEY_ACTION))
{
// They just let go of action - restore
// their old health again.
SetPlayerHealth(playerid, gPlayerHealth[playerid]);
}
return 1;
}
[/pawn]
Magyarázat
Nem kell aggódnod, hogy ezek a dolgok hogyan mennek végbe, végbe mennek és kész. HOLDING (Tartás) érzékeli, ha a játékos tartja a gombot. Tehát addig megy a holding, amíg azt a gombot el nem engeded. PRESSED érzékeli, ha csak simán lenyomtad a gombot. RELEASED érzékeli, ha elengedted a gombot. Ajánlott tovább olvasni, itt jön a lényeg:
Bináris számrendszerben a KEY_SPRINT a következõ:
0b00001000
Tehát a 4. bit. Ha a 4. bit igaz, akkor benne van a KEY_SPRINT és ha ellenõrizni akarjuk, hogy benne-e van, akkor csak megkell nézni, hogy a KEY_SPRINT benne-e van.
(newkeys & KEY_SPRINT)
vagy
(neweys & (1 << 3))
0001 binárisan az egy, ha ezt eltoljuk 3-al balra, akkor a következõ lesz: 1000 (8), ez pedig a KEY_SPRINT (8). Szóval itt a fenti megoldás sokkal egyszerûbb és átláhatóbbb. Ezt csak példának írtam.
KEY_SPRINT:
0b00001000
A KEY_JUMP pedig:
0b00100000
Ezek után a bitenkénti VAGY lefut és \"egyberakja\" õket.
Jelen esetben ez lesz a kívánt érték, amiben lefutott a bitenkénti VAGY a két érték között.
0b00101000
Kapcsolódó eljárások
OnPlayerStateChange: Ez az eljárás akkor hívódik meg, mikor a játékos megváltoztatja az állapotát.
Kapcsolódó függvények
GetPlayerKeys: Lekérdezi, hogy a játékos milyen gombot nyomott meg.
Eredeti téma: http://wiki.sa-mp.com/wiki/OnPlayerKeyStateChange
-
szépen leírtad, engem ez a bit-es megoldás érdekelne, van róla tutorial? esetleg el tudnádmagyarázni?
pl hogy KEY_JUMP ból hogy lesz 0b00100000
-
A \"KEY_JUMP\" így néz ki az a_samp.inc-ben:
#define KEY_JUMP (32)
Tehát az a 32.
A 32 a bináris (kettes) számrendszerben így néz ki: 0b10000
Tizenhatos (hexadecimális) számrendszerben pedig így: 0x20
Olvass utána google-n, hogy számrendszerek, ezt nemfogom elmagyarázni az egészet az elejétõl.
A bites részét azt leírhatom, bár elég részletesen szerintem le van írva a leírásba.
Bitmûveletekrõl ittvan egy leírás, tervezem ezt is lefordítani: http://web.archive.org/web/20071118114428/http://forum.sa-mp.com/index.php?topic=8301.msg67577#msg67577
-

Tizenhatos (hexadecimális) számrendszerben pedig így: 0x20
hogy is van ez?
-
Nekem ez a lenyomva tartás nem igazán akar mûködni,sehogy sem.
Azt szeretném megoldani,hogyha a játékos lenyomva tartja az N gomobt,akkor elkezdjen felfele számolni egy változó.
Igazából az a gondom,hogy lenyomva tartom a gombot,hozzáad 1-t,de nem folytatódik tovább a folyamat.
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
new str[5];
if (HOLDING(KEY_NO))
{
if(GetTickCount()-blimit < 1000) return 1;//ha letelt 1 másodperc,csak akkor ad hozzá,ha nem,akkor vissaztér
blimit = GetTickCount();
count++;
format(str,5,\"%i\",count);
SendClientMessage(playerid,-1,str);
}
else if (RELEASED(KEY_NO))
{
count = 0;
SendClientMessage(playerid,-1,\"vége\");
}
return 1;
}
Any idea?
-
kadaradam, a kódod jól mûködik, csak az eljárás nem egészen így viselkedik. Ez akkor hívódik meg, amikor a játékos billentyûzet állapota megváltozik, na most ha én ráfekszem a gombra akkor ez nem fog változni, hanem állandósul. Próbáld meg azt, hogy a gomb lenyomása mellett még nyomogatod a szóközt. A számláló menni fog.
Ezt még az angol fórumon találtam, ezt használd:
new
bool:HoldingKey[MAX_PLAYERS];
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
if(newkeys & KEY && !HoldingKey[playerid])
{
KeyCheck(playerid);
HoldingKey[playerid] = true;
}
return 1;
}
forward KeyCheck(playerid);
public KeyCheck(playerid)
{
if(IsPlayerConnected(playerid))
{
new
keys, ud, lr;
GetPlayerKeys(playerid, keys, ud, lr);
if(keys & KEY)
{
// Player is holding the key if it gets here
SetTimerEx(\"KeyCheck\", 100, 0, \"i\", playerid);
return 0;
}
}
HoldingKey[playerid] = false;
return 0;
}
-
És tényleg..
Köszönöm. :D
-
Az ALT-nak mi a neve?
-
Nem valami Walk?
-
Az ALT-nak mi a neve?
-
Nem valami Walk?
-
Az ALT-nak mi a neve?
key_walk
-
Es hogy tudom le kerdezni egy jatekosnak a gombjait,azaz nem csak elore,hatra,jobbra,balra, hanem mikor nyomja meg a key_crouch,key_fire stb.
Az ujjabb scriptembe lenne ra szuksegem :P
Dupla hozzászólás automatikusan összefûzve. ( 2012. július 04. - 15:38:37 )
Van egy kis kod ami leirja a key ID jat ha lenyomod az adott gombot.Valaki le tudna irni?Koszonom:P
-
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
SendClientMessagef(playerid, COLOR_WHITE, \"Oldkeys: %d | %b Newkeys: %d | %b\", oldkeys, oldkeys, newkeys, newkeys);
}
-
Ja tenleg.Pffff.Kossz
Dupla hozzászólás automatikusan összefûzve. ( 2012. július 05. - 07:57:20 )
de most ezt akkor ugy kene hogy:
new string[50];
format(string,sizeof(string),\"Oldkeys: %d | %b Newkeys: %d | %b\", oldkeys, oldkeys, newkeys, newkeys);
SendClientMessage(playerid, COLOR_WHITE, string);
-
régen errõl tanultam meg ;D
Király, kezdõknek jól jön!