Koska lähden lomille täsäs pikkoin enkä ehdi/jaksa kasata suuren suurta ja kattavaa esittelyä enginelle, niin teen sen tässä muodossa... Eli tässäpä hyvin yksinkertainen peli, joka kääntyy DJGPP:llä. On pieni ja kompakti :)
Luolastossa siis mennään ilman mitään päämäärää, ja suuntiakin on neljä (ooh!), ja näppäimet ovat tunnettu wasd. Olioita on jonkin verran ja ovia voi availla kävelemällä päin.
Näppäimellä 'I' luodaan uusi kenttä, jossa on 5 satunnaista vastustajaa ja sankari. Tallennusta demotaan 'S'-näppäimestä' ja latausta 'L':stä.
Harjoituksen vuoksi saatte itse lisätä esineet kentälle ^^
Pelintynkä ei käänny juuri muualle kuin DOS:iin, johtuen kentänpiirrossa käytetystä gotoxy:stä. Ne voi kuitenkin korvata periaatteessa helposti vaikkapa ncurses:lla (vinkkejä löytyy...)
EDIT 9.4.2005 - vinkki laitettu kokonaan uusiksi
EDIT 18.10.2005 - päivitetty vinkki uudelle enginelle
EDIT 29.10.2005 - muutettu sankarin etsintä CretureHandleen.
Sisällytetään enginestä muutama osa-alue
#include "erkki.h" #include "creature.h" #include "item.h" #include "inven.h" #include "erkki_io.h" /* RAW_ITEMCLASS sisältää kaiken datan, jonka pääesine tarvitsee. Esinekohtaiset lisäykset (kunto, voimat yms) voidaan sisällyttää kentän esineluokkaan. */ struct RAW_ITEMCLASS aseet[] = { /* Nimi Vahinko Puol Hyok Suoj Teho Sisus Luokka Massa Hinta Data(4) */ {"Puukko", 1, 4, 0, 2, 0, 0, -1, 0, 10, 20, 0,0,0,0}, {"Miekka", 4, 8, 2, 4, 1, 0, -1, 1, 40, 90, 0,0,0,0}, }; /* Olioille sama asia. Asennuksen jälkeen olioita kyetään käyttämään indeksin kautta, joka määräytyy asennusjärjestyksen mukaan. */ struct CREATUREPALETTE oliot[] = { /* Nimi Elo,Mana Melee Suojaus Voima Range Data(4) Liput */ {"orc", 10, 0, 4,5, 2, 3, 5, 0,0,0,0, 0}, {"big orc", 20, 0, 8,10, 4, 7, 5, 0,0,0,0, 0}, }; /* Sankari */ struct CREATUREPALETTE sankari[] = { /* Nimi Elo,Mana Melee Suojaus Voima Range Data(4) Liput */ {"da hero", 10, 10, 3,10, 2, 2, 5, 0,0,0,0, 0}, }; /* Sankari saa arvon 0, jos se asennetaan ensimmäisenä */ #define HERO 0 /* Objektit. Perustavaa laatua olevan kosketus/potkintatapahtuman voi koodata data-muuttujaan (WhenKick/WhenTouch-makrot) Objektien vakiot ovat erkki.h:ssa. */ struct OBJECTCLASS objektit[] = { /* Tyyppi Data Ansa Potku Kosketus Extradata Vahinko */ {ObjectClassWall, 0, -1, 0,0, 0,0, 0, 0}, /* Avattava ovi. Muutetaan kosketettaessa 2:ksi (avattu ovi) */ {ObjectClassDoor, WhenTouch(TouchChng), -1, 0,0, 2,0, 0, 0}, /* Avattu ovi. Muutetaan kosketettaessa 1:ksi eli suljetuksi. */ {ObjectClassDoor, ObjOpen|WhenTouch(TouchChng), -1, 0,0, 1,0, 0, 0}, }; /* Ja vielä vakioina */ #define muuri_ 0 #define ovi_k_ 1 #define ovi_a_ 2 /* Funktioiden esittely */ void peli(); void hae_sijainti(int *, int *); void iske_oliota(int, int); /* Käytettävä kenttä */ FIELD * fld; /* Kentän koko */ #define MAXX 40 #define MAXY 20 int main(void){ /* Alustetaan engine */ ERKKI_init(ERKKI_DYNAMIC); /* Luodaan kenttärakenne. Parametrit: leveys, korkeus, max. oliot, max. esineet, kenttäolioiden max. datamäärä, olioiden varustuksen esineslotit (kpl), osoitin olioiden varustefiltteriin. */ fld = ERKKI_FIELD(MAXX, MAXY, 20, 20, 2, 0, NULL); /* Asennetaan esineet... */ ERKKI_install_items_static(ItemClass_Weapon, aseet); /* Ja oliot. Asennuksen mukaan: sankari saa arvon 0, orc 1 ja big orc 2. */ ERKKI_install_creature_static(sankari); ERKKI_install_creature_static(oliot); /* Ja lopuksi objektit */ ERKKI_install_objects(objektit); /* Näyttö tyhjäksi */ clrscr(); /* Alustetaan 'random' */ srand(time(0)); /* Pelaamaan */ peli(); /* Siivotaan roskat */ ERKKI_FIELD_free(fld); ERKKI_exit(); return 0; } void peli(){ /* Muuttujia */ signed char fll[MAXX+2] = {0}, xx, yy; /* uhandle: kahva siihen olioon, johon sankari on linkitetty */ int r, uhandle = -1; /* Esineen lisäystä varten */ ITEMSCLASS ii; CREATURESTACK * crr; FILE * ff; signed int kk, x, y; /* Esineen alustus */ ii.main_class = 0; ii.link = 0; /* Alustetaan piirtosysteemi */ fll[MAXX] = '\n'; fll[MAXX+1] = '\0'; /* Initoi kenttä */ ERKKI_init_map(fld, 0); while(1){ /* Piirretään kenttä rumasti */ gotoxy(1,1); for(yy = 0; yy < 20; yy++){ for(xx = 0; xx < 40; xx++){ if((r=ERKKI_getcreature(fld, xx, yy)) >= 0){ crr = ERKKI_creature(fld, r); if(crr->crt_type == HERO)fll[xx] = '@'; else fll[xx] = crr->crt_type-1+'1'; }else if((r=ERKKI_getitem(fld, xx, yy)) >= 0){ if(ERKKI_item(fld, r)->ItemNum >= 0)fll[xx] = 'h'; else fll[xx] = 'i'; }else if((r=ERKKI_getobject(fld, xx, yy)) >= 0){ if(r==muuri_)fll[xx] = '#'; else if(r==ovi_a_)fll[xx] = 'ï'; else fll[xx] = '+'; }else fll[xx] = '.'; } printf(fll); } /* debug-infoa: esineiden ja olioiden lukumäärä */ gotoxy(41, 1); printf("%3i::%3i", CountItems(fld), ERKKI_CountCreatures(fld)); /* Piirretty */ kk = getch(); /* Lopeta */ if(kk == 27){break; /* Tallenna nykyinen kenttä */ }else if(kk == 'S'){ ff = fopen("testi.mpp", "wb"); if(ff){ ERKKI_FIELD_save_full(fld, ff); fclose(ff); } /* Lataa tallennettu kenttä */ }else if(kk == 'L'){ ERKKI_KENTTA_free(fld); ff = fopen("testi.mpp", "rb"); if(ff){ fld = ERKKI_FIELD_load_full(ff); uhandle = CreatureHandle(fld, HERO); fclose(ff); } /* Tee uusi kenttä */ }else if(kk == 'I'){ ERKKI_init_map(fld, 0); /* Luolaston muureina käytetään objekti <muuri_> eli 0 Lattia piirretään tunneleihin 0:lla, tunnelit 1:llä */ ERKKI_create_dungeon(fld, muuri_, 0, 1); /* Asetetaan ovet (kaikkialle, missä on maalaatujen 1 ja 0 raja) */ ERKKI_putdoors(fld, ovi_k_); /* Asetetaan oliot. Sankari ensin... */ hae_sijainti(&x, &y); PutCreatureToMap(fld, HERO, x, y); uhandle = CreatureHandle(kentta, HERO); /* Ja sitten muutama örkinmukula */ for(yy=0;yy<5;yy++){ hae_sijainti(&x, &y); PutCreatureToMap(fld, 1+rand()%2, x, y); } }else{ /* Liikkumiskoodi */ xx = 0; yy = 0; /* Sankarin sijainti */ CreaturePos(fld, uhandle, (Sint16*)&x, (Sint16*)&y); switch(kk){ case 'w': yy = -1; break; case 's': yy = 1; break; case 'a': xx = -1; break; case 'd': xx = 1; break; }; gotoxy(1, MAXY+1); /* Viestejä varten */ switch(MoveCreature(fld, uhandle, xx, yy)){ case ERKKI_OK: printf("%40s", ""); break; /* Törmäiltiin sitten ovia päin. Periaatteessa vain suljettu ovi luetaan esteeksi. */ case Block_Door: /* Objekti talteen */ r = ERKKI_getobject(fld, x+xx, y+yy); /* Yritetään avata se */ xx = ERKKI_HandleMap(fld, uhandle, x+xx, y+yy, StTouch); if(r==ovi_k_){ printf("%40s", "You open the door."); }else{ printf("%40s", "- unexpected harmless error -"); } break; case Block_Creature: r = ERKKI_getcreature(fld, x+xx, y+yy); xx = CreatureData(fld, r, GET_C_WHO, 0, SUB_CREATURE); iske_oliota(uhandle, r); printf("You damaged the %s (%i)!", CreatureNameBasic(xx), r); break; }; } } } /* Hakee sattumanvaraisen, vapaan sijainnin. */ void hae_sijainti(int * x, int * y){ do{ *x=rand()%MAXX; *y=rand()%MAXY; /* este_olio: mikäli sijainnissa olio, se on este. Muut liput on määritelty erkki.h:ssa */ }while(ERKKI_isblocked(fld, *x, *y, Blocked_Crt)); } /* Alkeellinen iskusysteemi. Taistellaan pelkillä meleevahingoilla. Esineet saa mukaan kehiin käyttämällä funktiota BasicItemLink, joka löytyy creature.c:stä. */ void iske_oliota(int iskija, int kohde){ int v1, v2, lama, kuka, kuka2; /* Ensin haetaan olioiden pääolioluokat */ kuka = CreatureData(fld, iskija, GET_C_WHO, 0, SUB_CREATURE); kuka2 = CreatureData(fld, kohde, GET_C_WHO, 0, SUB_CREATURE); /* Haetaan iskijän vahinko */ v1 = CreatureData(fld, kuka, GET_C_MIND, 0, MAIN_CREATURE); v2 = CreatureData(fld, kuka, GET_C_MAXD, 0, MAIN_CREATURE); lama = rand()%(v2-v1+1) + v1; /* Vähennetään suojausarvo */ lama -= CreatureData(fld, kuka2, GET_C_DEF, 0, MAIN_CREATURE); /* Ettei paranneta */ if(lama<0)lama=0; /* Vahingoita oliota. Mikäli kuoli, palauttaa ERKKI_KILLED. */ DamageCreature(fld, kohde, lama); }
Joo kyllä se jotenkin toimii.
Muuten aivan hyvä, mutta valittaa tälläistä:
"Compiling...
Roolipeli.cpp
c:\program files\microsoft visual studio\myprojects\roolipeli\erkki_d.h(20) : fatal error C1083: Cannot open include file: 'pc.h': No such file or directory
Error executing cl.exe."
Tuo johtuu siitä, että ERKKId on Dos-pohjainen sivukirjasto. Se ei mielellään käänny Windows-ympäristössä :)
Aion väsätä kesän mittaan win-pohjaisen sivukirjaston esineiden poimintaan ym. (pienillä ikkunoilla siis), mutta sen voi jo nyt tehdä kuka hyvänsä. Mallia esineiden listaamiseen kentältä ja poimintaan voi katsoa erkkid:stä.
Mistä saa nuo erkki_d.h ja erkki_m.h? Ei löydy ainakaan enginestä 0.8.5
Ne ovat sivukirjastoja, joita ei enää/vielä ole ladattavissa. Esimerkki toimii ilman niitäkin, jolloin esineisiin tulee pieniä muutoksia (WClass...:t korvataan vaikkapa 0:lla ja funktio ERKKId_PickUp() perusfunktiolla PickUpItem(field, x, y, 0, inventory) (poimitaan alin esine)).
Mainitsit projektisivulla, että tämä toimii enginen versioiden 7x kanssa. Miksi et joko päivitä tätä, tai laita linkkiä tähän enginen versioon?
Korjasin vinkin toimimaan ladattavalla versiolla 0.8.6.
Onpas paljon kommentteja joka on tietysti plussaa.
Kiitoksia ^^
Ei hemmetti miten osaatte kirjoittaa tota koodii!
Mut miksi teillä ei synny semmoista Max Paynen tapaisia pelejä`?
:D
...lähinnä siksi että joko a) (ainakaan minä) emme osaa vielä 3d-ohjelmointia ja/tai b) resurssit eivät riitä.
Luultavasti b, vaikka osaisikin 3d-ohjelmointia, se on niin laaja alue, että ei resurssit riitä.
Olis kiva saada esimerkki los:n käytöstä.
LOS-funktioiden käytössä ei tarvitse kuin lisätä seuraavat käskyt:
/* Peittää koko näkyvyyden kaikkialta */ ERKKI_unsee_area(fld); ... /* Sytyttää 'näköpisteen' kohtaan x,y. Näkö kantaa matkan <sade> päähän ja muuttaa valon tehokkuutta; pisteessä [x,y] on valoteho <teho> ja muissa sen ympärillä <teho>-1, <teho>-2 jne. */ ERKKI_see_area(fld, x, y, sade, teho); ... /* Kentän piirtämisessä voi sitten tutkia tilen näkyvyyttä kentänpalan data-muuttujasta: */ if(ERKKI_isexposed(fld, x, y))printf("Kohta %i,%i on näkyvissä.", x, y); valo = ERKKI_isvisible(fld, x, y); if(valo>0)printf("Kohta %i,%i on valaistu teholla %i.", x, y, valo);
no just... mä en saa tota koodii kääntymään nii millää!
ekaks se valittaa jostai 'no new line at end of erkki.h'
mä en tajuu miks Dev-Cpp ei suostu kääntää sitä ideoita?
Tuo on vain varoitus siitä, että ko. tiedoston lopussa ei ole ylimääräistä rivinvaihtoa; sillä ei pitäisi olla mitään suurempaa merkitystä kääntämisen kanssa.
Mitäs muuta Dev-C valittaa?
Aihe on jo aika vanha, joten et voi enää vastata siihen.