Peršokti į turinį
  • ŽAIDIMAI
  • , ŽAIDIMAI
  • ŽAIDIMAI

Timers


bebras

Ši tema yra neaktyvi. Paskutinis pranešimas šioje temoje buvo prieš 3839 dienas (-ų). Patariame sukurti naują temą, o ne rašyti naują pranešimą.

Už neaktyvių temų prikėlimą galite sulaukti įspėjimo ir pranešimo pašalinimo!

Recommended Posts

Sveiki, nepridėjau [Pamoka] nes čia nemokysiu kažkokio konkretaus dalyko. Tiesiog norėjau sukurti temą kurioje galėtume aptarti timerius, juk tiek daug apie juos ir jų greiti kalbama...

Ką vadiname timeriu pawn? Tai funkcija kuri bus iškviesta už nurodyto laiko.

Timeriai yra "kuriami" su dviem funkcijom: SetTimer, įprastas timer, bei SetTimerEx, timeris su papildomais parametrais.

Daugybę žmonių (neapsiriboju šiuo forumu ar Lietuva) teigia kad timeriai "lagina" serverį. Žinoma niekam niekada netrukdė vienas timeris. Bet kaip dauguma matėtė, GRP, vien įjungus serverį paleidžiami 5-6timeriai, jau nekalbu apie dar bent 2 asmeninius timerius...

Tai tikrai didelė problema, ypač kai tie timeriai kartojasi vienodu metu (pvz du timeriai kas 1min), kam to reikia? Skaičiau kažkur kaip Y_Less trumpai apibūdino timerių veikimą (dabar nerandu..), esmė kad kažkuriuo metu, žaidėjas nėra sinchronizavęsis su serveriu. Ką tai reiškia? Tai reiškia kad žaidėjas yra "atsijungęs" nuo serverio ir "sugrįš" tik tada kai timeris baigs tvarkyt reikalus.

Štai panašus pavizdys kurį pats mačiau:


SetTimer("Timer1",1000,true);
SetTimer("Timer2",1000,true);

forward Timer1();
public Timer1()
{
//kažkas vyksta
}
forward Timer2();
public Timer2()
{
///Vel kažkas vyksta
}

Kai kas galvoja: aha, du timeriai tuo pačiu metu, reiškia 2 skirtingi kodo blokai bus vykdomi vienu metu! Tikrai ne, apskritai sa-mp serveris veikia ant vieno thread of execution (dėja nežinau Lietuviško žodžių atitikmens). Ir vėl, ką tai reiškia? Tai kad niekada 2 kodo blokai nebus vykdomi vienu metu. T.y. bus nuspręsta(o tai sprendžiasi giliai kompiuteryje,berods) kuris eis pirmas, o kitas lauks. Čia įterpsiu smulkmena apie MySQL, jeigu neklystu(esu beveik tikras kad neklystu), naujosios mysql versijos veikia ant atskiro thread of execution, bet aišku čia kita tema.

Taipat, labai didelės funkcijos timeryje "lagins" žaidėjui. Kadangi kaip minėjau, kol timerio funkcija nebus baigta, žaidėjas nesinchronizuosis su serveriu.

Ir dar ne viskas apie timerius! Pasirod yra dar vienas didelis trūkumas... jie yra labai netikslūs! Yra daug kur testų rezultatų, bet aš atlikau savo. Štai testavimo kodas:


new MinTick,SecTick;
forward Minute();
forward Sekunde();
public OnGameModeInit()
{
mysql_debug(1);
SetTimer("Minute",60000,true);
MinTick = GetTickCount();
SetTimer("Sekunde",1000,true);
SecTick = GetTickCount();
return 1;
}

public Minute()
{
printf("Minutes timeris buvo iskviestas po %d MS",GetTickCount() - MinTick);
return 1;
}
public Sekunde()
{
printf("Sekundes timeris buvo iskviestas po %d MS",GetTickCount() - SecTick);
return 1;
}

Ir štai vienos sekundės timerio rezultatai:


[19:19:52] Sekundes timeris buvo iskviestas po 1075 MS
[19:19:53] Sekundes timeris buvo iskviestas po 2200 MS
[19:19:54] Sekundes timeris buvo iskviestas po 3315 MS
[19:19:56] Sekundes timeris buvo iskviestas po 4430 MS
[19:19:57] Sekundes timeris buvo iskviestas po 5550 MS
[19:19:58] Sekundes timeris buvo iskviestas po 6660 MS
[19:19:59] Sekundes timeris buvo iskviestas po 7770 MS
[19:20:00] Sekundes timeris buvo iskviestas po 8886 MS

Pagal idėja turėjome pamatyti lygius skaičius, 1000,2000,3000 ir t.t. Jau po pačio pirmojo iškvietimo paklaida yra 75MS. Tai gal ir neatrodo daug... Bet pažiūrėkime kas darosi toliau? Paklaidos susidės...ir timeris per 60 sekundžių bus iškviestas ne 60 kartų.

