Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: C: ERKKI-enginellä pelin alku

Sivun loppuun

sqwiik [21.06.2004 21:41:33]

#

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);
}

tgunner [22.06.2004 12:32:10]

#

Joo kyllä se jotenkin toimii.

Happi [29.06.2004 23:30:19]

#

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."

sqwiik [06.07.2004 11:26:12]

#

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ä.

ville-v [09.02.2005 08:55:20]

#

Mistä saa nuo erkki_d.h ja erkki_m.h? Ei löydy ainakaan enginestä 0.8.5

sqwiik [13.02.2005 21:55:17]

#

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)).

ville-v [02.04.2005 12:02:10]

#

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?

sqwiik [09.04.2005 21:19:41]

#

Korjasin vinkin toimimaan ladattavalla versiolla 0.8.6.

FastSnail [30.09.2005 18:54:10]

#

Onpas paljon kommentteja joka on tietysti plussaa.

sqwiik [18.10.2005 08:40:22]

#

Kiitoksia ^^

Nitros [24.10.2005 17:45:43]

#

Ei hemmetti miten osaatte kirjoittaa tota koodii!
Mut miksi teillä ei synny semmoista Max Paynen tapaisia pelejä`?
:D

sqwiik [24.10.2005 18:09:54]

#

...lähinnä siksi että joko a) (ainakaan minä) emme osaa vielä 3d-ohjelmointia ja/tai b) resurssit eivät riitä.

ZcMander [06.06.2006 13:18:11]

#

Luultavasti b, vaikka osaisikin 3d-ohjelmointia, se on niin laaja alue, että ei resurssit riitä.

Olis kiva saada esimerkki los:n käytöstä.

sqwiik [16.07.2006 19:22:40]

#

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);

ZAND825 [20.05.2007 11:22:22]

#

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?

sqwiik [29.05.2007 23:09:34]

#

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?


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta