Files
csteroids/asteroids.cpp

490 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// En "crt" ficaré el "pegamento" amb SDL i les coses de Pascal
// que vullga mantindre, com els noms dels tipos.
#include "crt.h"
// Amb "keybord.pas" faré el mateix, el convertiré a SDL, mantenint
// la mateixa interficie
#include "keyboard.h"
// =================================================================
// CONST
// =================================================================
// He decidit ficar defines per a les constants, que es el més
// paregut. La constant "velocitat" se pegaba amb algunes variables
// així que la he renombrat "velocitat_inicial"
#define marge_dalt 20
#define marge_baix 460
#define marge_esq 20
#define marge_dret 620
#define max_ipunts 30
#define max_ornis 15
#define velocitat_inicial 2
#define velocitat_max 6
#define max_bales 3
// =================================================================
// TYPE
// =================================================================
// Els tipos son structs normals. El ivector el tracte a part.
struct ipunt {
real r, angle;
};
struct punt {
integer x, y;
};
// ivector es un simple array estatic de ipunts
// typedef ipunt[max_ipunts] ivector;
struct triangle {
ipunt p1,p2,p3;
punt centre;
real angle;
real velocitat;
};
struct poligon {
ipunt ipuntx[max_ipunts];
punt centre;
real angle;
real velocitat;
byte n;
real drotacio, rotacio;
boolean esta;
};
// NOTA1:
// pvirt es un array estatic pa definir un punter que despres
// pillem memoria dinamica... que mareig. Si total, es la pantalla
// virtual que pillem la memoria i no la soltem en tot el joc.
// Així que millor un simple array estatic i menys feina
//pvirt=array [1..38400] of byte;
// =================================================================
// VAR
// =================================================================
// Ací han d'anar les variables globals. He llevat moltes perque nomes s'usen
// dins del main, les quals son locals a main
triangle nau;
poligon pol;
real ang;
//char ch;
//word Dx, Dy;
byte i, aux;
integer dist;
punt puntaux;
poligon orni[max_ornis];
byte virt[38400];
poligon bales[max_bales];
// NOTA2:
// Durant el joc se usa "mem" per a accedir a la memòria directament
// per a escriure a la memòria de video (mem[$A000:i]) o a/desde la
// memòria de la pantalla virtual (mem[sef(virt^):i]), lo qual es
// marejador i ara ja no val per a res. Podria fingir-ho, pero seria
// un desperdici de memòria. Així que vaig a intercanviar tot els
// accesos a memoria de video per un access al array "video[]" i tots
// els accesos a la pantalla virtual per acces al array "virt[]".
// video[] està definit en "crt.h"
void volca() {
for (int i=0;i<38400;++i) video[i] = virt[i];
}
void crear_poligon_regular(poligon &pol, byte n, real r) {
real act, interval;
ipunt aux;
interval = 2*pi/n;
act = 0;
for (int i=0;i<n;++i) {
aux.r = r;
aux.angle = act;
pol.ipuntx[i] = aux;
act = act + interval;
}
pol.centre.x = 320;
pol.centre.y = 200;
pol.angle = 0;
pol.velocitat = velocitat_inicial;
pol.n = n;
pol.drotacio = 0.078539816;
pol.rotacio = 0;
}
/*procedure MCGA;
begin
asm
mov ax,0012h
int 10h
end;
directvideo:= false;
end;
procedure Text;
begin
asm
mov ax,0003h
int 10h
end;
end;*/
/*procedure WaitRetrace; assembler;
label
l1,l2;
asm
mov dx,3DAh
l1:
in al,dx
and al,08h
jnz l1
l2:
in al,dx
and al,08h
jz l2
end;*/
void posa(word x, word y, byte color) {
if (color==1) {
switch (x % 8) {
case 0: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0x7F) | 0x80; break;
case 1: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xBF) | 0x40; break;
case 2: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xDF) | 0x20; break;
case 3: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xEF) | 0x10; break;
case 4: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xF7) | 0x08; break;
case 5: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xFB) | 0x04; break;
case 6: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xFD) | 0x02; break;
case 7: virt[y*80+(x>>3)] = (virt[y*80+(x>>3)] & 0xFE) | 0x01; break;
}
} else if (color==0) {
switch (x % 8) {
case 0: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0x7F; break;
case 1: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xBF; break;
case 2: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xDF; break;
case 3: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xEF; break;
case 4: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xF7; break;
case 5: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xFB; break;
case 6: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xFD; break;
case 7: virt[y*80+(x>>3)] = virt[y*80+(x>>3)] & 0xFE; break;
}
}
}
byte llig(word x, word y) {
switch (x % 8) {
case 0: return (virt[y*80+(x>>3)] & 0x80) >> 7; break;
case 1: return (virt[y*80+(x>>3)] & 0x40) >> 6; break;
case 2: return (virt[y*80+(x>>3)] & 0x20) >> 5; break;
case 3: return (virt[y*80+(x>>3)] & 0x10) >> 4; break;
case 4: return (virt[y*80+(x>>3)] & 0x08) >> 3; break;
case 5: return (virt[y*80+(x>>3)] & 0x04) >> 2; break;
case 6: return (virt[y*80+(x>>3)] & 0x02) >> 1; break;
case 7: return virt[y*80+(x>>3)] & 0x01; break;
}
return 0;
}
void posavga(word x, word y, byte color) {
if (color==1) {
switch (x % 8) {
case 0: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0x7F) | 0x80; break;
case 1: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xBF) | 0x40; break;
case 2: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xDF) | 0x20; break;
case 3: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xEF) | 0x10; break;
case 4: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xF7) | 0x08; break;
case 5: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xFB) | 0x04; break;
case 6: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xFD) | 0x02; break;
case 7: video[y*80+(x>>3)] = (video[y*80+(x>>3)] & 0xFE) | 0x01; break;
}
} else if (color==0) {
switch (x % 8) {
case 0: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0x7F; break;
case 1: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xBF; break;
case 2: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xDF; break;
case 3: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xEF; break;
case 4: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xF7; break;
case 5: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xFB; break;
case 6: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xFD; break;
case 7: video[y*80+(x>>3)] = video[y*80+(x>>3)] & 0xFE; break;
}
}
}
real modul(punt p) {
// sqr(p.x) es p.x al quadrat, que sería p.x^2. Pero es mes rapid p.x*p.x
return sqrt(p.x*p.x + p.y*p.y);
}
void diferencia(punt o, punt d, punt &p) {
p.x = o.x-d.x;
p.y = o.y-d.y;
}
integer distancia(punt o, punt d) {
punt p;
diferencia(o,d,p);
return round(modul(p));
}
real angle(punt p) {
// p.x/p.y peta si p.y es zero, obviament, així que si es zero, canviem la operació
// per un nombre proper a zero (0.001).
return p.y!=0?atan(p.x/p.y):atan(p.x/0.001);
}
void clsvirt() {
for (int i=0;i<38400;++i) virt[i]=0;
}
integer sign(integer x) { //like sgn(x) in basic
// PASCAL:
// if x<0 then sign:=-1 else if x>0 then sign:=1 else sign:=0 end;
// C:
// if (x<0) return -1; else if (x>0) return 1; else return 0;
// DOC:
return x<0?-1:x>0?1:0;
}
boolean linea(word x1, word y1, word x2, word y2, word color) {
bool result = false;
integer count;
integer col = 0;
integer x = x1, y = y1;
integer xs = x2-x1, ys = y2-y1;
integer xm = sign(xs), ym = sign(ys);
xs = fabs(xs); ys = fabs(ys);
if (llig(x,y)==1) col++;
posa(x,y,color);
if (xs > ys) { // flat line <45 deg
count = -(xs >> 1);
while (x != x2) {
count += ys;
x += xm;
if (count>0) {
y += ym;
count -= xs;
}
if (llig(x,y)==1) col++;
posa(x,y,color);
}
} else { // steep line >=45 deg
count = -(ys >> 1);
while (y != y2) {
count += xs;
y += ym;
if (count>0) {
x += xm;
count -= ys;
}
if (llig(x,y)==1) col++;
posa(x,y,color);
}
}
if (col>2) result = true;
return result;
}
byte rota_tri(triangle tri, real angul, real velocitat, byte color) {
word x1 = round((tri.p1.r+velocitat)*cos(tri.p1.angle+angul))+tri.centre.x;
word x2 = round((tri.p2.r+velocitat)*cos(tri.p2.angle+angul))+tri.centre.x;
word x3 = round((tri.p3.r+velocitat)*cos(tri.p3.angle+angul))+tri.centre.x;
word y1 = round((tri.p1.r+velocitat)*sin(tri.p1.angle+angul))+tri.centre.y;
word y2 = round((tri.p2.r+velocitat)*sin(tri.p2.angle+angul))+tri.centre.y;
word y3 = round((tri.p3.r+velocitat)*sin(tri.p3.angle+angul))+tri.centre.y;
bool result = 0;
if (linea(x1,y1,x2,y2,color)) result = 1;
if (linea(x1,y1,x3,y3,color)) result = 1;
if (linea(x3,y3,x2,y2,color)) result = 1;
return result;
}
void rota_pol(poligon pol, real angul, byte color) {
punt xy[max_ipunts];
for (int i=0;i<pol.n;++i) {
xy[i].x = round((pol.ipuntx[i].r)*cos(pol.ipuntx[i].angle+angul))+pol.centre.x;
xy[i].y = round((pol.ipuntx[i].r)*sin(pol.ipuntx[i].angle+angul))+pol.centre.y;
}
for (int i=0;i<pol.n-1;++i) {
linea(xy[i].x,xy[i].y,xy[i+1].x,xy[i+1].y,color);
linea(xy[pol.n-1].x,xy[pol.n-1].y,xy[0].x,xy[0].y,color);
}
}
void mou_orni(poligon &orni) {
orni.angle = orni.angle/*+(random(256)/512)*(random(3)-1)*/;
real dy = round(orni.velocitat*sin(orni.angle-pi/2.0))+orni.centre.y;
real dx = round(orni.velocitat*cos(orni.angle-pi/2.0))+orni.centre.x;
if ((dy>marge_dalt) && (dy<marge_baix)) {
orni.centre.y = round(dy);
} else {
// NOTA3: No he pogut reproduir el moviment dels ORNIs amb el codi que hi havia en l'original. Si el fique talqual no va be.
// (els ORNIs se queden atascats a les vores). El codi original es la linea comentada despres de la actual. Seguiré investigant...
orni.angle = orni.angle+(pi*(random(200)/100));
//orni.angle = orni.angle+(random(256)/512)*(random(3)-1);
}
if ((dx>marge_esq) && (dx<marge_dret)) {
orni.centre.x = round(dx);
} else {
// vore NOTA3
orni.angle = orni.angle+(pi*(random(200)/100));
//orni.angle = orni.angle+(random(256)/512)*(random(3)-1);
}
orni.rotacio = orni.rotacio+orni.drotacio;
}
void mou_bales(poligon &orni) {
orni.angle = orni.angle/*+(random(256)/512)*(random(3)-1)*/;
real dy = round(orni.velocitat*sin(orni.angle-pi/2))+orni.centre.y;
real dx = round(orni.velocitat*cos(orni.angle-pi/2))+orni.centre.x;
if ((dy>marge_dalt) && (dy<marge_baix)) {
orni.centre.y = round(dy);
} else {
/*orni.angle:=orni.angle+(random(256)/512)*(random(3)-1)*/
orni.esta = false;
}
if ((dx>marge_esq) && (dx<marge_dret)) {
orni.centre.x = round(dx);
} else {
/*orni.angle:=orni.angle+(random(256)/512)*(random(3)-1)*/
orni.esta = false;
}
}
//var
word itocado;
poligon chatarra_cosmica;
void tocado() {
if (itocado==1) {
chatarra_cosmica.centre.x = nau.centre.x;
chatarra_cosmica.centre.y = nau.centre.y;
chatarra_cosmica.n = max_ipunts;
for (int i=0;i<max_ipunts;++i) {
chatarra_cosmica.ipuntx[i].r = 1;
chatarra_cosmica.ipuntx[i].angle = random(360)*57.295779513;
}
nau.velocitat = 0;
}
if ((nau.p1.r>1) && (nau.p2.r>1) && (nau.p3.r>1) && (itocado<170)) {
nau.p1.r = nau.p1.r-0.7;
nau.p2.r = nau.p2.r-0.7;
nau.p3.r = nau.p3.r-0.7;
nau.angle = nau.angle-0.3;
rota_tri(nau,nau.angle,0,1);
} else {
for (int i=0;i<max_ipunts;++i) {
chatarra_cosmica.ipuntx[i].r = chatarra_cosmica.ipuntx[i].r+3;
word dx = round((chatarra_cosmica.ipuntx[i].r)*cos(chatarra_cosmica.ipuntx[i].angle))
+ chatarra_cosmica.centre.x;
word dy = round((chatarra_cosmica.ipuntx[i].r)*sin(chatarra_cosmica.ipuntx[i].angle))
+ chatarra_cosmica.centre.y;
if ((dx>=0)&&(dx<640)&&(dy>0)&&(dy<480)) posa(dx,dy,1);
}
}
itocado++;
if (itocado==170) {
nau.p1.r = 12; nau.p1.angle = 3*pi/2;
nau.p2.r = 12; nau.p2.angle = pi/4;
nau.p3.r = 12; nau.p3.angle = (3*pi)/4;
nau.angle = 0;
nau.centre.x = 320; nau.centre.y = 240;
}
if ((itocado>170)&&((itocado%3)==0)) rota_tri(nau,nau.angle,nau.velocitat,1);
if (itocado>250) itocado=0;
}
int main(int argc, char *argv[]) {
randomize();
//getmem(virt,38400); virt es un array estatic, no fa falta reservar memòria
itocado = 0;
clsvirt();
nau.p1.r = 12; nau.p1.angle = 3*pi/2;
nau.p2.r = 12; nau.p2.angle = pi/4;
nau.p3.r = 12; nau.p3.angle = (3*pi)/4;
nau.angle = 0;
nau.centre.x = 320; nau.centre.y = 240;
crear_poligon_regular(pol, 10, 200);
for (int i=1;i<max_ornis;++i) crear_poligon_regular(orni[i], 5, 20);
mcga();
rota_pol(pol,0,1);
instalarkb();
do {
clsvirt();
if (teclapuls(keyArrowRight)) nau.angle += 0.157079632;
if (teclapuls(keyArrowLeft)) nau.angle -= 0.157079632;
if (teclapuls(keyArrowUp)) {
if (nau.velocitat<velocitat_max) nau.velocitat += 0.2;
}
if (teclapuls(keySpace) && (!bales[1].esta)) {
bales[1].esta = true;
bales[1].centre.x = nau.centre.x;
bales[1].centre.y = nau.centre.y;
bales[1].n = 2;
bales[1].velocitat = 7;
bales[1].ipuntx[1].r = 10;
bales[1].ipuntx[1].angle = pi/2+nau.angle;
bales[1].ipuntx[2].r = 20;
bales[1].ipuntx[2].angle = pi/2+nau.angle;
bales[1].angle = nau.angle;
}
word dy = round(nau.velocitat*sin(nau.angle-pi/2))+nau.centre.y;
word dx = round(nau.velocitat*cos(nau.angle-pi/2))+nau.centre.x;
if ((dy>marge_dalt) && (dy<marge_baix)) nau.centre.y = dy;
if ((dx>marge_esq) && (dx<marge_dret)) nau.centre.x = dx;
if (nau.velocitat>0.1) nau.velocitat -= 0.1;
/* dist:=distancia(nau.centre,pol.centre);
diferencia(pol.centre,nau.centre,puntaux);
if dist<(pol.ipuntx[1].r+30) then begin
nau.centre.x:=nau.centre.x
+round(dist*cos(angle(puntaux)+0.031415));
nau.centre.y:=nau.centre.y
+round(dist*sin(angle(puntaux)+0.031415));
end;*/
/* for i:=1 to 5 do begin
rota_pol(orni[i],ang,0);
end;*/
for (int i=1;i<max_ornis;++i) {
mou_orni(orni[i]);
rota_pol(orni[i],orni[i].rotacio,1);
}
if (itocado==0) {
aux = rota_tri(nau,nau.angle,nau.velocitat,1);
} else {
tocado();
}
if (aux==1) { itocado++; aux=0; }
if (bales[1].esta) {
mou_bales(bales[1]);
rota_pol(bales[1],0,1);
}
// fiquem "volca" i "waitretrace" al reves, ja que waitretrace fa tota la faena de enviar-ho a sdl
volca();
waitretrace();
/* if aux=1 then begin {gotoxy(0,0);write('tocado')tocado;delay(200);end;*/
gotoxy(50,24);
write("¸ Visente i Sergi");
gotoxy(50,25);
write("áETA 2.2 2/6/99");
} while (!teclapuls(keyEsc) && !shouldexit() ); // afegim el shouldexit, ja que si tanquen la finestra, deuriem eixir
desinstalarkb();
ang = 0;
do {
waitretrace();
rota_pol(pol,ang,0);
ang += 0.031415;
rota_pol(pol,ang,1);
} while (!keypressed() && !shouldexit() );
text();
return 0;
}