#include #include "defs.h" #include "pad.h" #include "sincos.h" #include "floor.h" #include "tank.h" #include "missile.h" #include "control.h" #include "radar.h" #define PACKETMAX 6144 #define PACKETMAX2 (PACKETMAX*24) #define lengthOT 10 GsOT OT[2]; GsOT_TAG zTable[2][1 << lengthOT]; PACKET GpuOutputPacket[2][PACKETMAX2]; int buffIdx, sync, syncb; DRAWENV Screen[6]; #include "views.c" #define myTMD (u_long *)0x80090000 // soon to be part of the player's structure. #define DRONE1 "Immortal Wombat " #define DRONE2 "Atari Warrior " #define PLAYER1 "Player 1 " #define PLAYER2 "Player 2 " long scores[2]; // set up the values for whole screen, and top and bottom halves void initScreens(w, h) { Screen[0].clip.x = 0; Screen[0].clip.y = 0; Screen[0].clip.w = w; Screen[0].clip.h = h; Screen[0].ofs[0] = w >> 1; Screen[0].ofs[1] = h >> 1; Screen[1].clip.x = 0; Screen[1].clip.y = 256; Screen[1].clip.w = w; Screen[1].clip.h = h; Screen[1].ofs[0] = w >> 1; Screen[1].ofs[1] = (h >> 1) + 256; Screen[2].clip.x = 0; Screen[2].clip.y = 0; Screen[2].clip.w = w; Screen[2].clip.h = h >> 1; Screen[2].ofs[0] = w >> 1; Screen[2].ofs[1] = h >> 2; Screen[3].clip.x = 0; Screen[3].clip.y = 256; Screen[3].clip.w = w; Screen[3].clip.h = h >> 1; Screen[3].ofs[0] = w >> 1; Screen[3].ofs[1] = (h >> 2) + 256; Screen[4].clip.x = 0; Screen[4].clip.y = h >> 1; Screen[4].clip.w = w; Screen[4].clip.h = h >> 1; Screen[4].ofs[0] = w >> 1; Screen[4].ofs[1] = (h >> 2) + (h >> 1); Screen[5].clip.x = 0; Screen[5].clip.y = (h >> 1) + 256; Screen[5].clip.w = w; Screen[5].clip.h = h >> 1; Screen[5].ofs[0] = w >> 1; Screen[5].ofs[1] = (h >> 2) + (h >> 1) + 256; } void SetupDisplay(void) { int i; ResetGraph(3); ResetGraph(0); // reset the graphics // if (GetVideoMode() == MODE_NTSC) // GsInitGraph(320 ,240, GsOFSGPU, 0, 0); // else GsInitGraph(320 ,256, GsOFSGPU, 0, 0); // setRECT(&GsDRAWENV.tw,0,0,32,32); GsDefDispBuff(0, 0, 0, 256); GsInit3D(); for (i = 0; i < 2; i++) { OT[i].length = lengthOT; OT[i].org = zTable[i]; OT[i].offset = 0; OT[i].point = 0; } } void PrintInfo(void); void RunDemo(void); void InitModels(void) { tmd_reset(); initTile(); initTanks(); initMissiles(); initRadar(); } void main(void) { int q = 1; u_long padl, padr; GsF_LIGHT flatLight; int intro = 1; int game_mode = 0; // 0 one player, 1 two player int scr1 = 0, scr2 = 4; // for 2 player mode these are offsets int demotime; InitModels(); SetupTiles(); SetupTanks(); SetupMissiles(); SetVideoMode(MODE_PAL); SetupDisplay(); initScreens(320, 256); //--set up light setColor(&flatLight, 255, 0, 0); setVector(&flatLight, 0, 4096, 0); GsSetFlatLight(0, &flatLight); GsSetLightMode(0); // normal lighting GsSetAmbient(ONE/2,ONE/2,ONE/2); // ambient light (RGB) GsSetProjection(500); FntLoad(512, 0); /* Load basic font pattern in frame buffer */ FntOpen(-128, -128, 256, 200, 0, 512); /* Font display location setting */ PadInit(); init_views(); initGame(); while(q) { initPlayers(); scores[0] = 0; scores[1] = 0; if(intro) blue.mode |= MODE_DRONE; demotime = 250; blue.vp = 3; while(q && intro) { padl = PadRead(); if(padl & PADselect) q = 0; if(padl & PADL1 && 0) { while(PadRead() & PADL1); gameNext(); InitModels(); initPlayers(); } if(padl & PADRleft) { while(PadRead() & PADRleft); game_mode = 0; intro = 0; } RunDemo(); demotime--; if(!demotime) { blue.vp++; blue.vp &= 0x03; demotime = 250; } } scores[0] = 0; scores[1] = 0; initPlayers(); if(!intro) blue.mode &= ~MODE_DRONE; blue.mode |= MODE_MOVE; red.mode |= MODE_MOVE; while(q && !intro) { padl = PadRead(); padr = padl >> 16; if(padl & PADselect) q = 0; if(padr & PADRleft) { while((PadRead() >> 16) & PADRleft); game_mode = !game_mode; scores[0] = 0; scores[1] = 0; if(game_mode) { scr1 = 2; red.mode &= ~MODE_DRONE; // turn off drone } else { scr1 = 0; red.mode |= MODE_DRONE; // turn drone on } } if(padl & PADRleft) { while(PadRead() & PADRleft); intro = 1; } moveBlue(padl); moveRed(padr); buffIdx = GsGetActiveBuff(); GsSetRefView2(&tankviews[blue.vp]); GsSetWorkBase((PACKET*)GpuOutputPacket[buffIdx]); GsClearOt(0, 0, &OT[buffIdx]); // DrawTanks(); // DrawMissiles(); // DrawFloor(); // GsSortClear(0, 0, 0, &OT[buffIdx]); // add cls to ordering table PutDrawEnv(&Screen[buffIdx + scr1]);// screen_mode // GsDrawOt(&OT[buffIdx]); // draw // DrawSync(0); // GsClearOt(0, 0, &OT[buffIdx]); DrawTanks(); if(red.mode & MODE_MISSILE) DrawMissiles(1); if(blue.mode & MODE_MISSILE) DrawMissiles(0); if(blue.misstime) { blue.misstime--; if(!blue.misstime) RadarClear(0); } if((blue.vp & 0x07) < 2 || (blue.vp & 0x07) > 3) { if(blue.misstime) RadarScramble(0); else if(blue.mode & MODE_MISSILE && (blue.vp & 0x07) > 3) RadarTargetM(0, red.xpos - blue.xpos, red.zpos - blue.zpos, blue.angle); else if(blue.mode & MODE_MISSILE && (blue.vp & 0x07) < 2) RadarTargetF(0, red.xpos - blue.xold, red.zpos - blue.zold, blue.xpos - blue.xold, blue.zpos - blue.zold, blue.angle); else if(red.mode & MODE_MISSILE) RadarTargetI(0, red.xold - blue.xpos, red.zold - blue.zpos, red.xpos - blue.xpos, red.zpos - blue.zpos, blue.angle); else RadarTarget(0, red.xpos - blue.xpos, red.zpos - blue.zpos, blue.angle); drawRadar(0); } DrawFloor(); GsSortClear(0, 0, 0, &OT[buffIdx]); // add cls to ordering table GsDrawOt(&OT[buffIdx]); // draw if(!game_mode) { FntPrint("Blue - %s: %d\n", PLAYER1, scores[0]); FntPrint("Red - %s: %d\n", DRONE2, scores[1]); } else { FntPrint("\n\n\n\n\n\n\n\nBlue - %s: %d\n", PLAYER1, scores[0]); } FntFlush(-1); DrawSync(0); sync = VSync(0); if(game_mode) // player 2's views { GsSetRefView2(&tankviews[red.vp]); GsSetWorkBase((PACKET*)GpuOutputPacket[buffIdx]); GsClearOt(0, 0, &OT[buffIdx]); PutDrawEnv(&Screen[buffIdx + scr2]);// screen_mode DrawTanks(); if(red.mode & MODE_MISSILE) DrawMissiles(1); if(blue.mode & MODE_MISSILE) DrawMissiles(0); if(red.misstime) { red.misstime--; if(!red.misstime) RadarClear(1); } if((red.vp & 0x07) < 2 || (red.vp & 0x07) > 3) { if(red.misstime) RadarScramble(1); else if(red.mode & MODE_MISSILE && (red.vp & 0x07) > 3) RadarTargetM(1, blue.xpos - red.xpos, blue.zpos - red.zpos, red.angle); else if(red.mode & MODE_MISSILE && (red.vp & 0x07) < 2) RadarTargetF(1, blue.xpos - red.xold, blue.zpos - red.zold, red.xpos - red.xold, red.zpos - red.zold, red.angle); else if(blue.mode & MODE_MISSILE) RadarTargetI(1, blue.xold - red.xpos, blue.zold - red.zpos, blue.xpos - red.xpos, blue.zpos - red.zpos, red.angle); else RadarTarget(1, blue.xpos - red.xpos, blue.zpos - red.zpos, red.angle); drawRadar(1); } DrawFloor(); GsDrawOt(&OT[buffIdx]); // draw FntPrint("\n\n\n\n\n\n\n\nRed - %s: %d\n", PLAYER2, scores[1]); FntFlush(-1); } DrawSync(0); // finish any drawing syncb = VSync(0); GsSwapDispBuff(); // swap screens } } ResetGraph(1); // cleanup } void RunDemo(void) { u_long padl = 0, padr = 0; long sync; moveBlue(padl); moveRed(padr); buffIdx = GsGetActiveBuff(); GsSetRefView2(&tankviews[blue.vp]); // demo runs in Umpire view... GsSetWorkBase((PACKET*)GpuOutputPacket[buffIdx]); GsClearOt(0, 0, &OT[buffIdx]); DrawFloor(); GsSortClear(0, 0, 0, &OT[buffIdx]); // add cls to ordering table PutDrawEnv(&Screen[buffIdx]);// screen_mode GsDrawOt(&OT[buffIdx]); // draw DrawSync(0); GsClearOt(0, 0, &OT[buffIdx]); DrawTanks(); if(red.mode & MODE_MISSILE) DrawMissiles(1); if(blue.mode & MODE_MISSILE) DrawMissiles(0); GsDrawOt(&OT[buffIdx]); // draw FntPrint("Combat3D by majik-zx\nPress [square] to play\n\n"); FntPrint("Blue - %s: %d\n", DRONE1, scores[0]); FntPrint("Red - %s: %d\n", DRONE2, scores[1]); FntFlush(-1); DrawSync(0); sync = VSync(0); VSync(0); // skip frame GsSwapDispBuff(); } void PrintInfo(void) { long bx, bz, rx, rz, bmx, bmz; u_long dx, dz; SVECTOR bb[4], br[4], bmp; VECTOR hb[4], hr[4], bmt; MATRIX ltw; long hp, hl1, hl2; u_long bs[2][2], rs[2][2], sector; short angle; // for collision detection, treat the bounding box as four points // the tanks have collided if one of the points on a tank is on the // inside of a line, formed by two points on the other tank, wrt the centre // of the second tank FntPrint("Vsync = %d, %d\n", sync, syncb); bx = BTanks[0].coord2->coord.t[0]; bz = BTanks[0].coord2->coord.t[2]; rx = BTanks[1].coord2->coord.t[0]; rz = BTanks[1].coord2->coord.t[2]; // find the relevant 'hot-quadrants' no point testing them all! // the numbers are found by determing where the red tank is in relation // to the blue one: // // Red // 3 | 0 // | Blue // --+-- 3 | 0 // 2 | 1 | // z --+-- // | 2 | 1 // +- x if(bx > rx) // blue tank is on the right bs[0][0] = 3, bs[0][1] = 2, rs[0][0] = 0, rs[0][1] = 1; else bs[0][0] = 0, bs[0][1] = 1, rs[0][0] = 3, rs[0][1] = 2; if(bz > rz) // blue tank is in front (above) bs[1][0] = 2, bs[1][1] = 1, rs[1][0] = 3, rs[1][1] = 0; else bs[1][0] = 3, bs[1][1] = 0, rs[1][0] = 2, rs[1][1] = 1; sector = (4096 - blue.angle) >> 10; // the 'hot-quadrant' number needs adjusting by this amount bs[0][0] += sector, bs[0][1] += sector, bs[1][0] += sector, bs[1][1] += sector; // bs[0][0] -= sector, bs[0][1] -= sector, bs[1][0] -= sector, bs[1][1] -= sector; bs[0][0] &= 0x03, bs[0][1] &= 0x03, bs[1][0] &= 0x03, bs[1][1] &= 0x03; sector = (4096 - red.angle) >> 10; // the 'hot-quadrant' number needs adjusting by this amount rs[0][0] += sector, rs[0][1] += sector, rs[1][0] += sector, rs[1][1] += sector; // rs[0][0] -= sector, rs[0][1] -= sector, rs[1][0] -= sector, rs[1][1] -= sector; rs[0][0] &= 0x03, rs[0][1] &= 0x03, rs[1][0] &= 0x03, rs[1][1] &= 0x03; FntPrint("Blue - %d %d %d %d\n", bs[0][0], bs[0][1], bs[1][0], bs[1][1]); FntPrint("Red - %d %d %d %d\n", rs[0][0], rs[0][1], rs[1][0], rs[1][1]); GsGetLw(BTanks[0].coord2, <w); setVector(&bb[0], TANK_BOUNDW, 0, TANK_BOUNDF); setVector(&bb[1], TANK_BOUNDW, 0, -TANK_BOUNDB); setVector(&bb[2], -TANK_BOUNDW, 0, -TANK_BOUNDB); setVector(&bb[3], -TANK_BOUNDW, 0, TANK_BOUNDF); ApplyMatrix(<w, &bb[0], &hb[0]); ApplyMatrix(<w, &bb[1], &hb[1]); ApplyMatrix(<w, &bb[2], &hb[2]); ApplyMatrix(<w, &bb[3], &hb[3]); /* FntPrint("\nBlue Tank...\n"); FntPrint(" Angle: %d\n", blue.angle); FntPrint(" Centre: %d, %d\n", bx, bz); FntPrint(" FrontRight(0): %d, %d\n", hb[0].vx + bx, hb[0].vz + bz); FntPrint(" BackRight(1): %d, %d\n", hb[1].vx + bx, hb[1].vz + bz); FntPrint(" BackLeft(2): %d, %d\n", hb[2].vx + bx, hb[2].vz + bz); FntPrint(" FrontLeft(3): %d, %d\n", hb[3].vx + bx, hb[3].vz + bz); */ GsGetLw(BTanks[1].coord2, <w); setVector(&br[0], TANK_BOUNDW, 0, TANK_BOUNDF); setVector(&br[1], TANK_BOUNDW, 0, -TANK_BOUNDB); setVector(&br[2], -TANK_BOUNDW, 0, -TANK_BOUNDB); setVector(&br[3], -TANK_BOUNDW, 0, TANK_BOUNDF); ApplyMatrix(<w, &br[0], &hr[0]); ApplyMatrix(<w, &br[1], &hr[1]); ApplyMatrix(<w, &br[2], &hr[2]); ApplyMatrix(<w, &br[3], &hr[3]); dx = bx - rx; dz = bz - rz; angle = rinvtan(dz, dx); FntPrint("Heading from Blue to Red is %d\n", angle); /* FntPrint("\nRed Tank...\n"); FntPrint(" Angle: %d\n", red.angle); FntPrint(" Centre: %d, %d\n", rx, rz); FntPrint(" FrontRight(0): %d, %d\n", hr[0].vx + rx, hr[0].vz + rz); FntPrint(" BackRight(1): %d, %d\n", hr[1].vx + rx, hr[1].vz + rz); FntPrint(" BackLeft(2): %d, %d\n", hr[2].vx + rx, hr[2].vz + rz); FntPrint(" FrontLeft(3): %d, %d\n", hr[3].vx + rx, hr[3].vz + rz); */ }