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.