/*===============================================================* * Production Title: Collision Detection * *---------------------------------------------------------------* * Date Started: 08/09/99 * Code: Andrew Partington * Date Finished: 12/09/99 * * * Info: Pixel perfect collision using offscreen drawing etc * * References: * * tuto1.c : L. Evans (7/2/97, Sony Computer Entertainment Inc.) * Offscreen GsXXX operation using a seperate ordering table and * manipulating the drawing environment. * *===============================================================*/ #include #include "pad.h" #include "GFXLib.c" #include "globals.h" #include "__rts_info_t__.h" /*================================================================* * Global Data * *================================================================*/ #define OT_LENGTH 4 //Ordering table resolution (1<=base.x-32)&&(ufo.y>=base.y-32))&& ((ufo.x<=base.x+16)&&(ufo.y<=base.y+24))) { R=255; G=0; B=0; testCollision(); } else { R=G=B=255; } l1.x0=base.x-32; l1.x1=base.x+32; l1.y0=l1.y1=base.y-32; l1.r=R; l1.g=G; l1.b=B; l2.x0=base.x-32; l2.x1=base.x+32; l2.y0=l2.y1=base.y+32; l2.r=R; l2.g=G; l2.b=B; l3.y0=base.y-32; l3.y1=base.y+32; l3.x0=l3.x1=base.x-32; l3.r=R; l3.g=G; l3.b=B; l4.y0=base.y-32; l4.y1=base.y+32; l4.x0=l4.x1=base.x+32; l4.r=R; l4.g=G; l4.b=B; GsSortLine(&l1,&WorldOT[activeBuffer],0); GsSortLine(&l2,&WorldOT[activeBuffer],0); GsSortLine(&l3,&WorldOT[activeBuffer],0); GsSortLine(&l4,&WorldOT[activeBuffer],0); base2.rotate+=4096; base.rotate+=4096; // rect.x=128; // rect.y=160; // rect.w=16; // rect.h=8; // LoadImage(&rect,(u_long*)ufoArea2); // DrawSync(0); // rect.y+=SCR_HEIGHT; // LoadImage(&rect,(u_long*)ufoArea2); // DrawSync(0); getDirection(); /*----------------------------------------------------------------* * Wait for the vertical blanking gap then flip the screens * *----------------------------------------------------------------*/ DrawSync(0); //Wait for non-blocking GFX functions to terminate FntPrint("HSync: %d\n",VSync(0)); //Wait for the vertical blanking gap FntFlush(-1); GsSwapDispBuff(); //Then send the work screen to the display screen GsSortClear(0,0,64,&WorldOT[activeBuffer]); GsDrawOt(&WorldOT[activeBuffer]); //Send the OT to the GPU padStatus=PadRead(); } free(collisionArea); free(ufoArea); free(baseArea); free(clutArea); free(ufoArea2); free(baseArea2); return (0); } u_short getColour(u_char index) { return((u_short)clutArea[index]); } /** * * Collsion detection (VRAM version) * * info: This version keeps things in VRAM as much as possible * to try and get as much speed as possible. * **/ void testCollision() { RECT r; int offsetX,offsetY; //position of collider in collision buffer int offset,ufoOffset; int xpos,ypos; int collision; u_short colour; DRAWENV oldDrawEnv; //Old drawing environment //short offset[2]; //GsSPRITE b2; //b2=base; //b2.x=0; //b2.y=0; GsSetWorkBase((PACKET*)CollisionPacketArea[activeBuffer]); GsClearOt(0,0,&CollisionOT[activeBuffer]); //Clear the ordering table of commands oldDrawEnv=GsDRAWENV; //Save drawing environment for later r.x=320; r.y=447; r.w=64; r.h=64; GsDRAWENV.clip=r; GsDRAWENV.ofs[0]=320; GsDRAWENV.ofs[1]=447; PutDrawEnv(&GsDRAWENV); DrawSync(0); offsetX=(ufo.x-(base.x-32)); offsetY=(ufo.y-(base.y-32)); offset=((offsetY*64)+offsetX); // DrawSync(0); // // clear the collision area // ClearImage(&r,0,0,0); DrawSync(0); // // Step 2: Draw in things to collide with - // heres where the prerendered masks come in handy // GsSortSprite(&base2,&CollisionOT[activeBuffer],0); GsDrawOt(&CollisionOT[activeBuffer]); DrawSync(0); // // Step 3: Copy the VRAM collision area to main memory, // because we have to use main RAM to do the testing in // StoreImage(&r,(u_long*)collisionArea); DrawSync(0); ufoOffset=0; collision=0; /** * * Step 4: Do the collision detection * If the ANDed value is not equal to 0, then a pixel * is already occupying that space in the collision area, therefore a * collision must have occured. * **/ for(ypos=0;ypos<8;ypos++) { for(xpos=0;xpos<16;xpos++) { if(ufoArea[ufoOffset]!=0) //Don't bother drawing BG colour pixels { colour=clutArea[(ufoArea[ufoOffset])]; // xor the values together if((collisionArea[offset] ^ colour)!=colour) // to see if they change { collision++; //If collision detected, update // goto finish; // the flag and break out early } collisionArea[offset]=colour; //Else draw the sprite in the buffer } ufoOffset++; offset++; } offset+=(64-16); //-16 for sprite width } /** * * Determine the verdict * (and display whats happening) * **/ // DrawSync(0); // finish: GsDRAWENV=oldDrawEnv; //reset drawing environment DrawSync(0); // back to what it was PutDrawEnv(&GsDRAWENV); r.x=320; r.y=447; r.w=64; r.h=64; LoadImage(&r,(u_long*)collisionArea); DrawSync(0); MoveImage(&r,32,64); //DrawSync(0); MoveImage(&r,32,(64+SCR_HEIGHT)); DrawSync(0); // DrawSync(0); FntPrint("xoff: %d yoff: %d\n",offsetX,offsetY); if(collision>0) FntPrint("collision!\n"); // return(0); } /*==============================================* * Routine: Return whats going on with the pad * *==============================================*/ u_long PadRead() { return (~(*(pad0+3) | *(pad0+2)<<8 | *(pad1+3)<<16 | *(pad1+2)<<24)); } /*=============================================* * Routine: Do things when the pad is used * *=============================================*/ void getDirection() { // x1=(SIN[rotation>>12]>>12)+160; //Correct the X and Y coordinates for all the // y1=(COS[rotation>>12]>>12)+128; // sprites based on the angle of rotation if(padStatus & PADRdown) // X button { // rotation+=(ONE<<1); // if(rotation>=(360<<12)) rotation=0; } if(padStatus & PADRleft) //Square button { // rotation-=(ONE<<1); // if(rotation<0) rotation=(359<<12); } if(padStatus & PADLleft) { base.x--; //s1.mx-=mx1; // s1.my-=my1; // orgX-=2; } if(padStatus & PADLright) { base.x++; // orgX+=2; } if(padStatus & PADLup) { base.y--; // orgY-=2; } if(padStatus & PADLdown) { base.y++; // orgY+=2; } if(padStatus & PADL1) { // scale+=(ONE>>5); } if(padStatus & PADL2) { // scale-=(ONE>>5); } if(padStatus & PADR1) { } if(padStatus & PADR2) { } } /* // case PADRup: //triangle // break; case PADRleft: //square case PADRright: //circle break; case PADstart: break; case PADselect: break; default: // witch.u=0; break; } rotate<0) car1.car.rotate=(359<<12); } if(padStatus & PADLright) { car1.car.rotate+=car1.carSpeed; if (car1.car.rotate>=(360<<12)) car1.car.rotate=0; } */