Minutinio timerio rezultatai:


[19:20:58] Minutes timeris buvo iskviestas po 66574 MS
[19:22:04] Minutes timeris buvo iskviestas po 132610 MS

Išvis kažkas "lempinio", ar ne?

Kai kurie turbūt jau galvoja kad viskas, pasaulio pabaiga...nenaudosiu niekada timerių, bet visada yra tas "bet". Yra išleistas "timerfix" include. Oficiali jo tema. (Ir ten rasite atliktų testų).

Sekundinio timerio testas atliktas su timerfix.inc:


[19:24:54] Sekundes timeris buvo iskviestas po 1004 MS
[19:24:55] Sekundes timeris buvo iskviestas po 2004 MS
[19:24:56] Sekundes timeris buvo iskviestas po 3004 MS
[19:24:57] Sekundes timeris buvo iskviestas po 4004 MS
[19:24:58] Sekundes timeris buvo iskviestas po 5004 MS
[19:24:59] Sekundes timeris buvo iskviestas po 6004 MS
[19:25:00] Sekundes timeris buvo iskviestas po 7004 MS
[19:25:01] Sekundes timeris buvo iskviestas po 8004 MS
[19:25:02] Sekundes timeris buvo iskviestas po 9004 MS

Paklaida nedidesnė nei 4MS, kas jau yra niekis.

Minutinio timerio rezultatai su timerfix:


[19:25:53] Minutes timeris buvo iskviestas po 60007 MS
[19:26:54] Minutes timeris buvo iskviestas po 120541 MS

Tai tiek. Komentuokit, reiškit nuomonę, taisykit mane jei radote netikslumų :)

Redaguota , nario sneroq
  • Teigiamai 6
Nuoroda į komentarą
Dalintis per kitą puslapį

Tai va, jeigu aš turiu XP timeri kas 1 minute ir stažas? Kas tada? nes timerius paleidžiu ant OnGamemodInt abudu tik įsijungus serverį. Gal reiktu perkelt ant to kai įlipa į mašiną ;o tačiau, tai jeigu 2 timeriai 1 metu, tai vienas atsiliks?

Ne, 2 timeriai dar ne košmaras. Iš tikrųjų du tai niekis. Šiaip jei vienas yra labai trumpas, gali sumest į vieną. Ir šiaip dar vienas dalykas kurį kartais naudoju, toki dalyką:



OnGameModeInit()
{
 SetTimer("AntiHack",30*1000,true)
 SetTimer("XP",60*1000,true);
 return 1;
}
forward AntiHack();
public AntiHack()
{
   //anti hackas.
}
forward XP();
public XP()
{
/// XP augimas ar kazkas
}

Padarau tokiu

new antihacktoxp;
OnGameModeInit()
{
 SetTimer("XP",60*1000,true);
 return 1;
}
forward XP();
public XP()
{
antihacktoxp++;
/// XP augimas ar kazkas
If (antihacktoxp%2==0)
{
//antihackas
}
}

Nuoroda į komentarą
Dalintis per kitą puslapį

  • Parašė po 4 mėnesių...

Man kylo porą klausymų, žiurėk Bebrai. Tarkim noriu padariti tokia funkcija, kai kai paspaudi ENTER arba parašai komandą, tarkim po 10 sekundžių atsitinka kaškoks veiksmas, kaip reikia užrašyti kodą pawne, tarkim CMD: test (player;) ir t.t.t

(

Sendclientmessage tarkim: Lipi laiptais, tai užtruks kaškurį laiką. { IR dabar kokia man funkcija dėti, kad praeijus 10 sekundžių, pasikeistu žaidėjo pozicija, arba įviktu kaškoks veiksmas ?

Nuoroda į komentarą
Dalintis per kitą puslapį

//Užlipa ant pirmo laipto
SendClientMessage(playerid,-1,"Lipi laiptais, tai užtruks 1 minutę");
SetTimerEx("LipimasLaiptais",60000,false,"i",playerid);

//Timerio funkcija
forward LipimasLaiptais(playerid);
public LipimasLaiptais(playerid)
{
   SetPlayerPos(playerid,//Viršus laiptų.
   SendClientMessage(playerid,-1,"Sveikinu, užlipai laiptais ir užtrukai tik minutę!!!");
   return 1;
}

  • Teigiamai 1
Nuoroda į komentarą
Dalintis per kitą puslapį

Ši tema yra neaktyvi. Paskutinis pranešimas šioje temoje buvo prieš 3839 dienas (-ų). Patariame sukurti naują temą, o ne rašyti naują pranešimą.

Už neaktyvių temų prikėlimą galite sulaukti įspėjimo ir pranešimo pašalinimo!

Svečias
Ši tema yra užrakinta.
  • Šiame puslapyje naršo:   0 nariai

    • Nėra registruotų narių peržiūrinčių šį forumą.

Skelbimai


×
×
  • Sukurti naują...