490 lines
16 KiB
C++
490 lines
16 KiB
C++
// 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;
|
||
} |