No niin, tuolla VB-puolella onkin jo tästä enemmän selostettu versio. Kun siirsin ko. koodin C-maailmaan, koodi koki muutamilta osin suuria muutoksia koska:
* SDL:ssä ei ole suoraan viiva/piste-funktioita
* Piirtorajapintoja ei saakaan yhtä helposti kuin VB:ssä
* Yms. yms. ...
Eli: viivanpiirtorutiini täytyi tehdä itse, mikä tuli tämän kanssa tutuksi piirtorajapinnan lukitsemisen kanssa; samoin tuli miettiä miten suorittaa ruudun päivitys syötteen lukemisen lomassa.
VB:hen parannuksena mukaan tuli hyvin, hyvin yksinkertainen oliosysteemi monine bugeineen. Tässä versiossa siis lahdataan mömmöjä luolastossa; grafiikat löytyvät suoritettavan EXE:n kanssa (jossa mukana jopa musiikki; poistettu tästä versiosta - erillisenä vinkkinä C-osiolla) tämän linkin takaa.
Ja sitten itse koodiin. Pitkälti tämä tosin on miltei samaa VB-version kanssa, paitsi olio-osuus. Sankarin ei tarvitse olla kuin yksi kuva; Sen sijaan kaikki muut viholliset tarvitsevat Syvyys-muuttujan verran kuvia eri kokoisina, koko muuttuen syvyyden neliön käänteisenä (puolet, neljännes, kahdeksannes...). Tämän huomaa paketissa olevasta kuvasta.
Edit 20.4.2007: Tapettu pari tpyota.
#include <SDL/SDL.h> static char * Caption = "LUOLA by Sqwiik"; #define MaxX 16 #define MaxY 16 #define Syvyys 4 #define YlaSeina 1 #define AlaSeina 4 #define OikeaSeina 2 #define VasenSeina 8 /* Värejä... */ #define MAX_COL 4 # define COL_SEINA 0 # define COL_VSEINA 1 # define COL_LATTIA 2 # define COL_R1 3 #define MAX_R_COL 4 #define MAXOLIO 50 void TeeKentta(); void DoExit(void); Sint16 DoStart(); void Pelaa(); void Piirra3D(SDL_Surface*); void Liiku(Sint16, Sint16); void Kaanny(Sint16); void Hyokkaa(Sint16, Sint16); void TaytaVert(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Sint16, Uint32); void AI(); /* Tämän kaikkeuden typerin AI */ /* Piirtopinnat */ SDL_Surface * screen = NULL, * alue = NULL, * CrGraph[2] = {NULL}; /* Eri piirtojärjestykset */ typedef struct{ Sint16 j[4]; }JARJ; /* Hohoo, olio o__o */ typedef struct{ Sint16 gr; /* Grafiikka (CrGraph-taulukko) */ Sint16 x, y, hipat; }OLIO; /* Kenttä + 'pelin' oliot */ Sint16 Kentta[MaxX][MaxY]; OLIO Oliot[MAXOLIO]; /* KAIKKI eri piirtojärjestykset */ JARJ PiirJar[8] = { /* Vasemmalla */ {YlaSeina, VasenSeina, OikeaSeina, AlaSeina}, {OikeaSeina, YlaSeina, AlaSeina, VasenSeina}, {AlaSeina, OikeaSeina, VasenSeina, YlaSeina}, {VasenSeina, AlaSeina, YlaSeina, OikeaSeina}, /* Oikealla (peilikuva) */ {YlaSeina, OikeaSeina, VasenSeina, AlaSeina}, {OikeaSeina, AlaSeina, YlaSeina, VasenSeina}, {AlaSeina, VasenSeina, OikeaSeina, YlaSeina}, {VasenSeina, YlaSeina, AlaSeina, OikeaSeina}, }; /* Värejä - 4 erilaista hauskan pintakuvion aikaansaamiseksi */ Uint32 Varit[MAX_COL][MAX_R_COL]; /* Tarpeellisia muuttujia - syvyyden neliöt, sankarin sijainti ja katselusuunta */ Sint16 Maara[Syvyys] = {1, 2, 4, 8}, HX, HY, Suunta; /* Tyhjän ruutun luonti ENDIAN:n mukaan */ SDL_Surface *CreateSurface(Sint16 w, Sint16 h, Sint16 bpp) { /* Maskit */ Uint32 r, g, b, a; #if SDL_BYTEORDER == SDL_BIG_ENDIAN r=0xff000000; g=0x00ff0000; b=0x0000ff00; a=0x000000ff; #else r=0x000000ff; g=0x0000ff00; b=0x00ff0000; a=0xff000000; #endif return SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, r, g, b, a); } /* Rujoa grafiikkaa! Kärsikää! Täyttää nelikulmion (palikan seinä) tietyllä värillä. Väreistä käytetään seinää, koska tällä ei piirretä kuin seiniä. Katto/lattia vaatisi oman funktion, mutten jaksanut tehdä. */ void TaytaVert(SDL_Surface * s, Sint16 x1, Sint16 x2, Sint16 y1, Sint16 y2, Sint16 h1, Uint32 col){ double ym; Sint16 x, xm, w, yy, yym; /* Esilaskenta */ ym = (double)(abs(y2 - y1)) / (double)(x2 - x1); xm = ((x2 < x1)?(-1):(1)); w = (x2 - x1) + xm; /* Lukitus */ if(SDL_MUSTLOCK(s)) { if(SDL_LockSurface(s) < 0) { fprintf(stderr, "Ruudun lukitus ei onnistu: %s\n", SDL_GetError()); return; } } /* Rumuus piirroksi. Piirretään siis säännöllinen nelikulmio (seinä). */ for(x = 0; x != w; x += xm){ yym = y1 + h1 + (Sint16)(x * ym); if(x + x1 < 0 || x + x1 > s->w); else for(yy = y1 - (Sint16)(x * ym); yy <= yym; yy++){ if(yy < 0 || yy >= s->h); else *(Uint32 *)((Uint8 *)s->pixels + (yy * s->pitch) + ((x + x1)<<2)) = Varit[COL_SEINA][rand()%4]; } } if(SDL_MUSTLOCK(s))SDL_UnlockSurface(s); } /* Täyttää nelikulmion. */ void TaytaBox(SDL_Surface * s, SDL_Rect * r){ Sint16 x, y; if(SDL_MUSTLOCK(s)) { if(SDL_LockSurface(s) < 0) { fprintf(stderr, "Ruudun lukitus ei onnistu: %s\n", SDL_GetError()); return; } } for(y = r->y; y < r->y + r->h; y++){ for(x = r->x; x < r->x + r->w; x++){ if(x < 0 || x >= s->w || y < 0 || y >= s->h); else *(Uint32 *)((Uint8 *)s->pixels + (y * s->pitch) + (x<<2)) = Varit[COL_SEINA][rand()%4]; } } if(SDL_MUSTLOCK(s))SDL_UnlockSurface(s); } /* Taitaa olla lyhin main-funktioni >_> */ int main(int argc, char ** args){ if(DoStart())return -1; Pelaa(); exit(0); } /* Alustuksia */ Sint16 DoStart(){ Sint16 a, b; if(SDL_Init(SDL_INIT_VIDEO) < 0){ printf("Moka SDL:n alustuksess (%s)!\n", SDL_GetError()); return -1; } /* Automaatio muistin vapauttamiseksi */ atexit(DoExit); SDL_WM_SetCaption(Caption, NULL); screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF); if(!screen){ printf("Ei muistia ruudulle!\n"); return -1; } alue = CreateSurface(320, 320, 32); if(!alue){ printf("Ei muistia puskurille!\n"); return -1; } /* Oliografiikat */ CrGraph[0] = SDL_LoadBMP("hahmo.bmp"); if(!CrGraph[0])return -1; SDL_SetColorKey(CrGraph[0], SDL_SRCCOLORKEY, SDL_MapRGB(CrGraph[0]->format, 0, 0, 0)); CrGraph[1] = SDL_LoadBMP("vihu.bmp"); if(!CrGraph[1])return -1; SDL_SetColorKey(CrGraph[1], SDL_SRCCOLORKEY, SDL_MapRGB(CrGraph[1]->format, 0, 0, 0)); /* Alusta värit... seinä on kauniin sininen. Harmaalla saisi synkkyyttä. */ Varit[COL_SEINA][0] = SDL_MapRGB(alue->format, 0, 0, 255); Varit[COL_SEINA][1] = SDL_MapRGB(alue->format, 0, 0, 128 + rand()%128); Varit[COL_SEINA][2] = SDL_MapRGB(alue->format, 0, 0, 64 + rand()%196); Varit[COL_SEINA][3] = SDL_MapRGB(alue->format, 0, 0, rand()%255); return 0; } void DoExit(){ Sint16 a; if(screen)SDL_FreeSurface(screen); if(alue)SDL_FreeSurface(alue); if(CrGraph[0])SDL_FreeSurface(CrGraph[0]); if(CrGraph[1])SDL_FreeSurface(CrGraph[1]); SDL_Quit(); } /* Itse pelaaminen kontrolleineen */ void Pelaa(){ Uint8 paalla = 1, update = 1, turn = 0; Uint16 a; /* Pari ennalta laskettua väriä. */ Uint32 black = SDL_MapRGB(alue->format, 0, 0, 0), puna = SDL_MapRGB(alue->format, 255, 0, 0); SDL_Event e; /* Kestopistepalkkia varten */ SDL_Rect hipa = {0, 0, 40, 20}; TeeKentta(); /* Kenttä... */ while(paalla){ /* Jos siirto on tehty, niin A.I.:n vuoro. */ if(turn){ AI(); turn = 0; update = 1; } /* Grafiikka päivitetään vain ja vain jos on pakko. */ if(update){ SDL_FillRect(alue, NULL, black); /* Tyhjäys */ Piirra3D(alue); /* Piirtous */ /* Hipat */ hipa.x = (alue->w /2) - ((Oliot[0].hipat * (hipa.w + 20)) >> 1); for(a = 0; a < Oliot[0].hipat; a++, hipa.x += 60){ SDL_FillRect(alue, &hipa, puna); } /* Piirretyn alueen siirto screen:lle & flippaus */ SDL_BlitSurface(alue, NULL, screen, NULL); SDL_Flip(screen); update = 0; } /* Tapahtumahorisontti */ while(SDL_PollEvent(&e)){ switch(e.type){ case SDL_QUIT: paalla = 0; break; case SDL_KEYDOWN: switch(e.key.keysym.sym){ /* Ohjaus ja yleinen */ case SDLK_ESCAPE: paalla = 0; break; case SDLK_UP: Liiku(0, Suunta); update = 1; turn = 1; break; case SDLK_LEFT: Kaanny(-1); update = 1; break; case SDLK_RIGHT: Kaanny(1); update = 1; break; /* Idle */ case SDLK_COMMA: turn = 1; update = 1; break; /* MUKS! */ case SDLK_LCTRL: Hyokkaa(0, Suunta); update = 1; turn = 1; break; }; break; }; } } } /* Käännähdys */ void Kaanny(Sint16 dir){ Suunta += dir; if(Suunta < 0)Suunta = 3; if(Suunta > 3)Suunta = 0; } /* Mömmö o humauttaa suuntaan s. */ void Hyokkaa(Sint16 o, Sint16 s){ Sint16 xm, ym, ol; xm = 0; ym = 0; switch(s){ case 0: ym = -1; break; case 1: xm = 1; break; case 2: ym = 1; break; case 3: xm = -1; break; }; /* Määritetään lyönnin oikeaoppisuus. */ /* Ei seinää edessä? */ if(Kentta[Oliot[o].x][Oliot[o].y] & (1 << s))return; /* Sijainnit OK? */ if(Oliot[o].x+xm < 0 || Oliot[o].x+xm >= MaxX || Oliot[o].y+ym < 0 || Oliot[o].y+ym >= MaxY)return; /* Onkos lyönnin edessä kohdetta? */ for(ol = 0; ol < MAXOLIO; ol++){ /* Onhan siinä... */ if(Oliot[o].x+xm == Oliot[ol].x && Oliot[o].y+ym == Oliot[ol].y && ol != o)break; } if(ol >= MAXOLIO)return; /* Ei kohdetta */ Oliot[ol].hipat --; if(Oliot[ol].hipat < 1){ /* Kuoli pois - heivaus på helvetti. */ Oliot[ol].x = -10; }else{ /* Lämänotto */ } } /* Liikauttaa oliota o suuntaan s. */ void Liiku(Sint16 o, Sint16 s){ Sint16 xm, ym, aSuunta, ol; xm = 0; ym = 0; /* aSuunta = vastasuunta */ switch(s){ case 0: ym = -1; aSuunta = 2; break; case 1: xm = 1; aSuunta = 3; break; case 2: ym = 1; aSuunta = 0; break; case 3: xm = -1; aSuunta = 1; break; }; /* Seinä? */ if(Kentta[Oliot[o].x][Oliot[o].y] & (1 << s))return; /* Rajat? */ if(Oliot[o].x+xm < 0 || Oliot[o].x+xm >= MaxX || Oliot[o].y+ym < 0 || Oliot[o].y+ym >= MaxY)return; /* Ei estesinää _toiselta_ puolelta? */ if(Kentta[Oliot[o].x+xm][Oliot[o].y+ym] & (1 << aSuunta))return; for(ol = 0; ol < MAXOLIO; ol++){ /* Olio käytäväntukkeena? */ if(Oliot[o].x+xm == Oliot[ol].x && Oliot[o].y+ym == Oliot[ol].y){ /* Autetaan AI:ta -_- */ if(o > 0 && ol == 0)Hyokkaa(o, s); return; } } /* The liike */ Oliot[o].x += xm; Oliot[o].y += ym; if(o == 0){ HX += xm; HY += ym; } } /* Keinoäly juhlii */ void AI(){ Sint16 a, s; for(a = 1; a < MAXOLIO; a++){ /* Suunta joko kohti sankaria tai random */ if(abs(HX - Oliot[a].x) < 2 && abs(HY - Oliot[a].y) < 2){ if(abs(HX - Oliot[a].x) >= 2){ s = (HX < Oliot[a].x)? (3):(1); }else{ s = (HY < Oliot[a].y)? (0):(2); } }else s = rand()%4; Liiku(a, s); } } /* Teh 3D-piirto. VB-versiosta tuttu, mutta nyt piirretään vapaan kokoiselle pinnalle. Rautalankamallille ei tällä erää mahdollisuutta. */ void Piirra3D(SDL_Surface * ss){ Sint16 x, y, xx, yy, xx2, yy2, xm, ym , w, h, a, kx, ky, mw, mh, mw2, mh2, b, pala, w2, h2, kier; Sint16 ox, oy, olc; Uint32 col; SDL_Rect rect, orec; xm = 0; ym = 0; col = SDL_MapRGB(ss->format, 128, 128, 128); switch(Suunta){ case 0: ym = -1; break; case 1: xm = 1; break; case 2: ym = 1; break; case 3: xm = -1; break; }; /* Alkumuuttujia... */ w = ss->w / 16; h = ss->h / 16; w2 = w / 2; h2 = h / 2; kx = ss->w / 2; ky = ss->h / 2; /* Rivit (takaa eteen) */ for(a = Syvyys - 1; a >= 0; a--){ /* X/Y-jako */ if(ym){ y = HY + (a * ym); x = HX; }else{ y = HY; x = HX + (a * xm); } /* Laske leveydet ja korkeudet */ mw = w * (1 << (Syvyys - a - 1)); mh = h * (1 << (Syvyys - a - 1)); mw2 = w * (1 << (Syvyys - a)); mh2 = h * (1 << (Syvyys - a)); yy = ky - (h2 * (1 << (Syvyys - a - 1))); yy2 = ky - (h2 * (1 << (Syvyys - a))); /* Käy läpi 'näkyvät' tilet */ for(b = -Maara[a]; b <= Maara[a]; b++){ /* Onko ruutu kentällä? */ if((b + x >= 0 && b + x < MaxX && y >= 0 && y < MaxY && ym) || (b + y >= 0 && b + y < MaxY && x >= 0 && x < MaxX && xm)){ /* Tarvittavia muuttujia */ xx = kx - (w2 * (1 << (Syvyys - a - 1))); xx2 = kx - (w2 * (1 << (Syvyys - a))); /* Peilaus */ if(ym < 0 || xm > 0){ xx += (b * mw); xx2 += (b * mw2); }else{ xx -= (b * mw); xx2 -= (b * mw2); } if(ym){ox = b + x; oy = y;} else{ox = x; oy = b + y;} pala = Kentta[ox][oy]; /* Kierretään seinät järjestyksessä: taka, vasen, oikea, etu. */ for(kier = 0; kier < 4; kier ++){ if(pala & PiirJar[Suunta + ((xx>kx)?(4):(0))].j[kier]){ switch(kier + ((xx>kx)?(4):(0))){ case 0: case 4: rect.x = xx; rect.y = yy; rect.w = mw; rect.h = mh; TaytaBox(ss, &rect); break; case 1: case 6: TaytaVert(ss, xx, xx2, yy, yy2, mh, col); break; case 2: case 5: TaytaVert(ss, xx + mw, xx2 + mw2, yy, yy2, mh, col); break; case 3: case 7: rect.x = xx2; rect.y = yy2; rect.w = mw2; rect.h = mh2; if(a)TaytaBox(ss, &rect); break; }; } /* Tässä vaiheessa täytyy testata oliot */ if(kier == 1){ for(olc = 0; olc < MAXOLIO; olc++){ /* Piirrä mokoma */ if(Oliot[olc].x == ox && Oliot[olc].y == oy){ /* Laske sijainti laatikon pohjan keskipisteen mukaan */ rect.w = (CrGraph[Oliot[olc].gr]->w) >> (a); rect.h = (CrGraph[Oliot[olc].gr]->w) >> (a); rect.x = ((xx + xx2 + mw2) >> 1) - (rect.w); rect.y = ((yy + mh + yy2 + mh2) / 2) - rect.h; orec.w = rect.w; orec.h = rect.h; orec.x = (CrGraph[Oliot[olc].gr]->w - orec.w) >> 1; orec.y = a * CrGraph[Oliot[olc].gr]->w + ((CrGraph[Oliot[olc].gr]->w - rect.h) >> 1); /* Piirto paikkaansa */ SDL_BlitSurface(CrGraph[Oliot[olc].gr], &orec, ss, &rect); } } } } /* for kier */ }/* Kentällä */ } /* for b */ } /* for a */ } /* Kaunis kenttä. */ void TeeKentta(){ Sint16 kk[MaxX][MaxY] = { { 9, 1, 5, 5, 5, 5, 1, 3, 1, 9, 5, 5, 5, 7, 1, 3}, { 8, 0, 2, 0, 0, 0, 2,10, 0, 0, 0, 0, 0, 0, 0, 2}, { 8, 0, 2, 0, 0, 2, 2,10,12, 4, 4, 5, 5, 5, 7, 2}, { 8, 0, 2, 0, 0, 2, 2,10, 0,10, 0, 0,10, 0, 0, 2}, { 8, 4, 6, 6,11,14, 2,10, 0, 2, 0, 5, 2, 0, 0, 2}, { 9, 4, 4, 4, 4, 4, 6,10, 0,10, 0, 0,10, 0, 0, 2}, {12, 5, 5, 5, 1, 1, 3,10,12,10, 4, 4,10, 4, 4, 6}, { 8, 1, 1, 3, 0, 0, 2, 4, 5, 4, 5, 5, 4, 5, 1, 3}, {12, 4, 4, 2, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0,10, 2}, {13, 5, 5, 4, 4, 4, 6, 0, 0, 8, 0, 0, 0, 0,10, 2}, { 8, 0, 0, 3, 0, 0, 0, 0, 8, 5, 5, 5, 5, 7,10, 6}, { 8, 0, 0, 2, 0, 0, 0, 0, 8, 0, 0, 0, 0, 5, 0, 2}, { 8, 0, 0, 5, 5, 4, 1, 7, 8, 1, 1, 1, 5, 5, 5, 3}, { 8, 0, 0, 2, 0, 0,10, 0, 9, 1, 3,10, 1, 1, 1, 2}, { 8, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2,10, 0, 0, 0, 2}, {12, 4, 4, 6, 4, 4, 4, 4, 4, 4, 6,10,12, 4, 4, 6}}, x, y, sivut[4] = {1, 2, 4, 8}, sivut2[4] = {4, 8, 1, 2}, a, xm[4] = {0, 1, 0, -1}, ym[4] = {-1, 0, 1, 0}; for(y = 0; y < MaxY; y++)for(x = 0; x < MaxX; x++) Kentta[x][y] = kk[y][x]; /* Koska olen laiska paska, hoitakoon kone kentän korjaamisen -_-: tarkistetaan seinien yhtenevyys eri tilejen reunoilla */ for(y = 0; y < MaxY; y++)for(x = 0; x < MaxX; x++){ for(a = 0; a < 4; a++){ if(Kentta[x][y] & sivut[a]){ if(x + xm[a] >= 0 && x + xm[a] < MaxX && y + ym[a] >= 0 && y + ym[a] <= MaxY){ Kentta[x + xm[a]][y + ym[a]] |= sivut2[a]; } } } } /* Oliot pois. */ for(x = 0; x < MAXOLIO; x++){ Oliot[x].x = -10; } /* 'Sankari' */ Oliot[0].x = 4; Oliot[0].y = 4; Oliot[0].gr = 0; Oliot[0].hipat = 6; /* Muita olioita */ for(x = 1; x < MAXOLIO; x++){ Oliot[x].x = rand()%MaxX; Oliot[x].y = rand()%MaxY; Oliot[x].gr = 1; Oliot[x].hipat = rand()%3 + 1; } HX = Oliot[0].x; HY = Oliot[0].y; Suunta = 0; }
sqwiik, olet elite.
Tack.
Tämä on kyllä hauska. :)
moptim kirjoitti:
sqwiik, olet eläin.
KAUHEAA MITEN PITKÄÄ KOODIA!!!!!! huhhuhuh.... =)
KAUHEAA MITEN PITKÄÄ KOODIA!!!!!! huhhuhuh.... =)
KAUHEAA MITEN PITKÄÄ KOODIA!!!!!! huhhuhuh.... =)
Aihe on jo aika vanha, joten et voi enää vastata siihen.