Algorisme Joc

Matrius. Objecte. Procediment. Referància. Ambit Global

  • Enviado por: Miquel Martí
  • Idioma: catalán
  • País: España España
  • 9 páginas
publicidad

ALGORISME JOC

[variables globals

[registre ESTAT

X: enter;

Y: enter;

E: lògic;

]fi registre

[matrius

DISPARS[5]: ESTAT;

ENEMICS[9]: ESTAT;

ESTR[101]: ESTAT;

]fi matrius

]fi variables

S'han deixat com a variables globals el registre ESTAT i les matrius de cada un dels elements del joc, ja que aquestes estructures de variables s'empren freqüentment en la majoria dels procediments i funcions del joc. Això també fa que la lectura del codi sigui més fàcil.

El registre ESTAT s'usa per guardar les coordenades d'un objecte, i l'existència o no d'aquest objecte.

Les matrius declarades es refereixen als enemics, als dispars de la nau, i a les estrelles de fons. No fa falta declarar una matriu per la nau, per què només en pot existir una.

[INICI

SORTIR <- FALS;

DISPARAR <- FALS;

SENTIT <- 0;

PUNTS <- 0;

RETARD_ENEM <- 2;

ACUM1 <- 0;

ACUM2 <- 0;

MAX_DISPAR <- 2;

MAX_ENEMIC <- 4;

MAX_ESTR <- 99;

REINICIAR (MAX_DISPAR, MAX_ENEMIC, MAX_ESTR);

Procediment que reinicia l'existència i les coordenades de tots els elements del joc.

{bucle principal}

[mentres (SORTIR = FALS)

[si (PITJAR TECLA)

GESTIONAR_TECLA (&SENTIT, &DISPARAR, &SORTIR);

]fi si

Gestiona una pulsació de teclat només si es realitza, i la reconeix. Les variables es passen per referància per poder modificar-ne el seu contingut.

[si (SENTIT /= 0)

MOURE_NAU (&SENTIT);

]fi si

El procediment de MOURE_NAU es crida sempre que SENTIT no valgui 0, per què d'aquesta forma la nau es mou sempre cap a un sentit o altra; i possibilita que es pugui disparar mentres la nau es mou. SENTIT es passa per referencia per què aquest procediment en pugui modificar el seu valor.

[des de (NUM_DISPAR <- 1 fins MAX_DISPAR)

COMPROVAR_DISPAR (NUM_DISPAR, &DISPARAR);

La variable disparar es passa per referència per què es pugui modificar, ja que el seu valor s'ha de restaurar un cop el dispar s'hagui creat; sinó la nau estaria disparant sempre.

[des de (NUM_ENEMIC <- 1 fins MAX_ENEMIC)

{retarda el moviment dels enemics}

[si (ACUM2 = RETARD_ENEM)

COMPROVAR_ENEMIC (NUM_ENEMIC, &ACUM1, &SORTIR);

ACUM2 <- 0;

[si no

ACUM2 <- ACUM2+1;

]fi si

S'ha emprat un acumulador (ACUM2) per retardar COMPROVAR_ENEMIC, ja que a la velocitat mínima (1) els enemics es moven massa aviat com per que el joc sigui jugable. Si s'hagués emprat una instrucció del tipus delay es returaria tot el joc, no només els enemics.

{si dispar mata enemic}

[si (XOC (NUM_DISPAR, NUM_ENEMIC) = 1)

GESTIONAR_XOC (NUM_DISPAR, NUM_ENEMIC, PUNTS);

La funció XOC torna 1 quan la colisió és entre un dispar i un enemic, i es passen les dades sobre els elements que han colisionat al procediment que el gestiona. També segueix el número d'enemics eliminats amb la variable PUNTS.

{si enemic mata nau}

[si no si (XOC (NUM_DISPAR, NUM_ENEMIC) = 2)

SORTIR <- VERTADER;

]fi si

Si la colisió és entre un enemic i la nau, SORTIR torna vertader per rompre el bucle principal i que s'acabi el joc.

]fi des de

]fi des de

Els dos bucles aniuats MENTRES van recorrent els diferents dispars i enemics (existesquin o no) per comprovar-ne el seu estat i gestionar-los quan faci falta

COMPROVAR_ESTR (NUM_ESTR, MAX_ESTR);

La comprovació de les estrelles no està subjecta a cap condicio. Mentre el joc no s'acabi les estrelles sempre brillen. La raó de que s'hi passin paràmetres és per què NUM_ESTR i MAX_ESTR s'han emprat al procediment que reinicia tots els elements del joc.

]fi mentres

PUNTUACIO (PUNTS);

TANCA_GRÀFICS;

Mostra la puntuació quan el joc s'ha acabat, i tanca els gràfics per tornar a la consola del S.O.

[variables

procediment REINICIAR (MAX_DISPAR: enter; MAX_ENEMIC: enter; MAX_EST: enter);

procediment GESTIONAR_TECLA (SENTIT: enter; DISPARAR: lògic; SORTIR: lògic);

procediment MOURE_NAU (SENTIT: lògic);

procediment COMPROVAR_DISPAR (NUM_DISPAR: enter; DISPARAR: lògic);

procediment COMPROVAR_ENEMIC (NUM_ENEMIC: enter; ACUM: enter; SORTIR: lògic);

procediment COMPROVAR_ESTR (NUM_ESTR: enter; MAX_ESTR: enter);

procediment GESTIONAR_XOC (NUM_DISPAR: enter; NUM_ENEMIC: enter; PUNTS: enter);

procediment PUNTUACIO (PUNTS: enter);

funció XOC (NUM_DISPAR: enter; NUM_ENEMIC: enter): enter;

SORTIR: lògic;

SENTIT: enter;

DISPARAR: lògic;

PUNTS: enter;

NUM_DISPAR: enter;

MAX_DISPAR: enter;

NUM_ENEMIC: enter;

MAX_ENEMIC: enter;

NUM_ESTR: enter;

MAX_ESTR: enter;

ACUM1: enter;

S'empra per provovar un retard entre l'aparició dels diferents enemics. Si no es fes així tots els enemics caurien en files alineades. Només s'utilitza a GESTIONAR_ENEM, però s'ha definit a l'algorisme ppal. per no haver de declarar-lo com a variable estàtica.

ACUM2: enter;

RETARD_ENEM: enter;

ACUM2 és un acumulador que es va comparant amb RETARD_ENEM. S'utilitza per retardar la gestió dels enemics i returar-ne el moviment.

]fi variables

]FI

////////////////////////////////////////////////////////////////////

procediment GESTIONAR_TECLA (SENTIT: enter; DISPARAR: enter; SORTIR: lògic)

[INICI

[variables

TECLA: caràcter;

]

TECLA <- LLEGIR_TECLA;

[cas (TECLA)

'o': *SENTIT <- -1;

'p': *SENTIT <- 1;

'ESPAI': *DISPARAR <- VERTADER;

'ESC': *SORTIR <- 1;

]fi cas

Modifica les variables que controlen el SENTIT, el DISPAR, i SORTIR segons la tecla pitjada.

]FI

{////////////////////////////////////////////////////////}

procediment MOURE_NAU (char SENTIT)

[INICI

[variables

procediment DIBUIXAR_NAU;

VEL_NAU: enter;

]fi variables

VEL_NAU <- 3;

[si (*SENTIT = -1)

[si (NAU.X <= 5)

*SENTIT <- 0; {aturar nau si s'acaba la pantalla}

[si no

NAU.X <- NAU.X - VEL_NAU;

]fi si

[si no si (*SENTIT = 1)

[si (NAU.X >= MAXIMA_X-45)

*SENTIT <- 0; {aturar nau si s'acaba la pantalla}

[si no

NAU.X <- NAU.X + VEL_NAU;

]fi si

]fi si

Depenent del valor de SENTIT modifica l'eix oX en la quantitat de VEL_NAU. Quan la nau arriba al final de la pantalla assigna 0 a SENTIT per què no s'entri dins aquest procediment i la nau no es mogui.

DIBUIXAR_NAU;

Es dibuixa la nau a la seva nova posició. No fa falta esborrar l'anterior, ja que la pròpia figura va matxacant el seu rastre. En aquest procediment no s'hi passa cap variable per què NAU.X i NAU.Y són globals.

]FI

{/////////////////////////////////////////////////////////}

procediment COMPROVAR_DISPAR (NUM_DISPAR: enter; DISPARAR: lògic)

[INICI

[variables

procediment CREAR_DISPAR (NUM_DISPAR: enter);

procediment MOURE_DISPAR (NUM_DISPAR: enter);

procediment ELIMINAR_DISPAR (NUM_DISPAR: enter);

]fi variables

{moure els dispars que existeixen}

[si (DISPARS[NUM_DISPAR].E = VERTADER)

MOURE_DISPAR (NUM_DISPAR);

{si arriba a dalt de la pantalla, eliminar dispar}

[si (DISPARS[NUM_DISPAR].Y <= 0)

ELIMINAR_DISPAR (NUM_DISPAR);

]fi si

Aquesta condició s'encarrega d'ELIMINAR_DISPAR quan el dispar al qual es refereix NUM_DISPAR arriba a la part superior de la pantalla.

{si DISPAR vertader, crear dispar i restablir valor}

[si no si (*DISPARAR = VERTADER)

CREAR_DISPAR (NUM_DISPAR);

*DISPARAR <- FALS;

]fi si

Aquestes condicions fan que si el dispar que s'intenta comprovar existeix, el mou cridant MOURE_DISPAR. Si no existeix comprova que DISPARAR sigui vertader, i en cas afirmatiu el crea amb CREAR_DISPAR.

]FI

{/////////////////////////////////////////////////////////}

procediment CREAR_DISPAR (NUM_DISPAR: enter)

[INICI

DISPARS[NUM_DISPAR].E <- VERTADER;

DISPARS[NUM_DISPAR].X <- NAU.X + (LONGITUD_NAU/2);

DISPARS[NUM_DISPAR].Y <- NAU.Y - ALTURA_DISPAR;

Aquí es crea el dispar otorgant-li l'estat de vertader a la variable que controla si existeix, i les coordenades des d'on parteix el dispar respecte a les de la nau.

]FI

{////////////////////////////////////////////////////////////////}

procediment MOURE_DISPAR (NUM_DISPAR: enter)

[INICI

[variables

procediment ESBORRAR_DISPAR (NUM_DISPAR: enter);

procediment DIBUIXAR_DISPAR (NUM_DISPAR: enter);

VEL_DISP: enter;

]fi variables

VEL_DISP <- 15;

ESBORRAR_DISPAR (NUM_DISPAR);

S'esborra el dispar abans de pintar el nou

DISPARS[NUM_DISPAR].Y <- DISPARS[NUM_DISPAR].Y - VEL_DISP;

DIBUIXAR_DISPAR (NUM_DISPAR);

Es modifica la coordenada en l'eix oY del dispar i es dibuixa el dispar a la nova posició. Així dóna la sensació de que estigui en moviment.

La coordenada modificada no es passa al procediment DIBUIXAR_DISPAR per què és d'àmbit global.

]FI

{////////////////////////////////////////////////////////////////}

procediment ELIMINAR_DISPAR (NUM_DISPAR: enter)

[INICI

[variables

procediment ESBORRAR_DISPAR (NUM_DISPAR: enter)

]fi variables

DISPARS[NUM_DISPAR].E <- FALS;

ESBORRAR_DISPAR (NUM_DISPAR);

S'elimina el dispar marcant el seu registre E com a fals, i esborrant-lo de la pantalla.

]FI

{////////////////////////////////////////////////////}

procediment COMPROVAR_ENEMIC (NUM_ENEMIC: enter; ACUM: enter; SORTIR: lògic)

[INICI

[variables

procediment CREAR_ENEMIC (NUM_ENEMIC: enter);

procediment MOURE_ENEMIC (NUM_ENEMIC: enter);

procediment ELIMINAR_ENEMIC (NUM_ENEMIC: enter);

PER_AP_ENEM: enter;

]fi variables

PER_AP_ENEM <- 25;

{si existeix l'enemic el mou, si no el crea}

[si (ENEMICS[NUM_ENEMIC].E = VERTADER)

MOURE_ENEMIC (NUM_ENEMIC);

{si enemic arriba abaix de la pantalla... s'acaba el joc}

[si (ENEMICS[NUM_ENEMIC].Y >= MAXIMA_Y-40)

*SORTIR <- VERTADER;

]fi si

{periode d'aparició, imposa retard}

[si no si (*ACUM = PER_AP_ENEM)

CREAR_ENEMIC (NUM_ENEMIC);

*ACUM <- 0;

[si no

*ACUM <- *ACUM + 1;

S'empra un acumulador per què el procediment CREAR_ENEMIC només es cridi cada X voltes de programa (PER_AP_ENEM) i els enemics no apareguin al principi de la partida tots en la mateixa fila, i estiguin més repartits per la pantalla.

]fi si

Si l'enemic a comprovar existeix, es mou (MOURE_ENEMIC). Si no existeix es crea amb CREAR_ENEMIC quan l'acumulador ACUM (que apunta a ACUM1 definit a l'algorisme ppal.) s'incrementa fins a igualar a PER_AP_ENEM (període d'aparició de l'enemic).

Així sempre existeix un nombre fixe d'enemics i la matriu està sempre plena fins on determini MAX_ENEM, ja que quan se n'elimina un (no existeix) es crea de nou en passar per aquest procediment.

]FI

{///////////////////////////////////////////////////}

procediment CREAR_ENEMIC (NUM_ENEMIC: enter)

[INICI

ENEMICS[NUM_ENEMIC].E <- VERTADER;

ENEMICS[NUM_ENEMIC].X <- aleatori(MAXIMA_X - LONGITUD_ENEM);

ENEMICS[NUM_ENEMIC].Y <- 5;

Per crear l'enemic es marca el registre E com a vertader, que en determina l'existència.

Se li assignen les coordenades, de forma que l'enemic apareixarà a un punt aleatori de la part superior.

]FI

{///////////////////////////////////////////////////}

procediment MOURE_ENEMIC (NUM_ENEMIC: enter)

[INICI

[variables

procediment DIBUIXAR_ENEMIC (NUM_ENEMIC: enter);

VEL_ENEM: enter;

]fi variables

VEL_ENEM <- 1;

ENEMICS[NUM_ENEMIC].Y <- ENEMICS[NUM_ENEMIC].Y + VEL_ENEM;

DIBUIXAR_ENEMIC (NUM_ENEMIC);

Per moure un enemic s'incrementa la coordenada oY en les unitats que determini VEL_ENEM, i es dibuixa l'enemic a la seva nova posició.

No fa falta esborrar l'anterior, ja que la pròpia figura va matxacant el seu rastre. En aquest procediment no s'hi passa cap variable per què ENEMIC[NUM_ENEMIC].X i ENEMICS[NUM_ENEMIC].Y són globals.

]FI

{///////////////////////////////////////////////////}

procediment ELIMINAR_ENEMIC(NUM_ENEMIC: enter)

[INICI

[variables

procediment ESBORRAR_ENEMIC (NUM_ENEMIC: enter);

]fi variables

ENEMICS[NUM_ENEMIC].E <- FALS;

ESBORRAR_ENEMIC (NUM_ENEMIC);

No hi ha res més senzill que eliminar un enemic: es marca com a no existent i s'esborra.

]FI

{////////////////////////////////////////////////////}

procediment COMPROVAR_ESTR (NUM_ESTR: enter; MAX_ESTR: enter)

[INICI

[variables

procediment CREAR_ESTR (NUM_ESTR: enter);

procediment ELIMINAR_ESTR (NUM_ESTR: enter);

]fi variables

{Mètode de Sa Lloca}

NUM_ESTR <- aleatori(MAX_ESTR);

[si (ESTR[NUM_ESTR].E = FALS)

CREAR_ESTR (NUM_ESTR);

[si no

ELIMINAR_ESTR (NUM_ESTR);

]fi si

El mètode de sa lloca elegeix una posició aleatòria dins la matriu d'estrelles. Si l'estrella està creada aquesta s'elimina; i si no hi està, es crea.

D'aquesta forma la matriu es va omplint d'estrelles crades fins que arriba al punt de que se'n van eliminant quan està prou plena per a què la probabilitat de que se'n vagin creant de noves sigui massa petita. A partir d'aquí el que ocurreix és que la matriu tendeix a omplir-se però no del tot deixant espai per a una petita fluctuació, que és el que fa que la pantalla estigui plena d'estrelles que apereixen i desapareixen constantment en ordre, ferqüència i posició totalment aleatoris.

Li he posat aquest nom al mètode per què s'assembla al comportament d'una lloca que pica sobre un menjador a una posició aleatoria, i quan no hi ha menjar n'hi posa per què els pollets no es quedin sense; però que quan n'hi ha prou, el menjar és per ella. De forma que el menjador està sempre ple pels polls i ella també s'alimenta.

]FI

{//////////////////////////////////////////}

procediment CREAR_ESTR (NUM_ESTR: enter)

[INICI

[variables

procediment DIBUIXAR_ESTR (NUM_ESTR: enter);

]fi variables

ESTR[NUM_ESTR].E <- VERTADER;

ESTR[NUM_ESTR].X <- aleatori(MAXIMA_X);

ESTR[NUM_ESTR].Y <- aleatori(MAXIMA_Y);

DIBUIXAR_ESTR (NUM_ESTR);

Per crear una estrella es marca com a existent, i se li assignen coordenades aleatòries, i es dibuixa a la pantalla.

]FI

{///////////////////////////////}

procediment ELIMINAR_ESTR (NUM_ESTR: enter)

[INICI

[variables

procediment ESBORRAR_ESTR (NUM_ESTR: enter);

]fi variables

ESTR[NUM_ESTR].E <- FALS;

ESBORRAR_ESTR (NUM_ESTR);

Quan s'elimina una estrella es marca la seva existència (E) com a falsa i s'esborra de la pantalla.

]FI

/////////////////////////////////////////

funció XOC (NUM_DISPAR: enter; NUM_ENEMIC: enter): enter

[INICI

{xoc dispar->enemic}

[si ((DISPARS[NUM_DISPAR].E = VERTADER) I (ENEMICS[NUM_ENEMIC].E = VERTADER) )

{si les coordenades coincideixen}

{la funcio torna 1}

{eix oX}

[si ((DISPARS[NUM_DISPAR].X >= ENEMICS[NUM_ENEMIC].X) I

(DISPARS[NUM_DISPAR].X <= ENEMICS[NUM_ENEMIC].X + LONGIDUD_ENEMIC))

{eix oY}

[si ((DISPARS[NUM_DISPAR].Y >= ENEMICS[NUM_ENEMIC].Y) I

(DISPARS[NUM_DISPAR].Y <= ENEMICS[NUM_ENEMIC].Y + ALURA_ENEMIC)

Comprova que les dues coordenades coincidesquin dins un rang.

PITAR (0.1 segons);

XOC <- 1;

]fi si

]fi si

{xoc enemic->nau}

[si no si (ENEMICS[NUM_ENEMIC].E = VERTADER)

{si les coordenades coincideixen}

{la funcio torna 2}

{eix oX}

[si ((NAU.X <= ENEMICS[NUM_ENEMIC].X + LONG_ENEM) I (NAU.X + LONG_NAU >=

ENEMICS[NUM_ENEMIC].X)

{eix oY}

[si ((NAU.Y >= ENEMICS[NUM_ENEMIC].Y) I (NAU.Y <= ENEMIC[NUM_ENEMIC].Y + ALTURA_ENEM))

Comprova que les dues coordenades coincidesquin dins un rang.

PITAR (0.1 segons);

XOC <- 2;

]fi si

]fi si

]si no

{si no hi ha hagut xoc torna 0}

XOC <- 0;

[fi si

Encara que les condicions estan molt aniuades i pareixen compilcades, el que fa aquesta funció és molt senzill.

Quan el xoc és entre un dispar i un enemic, la funció torna 1.

Si el xoc és entre un enemic i una nau, torna 2.

Si cap condició és vertadera, la funció torna 0.

]FI

////////////////////////////////////////////////////

procediment GESTIONAR_XOC (NUM_DISPAR: enter; NUM_ENEMIC: enter; PUNTS: enter)

[INICI

[variables

procediment ELIMINAR_ENEMIC (NUM_ENEMIC: enter);

procediment ELIMINAR_DISPAR (NUM_DISPAR: enter);

]fi variables

ELIMINAR_ENEMIC (NUM_ENEMIC);

ELIMINAR_DISPAR (NUM_DISPAR);

*PUNTS <- PUNTS + 1;

En aquest procediment només s'hi entra quan es mata un enemic.

Per tant, s'elimina l'enemic i el dispar que han xocat i s'anoten els punts.

]FI

{/////////////////////////////////////////////////////}

procediment PUNTUACIO (PUNTS: enter)

[INICI

[variables

CONT: enter;

]fi variables

escriure ("GAME OVER!!");

retard (2 segons);

escriure ("Puntuació: ");

escriure (PUNTS * 100);

retard (2 segons);

ESPERAR_TECLA;

En acabar-se el joc s'informa de que s'ha acabat i es mostren els punts.

]FI