/*============================================================================
NuSYSTEM sample program SNAKE TAIL HACK
gamemain.c
Copyright (C) 1997, NINTENDO Co,Ltd.
============================================================================*/
#include <assert.h>
#include <nusys.h>
#include <nualsgi_n.h>
#include "main.h"
#include "graphic.h"
#include "math.h"
#include "font.h"
#include "para.h"
#include "./kiyaata1.h"/*Head model data of player 1 */
#include "./kiyadou1.h"/*Tail model data of player 1*/
#include "./kiyaata2.h"/*Head model data of player 2 */
#include "./kiyadou2.h"/*Tail model data of player 2*/
#include "./kiyaata3.h"/*Head model data of player 3 */
#include "./kiyadou3.h"/*Tail model data of player 3*/
#include "./kiyaata4.h"/*Head model data of player 4 */
#include "./kiyadou4.h"/*Tail model data of player 4*/
#define START_TIME 100000000LL/*100 */
#define TAIL_NUM 0
#define TIME_UP 1
/* Function declaration */
void InitSnake( void );
void InitShotTail( void );
void DrawHead( Dynamic* , int );
void UpdateTailPos( int );
void RecordHeadPos( int );
void DrawTail( Dynamic* , int );
void ChgHeadDir( int, int, int);
void DrawShotTail( Dynamic* );
void EntryShotTail( int, int );
void EraseShotTail( int );
void ShotTailMove( void );
void SlideTail( int );
void ReadMovie( int , Dynamic* );
void DrawInfo( void );
int CheckTailNum( int );
void InitGame( void );
/* extern declaration */
/* nusys */
extern u32 nuScRetraceCounter; /* The retrace counter */
/* gameover.c */
extern int SavePak;
extern int SavePakEnd;
/* map.c*/
extern void DrawMap( Dynamic* dynamicp );
extern void DrawMapSaku( Dynamic* dynamicp );
extern void DrawMapObj( Dynamic* );
extern void DrawMovie( Dynamic* dynamicp, unsigned short * );
/* hitchk.c */
extern void Snake2Wall( int );
extern void Snake2Obj( int );
extern void Snake2Enemy( int );
extern int ShotTail2Wall( float, float );
extern int ShotTail2Obj( float, float );
extern void Snake2ShotTail( int );
extern void Snake2EnemyTail( int );
/* main.c */
extern void SaveContPak( void );
extern NUContData ContTriger[];
extern int TraceIdx;
extern int ReplayMode;
volatile extern int stage;
extern int SaveIdx;
extern int SaveOfsIdx;
/* view.c */
extern void SetViewMtx( Dynamic* dynamicp );
/* spec */
extern u8 _moviedataSegmentRomStart[];
extern u8 _moviedataSegmentRomEnd[];
/* Variable declaration */
float View; /* The camera position */
int MovieNumber; /* The texture number for the movie */
SnakePara Snake; /* Various kinds of parameters of each machine */
SnakeMove snakemove[4]; /* The buffer for drawing the body of each machine */
ShotTail mtx_shot[20]; /* Various kinds of parameters of shot tails */
int Pause; /* The flag for the pause */
int MovieUpDate; /* The counter for updating the movie*/
OSTime StartTime; /* Start time of the game */
OSTime NowTime; /* The current time */
OSTime NowPauseTime; /* For keeping time at the pause */
OSTime LapTime; /* Elapsed time */
int Winner; /* The winner number */
int UpTempo; /* The flag for tempo-up sequence */
/*--------------------------------------------------------------*/
/* makegameDL */
/* Make the display list and activate the graphic task. */
/* IN: None */
/* RET:None */
/* -------------------------------------------------------------*/
void
makegameDL(void)
{
int idx;
Dynamic* dynamicp;
/* Specify the dynamic buffer */
dynamicp = &gfx_dynamic[gfx_gtask_no];
/* Specify the display list buffer */
glistp = &gfx_glist[gfx_gtask_no][0];
/* The initialization of RSP and RDP */
gfxRCPInit();
/* Clear the frame and Z-buffer*/
gfxClearCfb();
/* Setting the view-matrix*/
SetViewMtx( dynamicp );
/* Draw the map */
DrawMap( dynamicp );
DrawMapSaku( dynamicp );
DrawMapObj( dynamicp );
/* Read the texture for the movie by PI */
ReadMovie( MovieNumber, dynamicp );
/* Draw the texture read by MovieBuf (MovieBuf[0]~MovieBuf[3] is unused data)*/
DrawMovie( dynamicp, &(dynamicp->MovieBuf[4]));
/* Draw the self-machine */
for(idx = 0; idx < 4; idx++){
UpdateTailPos( idx );
DrawTail( dynamicp, idx );
DrawHead( dynamicp, idx );
}
/* Draw the shot tail */
DrawShotTail( dynamicp );
/*Display screen information*/
DrawInfo();
gDPFullSync(glistp++);
gSPEndDisplayList(glistp++);
assert((glistp - gfx_glist[gfx_gtask_no]) < GFX_GLIST_LEN);
/* Activate the RSP task and switch display buffers*/
nuGfxTaskStart(&gfx_glist[gfx_gtask_no][0],
(s32)(glistp - gfx_glist[gfx_gtask_no]) * sizeof (Gfx),
NU_GFX_UCODE_F3DEX , NU_SC_SWAPBUFFER);
/* Specify next graphic task number */
gfx_gtask_no++;
gfx_gtask_no %= GFX_GTASK_NUM;
}
/*------------------------------*/
/* updateGame */
/* The progressing process of the game main part */
/* IN: None */
/* RET:None */
/*------------------------------*/
void
updateGame(void)
{
int padnum;
int idx;
int EnemyNum, EnemyTailNum;
s32 tempo;
/* PAUSE */
if(ContTriger[0].trigger & START_BUTTON){
nuAuSndPlayerPlay(EFF_PAUSE);
nuAuSndPlayerSetPitch(44100.0/32000);
Pause ^= 1;
}
/* Reset */
if((ContTriger[0].trigger & L_TRIG) &&
(ContTriger[0].trigger & R_TRIG)){
/* Remove the call-back function*/
nuGfxFuncRemove();
/* Return the title*/
stage = 0;
}
/* Update the timer */
if( Pause == 0 ){
NowTime = osGetTime();
NowPauseTime = NowTime - StartTime;
LapTime = START_TIME - OS_CYCLES_TO_USEC(NowTime - StartTime);
LapTime /= 1000;
}else{ /* Keep the time */
NowTime = osGetTime();
StartTime = NowTime - NowPauseTime;
LapTime = START_TIME - OS_CYCLES_TO_USEC(NowTime - StartTime);
LapTime /= 1000;
}
/* The end according to number of tails (when number of tails becomes 20)*/
if(CheckTailNum(TAIL_NUM)){
/* Indicate next stage to main */
stage = 2;
SavePak = 0;
SavePakEnd = 0;
/* Remove the call-back function*/
nuGfxFuncRemove();
}
/* The end according to time-up */
if(LapTime > NowTime){
CheckTailNum(TIME_UP);
LapTime = 0;
/* Indicate next stage to main */
stage = 2;
SavePak = 0;
SavePakEnd = 0;
/* Remove the call-back function*/
nuGfxFuncRemove();
}
/* Change the camera position */
if(nuContData[0].button & U_CBUTTONS){
if((View += 1.0) > 89.0){
View = 89.0;
}
}
/* The same as the above */
if(nuContData[0].button & D_CBUTTONS){
if((View -= 1.0) <= -89.0){
View = -89.0;
}
}
/* If it is not on the pause */
if(Pause == 0){
/* The updating process of each pad */
for(padnum = 0; padnum < NU_CONT_MAXCONTROLLERS; padnum++){
/* Go to the next if the controller pad is not connected */
/* Depend on the result of the initialization by nuContInit() of main.c*/
if(nuContStatus[padnum].errno != 0){
continue;
}
/* Go to the next if it's on fainting */
if(Snake.sleepcnt[padnum] > 0){
continue;
}
/* If the head is not piled up on the opponent's tail */
if(Snake.enemytailhit[padnum] == -1 ){
/* The button A */
if(ContTriger[padnum].trigger & A_BUTTON){
/* Do entry if the shooting tail can do entry */
if(Snake.tailcnt[padnum] > 0){
nuAuSndPlayerPlay(EFF_SHOT_TAIL);
nuAuSndPlayerSetPitch(44100.0/32000);
EntryShotTail( padnum, Snake.tail_attr[padnum][1]);
}
}
}else{ /* If the head is piled up on the opponent's tail */
/* The button A */
EnemyNum = Snake.enemytailhit[padnum];
EnemyTailNum = Snake.enemytailhitnum[padnum];
/* Take away the opponent's tail */
if(ContTriger[padnum].button & A_BUTTON){
nuAuSndPlayerPlay(EFF_EAT_TAIL);
nuAuSndPlayerSetPitch(44100.0/32000);
for(idx = EnemyTailNum; idx < Snake.tailcnt[EnemyNum]+1; idx++){
Snake.tail_attr[padnum][++Snake.tailcnt[padnum]] =
Snake.tail_attr[EnemyNum][idx];
Snake.tail_attr[EnemyNum][idx] = -1;
}
/* Shorten the tail that the one who is taken away his tail */
Snake.tailcnt[EnemyNum] = EnemyTailNum - 1;
}
}
/* Don't move during each 3D stick of X and Y between -3 to 3 (play)*/
if(!((nuContData[padnum].stick_x/10 < 3 &&
nuContData[padnum].stick_x/10 > -3) &&
(nuContData[padnum].stick_y/10 < 3 &&
nuContData[padnum].stick_y/10 > -3 ))){
/* Move the head by the 3D stick (directions of up, down, right and left) */
if( Zettai(nuContData[padnum].stick_x/5) >
Zettai(nuContData[padnum].stick_y/5) ){
Snake.pos_x[padnum][0] += nuContData[padnum].stick_x/5;
nuContData[padnum].stick_y = 0;
/* Change the head direction corresponding to the direction of the 3D stick*/
ChgHeadDir( padnum, nuContData[padnum].stick_x, 0 );
}else{
Snake.pos_y[padnum][0] += nuContData[padnum].stick_y/5;
nuContData[padnum].stick_x = 0;
/* Change the head direction corresponding to the direction of the 3D stick */
ChgHeadDir( padnum, 0, nuContData[padnum].stick_y );
}
Snake.stickon[padnum] = 1;
}else{
Snake.stickon[padnum] = 0;
}
Snake2Wall( padnum ); /* Collision detection: the self-machine vs. map area */
Snake2Obj( padnum ); /* Collision detection: the self-machine vs. map object */
Snake2Enemy( padnum ); /* Collision detection: the self-machine vs. enemy*/
Snake2EnemyTail( padnum ); /* Collision detection: the self-machine vs. opponents */
/* Return to the beginning if it hits something */
if(Snake.wallhit[padnum] == 1 || /* Hit the wall */
Snake.objhit[padnum] != -1 || /* Hit the map object */
Snake.enemyhit[padnum] != -1){ /* Hit the enemy*/
Snake.pos_x[padnum][0] -= nuContData[padnum].stick_x/5;
Snake.pos_y[padnum][0] -= nuContData[padnum].stick_y/5;
}else{
if(Snake.stickon[padnum]) /* If control stick has collapsed some degree*/
RecordHeadPos( padnum ); /* Record the head locus in the buffer */
}
/* Collision detection between the self-machine and the flown tail */
Snake2ShotTail( padnum );
if(Snake.shottailhit[padnum] != -1){
nuAuSndPlayerPlay(EFF_CUR_MOVE);
nuAuSndPlayerSetPitch(44100.0/32000);
/* Increase one tail connected the self-machine (20 max.)*/
if((Snake.tailcnt[padnum]++) >= 20){
Snake.tailcnt[padnum] = 20;
}
/* Register the hit tail to the own rear side */
Snake.tail_attr[padnum][Snake.tailcnt[padnum]] =
mtx_shot[Snake.shottailhit[padnum]].tail_pattern;
/* Erase the register of the shot tail */
EraseShotTail( Snake.shottailhit[padnum] );
}
}
ShotTailMove(); /* Move if there are any shot tail */
/* Surplus to next texture number at each specifying retrace (0 to 15)*/
if((MovieUpDate % MOVIE_UPDATE) == 0) {
if((++MovieNumber) > 15){
MovieNumber = 0;
}
}
MovieUpDate++;
/* Tempo up music if the rest of the time becomes less than 30 seconds */
if(UpTempo == 0 && (LapTime/1000) < 30){
UpTempo = 1;
tempo = nuAuSeqPlayerGetTempo(0);
tempo /= 13;
tempo *= 10;
nuAuSeqPlayerSetTempo(0,tempo);
}
/* Count down when the rest of the time is less than 30 seconds */
if(((LapTime/1000) < 32) && ((LapTime/1000) > 1)){
if(((LapTime/100) % 10) == 0){
nuAuSndPlayerPlay(EFF_TIME_DWN1);
nuAuSndPlayerSetPitch(44100.0/32000);
}
}
if((LapTime/1000) == 1){
if(((LapTime/100) % 10) == 0){
nuAuSndPlayerPlay(EFF_TIME_DWN2);
nuAuSndPlayerSetPitch(44100.0/32000);
}
}
}
}
/*------------------------------*/
/* The initialization of various parameters */
/* IN: None */
/* RET:None */
/*------------------------------*/
void
InitSnake( void )
{
int idx, idx2;
/* Initialization of self-machine (for the amount of parameters vary for each player) */
for(idx = 0; idx < SNAKE_MAX_LEN + 1; idx++){
/* The position of player 1*/
Snake.pos_x[0][idx] = -BASE_MAX_SIZE+50;
Snake.pos_y[0][idx] = BASE_MAX_SIZE-50;
Snake.pos_z[0][idx] = 30.0;
/* The head direction */
Snake.head_dir[0] = 0.0;
/* The position of player 1 */
Snake.pos_x[1][idx] = -BASE_MAX_SIZE+50;
Snake.pos_y[1][idx] = -BASE_MAX_SIZE+50;
Snake.pos_z[1][idx] = 30.0;
/* The head direction */
Snake.head_dir[1] = 90.0;
/* The position of player 1 */
Snake.pos_x[2][idx] = BASE_MAX_SIZE-50;
Snake.pos_y[2][idx] = BASE_MAX_SIZE-50;
Snake.pos_z[2][idx] = 30.0;
/* The head direction*/
Snake.head_dir[2] = 270.0;
/* The position of player 1 */
Snake.pos_x[3][idx] = BASE_MAX_SIZE-50;
Snake.pos_y[3][idx] = -BASE_MAX_SIZE+50;
Snake.pos_z[3][idx] = 30.0;
/* The head direction*/
Snake.head_dir[3] = 180.0;
}
/* Positions of the Z-axis are all common */
Snake.pos_z[0][0] = 40.0;
Snake.pos_z[1][0] = 40.0;
Snake.pos_z[2][0] = 40.0;
Snake.pos_z[3][0] = 40.0;
for(idx = 0; idx < SNAKE_MAX; idx++){
for(idx2 = 0; idx2 < SNAKE_MAX_LEN + 1; idx2++){
/* The direction of the snake (the same direction as that of the head)*/
Snake.rot_x[idx][idx2] = 0.0;
Snake.rot_y[idx][idx2] = 0.0;
Snake.rot_z[idx][idx2] = Snake.head_dir[idx];
/* The drawing size */
Snake.size_x[idx][idx2] = 2.0;
Snake.size_y[idx][idx2] = 2.0;
Snake.size_z[idx][idx2] = 2.0;
}
}
for(idx = 0; idx < SNAKE_MAX; idx++){
Snake.tailcnt[idx] = 5;
Snake.wallhit[idx] = 0;
Snake.objhit[idx] = -1;
Snake.enemyhit[idx] = -1;
Snake.bufidx[idx] = TAIL_MOVE_BUF-1;
Snake.enemytailhit[idx] = -1;
Snake.enemytailhitnum[idx] = -1;
Snake.sleepcnt[idx] = 0;
}
/* Setting the kind of the tail */
for(idx = 1; idx < 6; idx++){
Snake.tail_attr[0][idx] = 0;
Snake.tail_attr[1][idx] = 1;
Snake.tail_attr[2][idx] = 2;
Snake.tail_attr[3][idx] = 3;
}
/* The initialization of the buffer for drawing the body of the self-machine */
/* Set the default position, first */
for(idx2 = 0; idx2 < 4; idx2++){
for(idx = 0; idx < TAIL_MOVE_BUF; idx++){
snakemove[idx2].SnakeX[idx] = Snake.pos_x[idx2][0];
snakemove[idx2].SnakeY[idx] = Snake.pos_y[idx2][0];
snakemove[idx2].SnakeRotZ[idx] = Snake.rot_z[idx2][0];
}
}
}
/*------------------------------*/
/* The initialization of the shooting tail */
/* IN: None */
/* RET:None */
/*------------------------------*/
void
InitShotTail( void )
{
int idx;
for( idx = 0; idx < 20; idx++ ){
/* The position */
mtx_shot[idx].pos_x = 0.0;
mtx_shot[idx].pos_y = 0.0;
mtx_shot[idx].pos_z = 20.0;
/* The rotation */
mtx_shot[idx].rot_x = 0.0;
mtx_shot[idx].rot_y = 0.0;
mtx_shot[idx].rot_z = 0.0;
/* The size */
mtx_shot[idx].size_x = 2.0;
mtx_shot[idx].size_y = 2.0;
mtx_shot[idx].size_z = 2.0;
/* The kind */
mtx_shot[idx].tail_pattern = -1;
/* The direction */
mtx_shot[idx].tail_dir = 0.0;
/* The status */
mtx_shot[idx].status = TAIL_NOTHING;
/* The one who shots */
mtx_shot[idx].user = -1;
}
}
/*------------------------------------------------------*/
/* Entry of the tail for shooting */
/* IN: PadNum The registering player number */
/* TailAttr The kind of registering tail */
/* RET:None */
/*------------------------------------------------------*/
void
EntryShotTail( int PadNum, int TailAttr )
{
int idx;
for(idx = 0; idx < 20; idx++){
if(mtx_shot[idx].tail_pattern == -1){
mtx_shot[idx].pos_x =
Snake.pos_x[PadNum][0] + cosf(2.0*M_PI/(360/Snake.head_dir[PadNum]))*HEAD_SIZE;
mtx_shot[idx].pos_y =
Snake.pos_y[PadNum][0] + sinf(2.0*M_PI/(360/Snake.head_dir[PadNum]))*HEAD_SIZE;
/* Don't enter if the entry location is out of range of the map */
/* Don't enter if the entry location is on the map object */
if(ShotTail2Wall( mtx_shot[idx].pos_x,mtx_shot[idx].pos_y ) ||
ShotTail2Obj( mtx_shot[idx].pos_x,mtx_shot[idx].pos_y ) != -1){
return;
}
mtx_shot[idx].pos_z = Snake.pos_z[PadNum][0];
mtx_shot[idx].tail_pattern = TailAttr;
mtx_shot[idx].rot_x = Snake.rot_x[PadNum][0];
mtx_shot[idx].rot_y = Snake.rot_y[PadNum][0];
mtx_shot[idx].rot_z = Snake.rot_z[PadNum][0];
mtx_shot[idx].tail_dir = Snake.head_dir[PadNum];
mtx_shot[idx].status = TAIL_MOVING;
mtx_shot[idx].user = PadNum;
SlideTail( PadNum );
if((--Snake.tailcnt[PadNum]) < 0){
Snake.tailcnt[PadNum] = 0;
}
return;
}
}
}
/*----------------------------------------------*/
/* Erase the register of the tail for shooting */
/* IN: ShotTailNum Registered tail number */
/* RET:None */
/*----------------------------------------------*/
void
EraseShotTail( int ShotTailNum )
{
mtx_shot[ShotTailNum].pos_x = 0.0;
mtx_shot[ShotTailNum].pos_y = 0.0;
mtx_shot[ShotTailNum].pos_z = 20.0;
mtx_shot[ShotTailNum].rot_x = 0.0;
mtx_shot[ShotTailNum].rot_y = 0.0;
mtx_shot[ShotTailNum].rot_z = 0.0;
mtx_shot[ShotTailNum].size_x = 2.0;
mtx_shot[ShotTailNum].size_y = 2.0;
mtx_shot[ShotTailNum].size_z = 2.0;
mtx_shot[ShotTailNum].tail_pattern = -1;
mtx_shot[ShotTailNum].tail_dir = 0.0;
/* The status */
mtx_shot[ShotTailNum].status = TAIL_NOTHING;
}
/*--------------------------------------*/
/* Rotate the tail of the self-machine */
/* IN: PadNum Player number */
/* RET:None */
/*--------------------------------------*/
void
SlideTail( int PadNum )
{
int idx;
if(Snake.tailcnt[PadNum] >= 2){
for(idx = 1; idx < Snake.tailcnt[PadNum]+1; idx++){
Snake.tail_attr[PadNum][idx] = Snake.tail_attr[PadNum][idx+1];
}
}
}
/*------------------------------*/
/* Move of the shot tail */
/* IN: None */
/* RET:None */
/*------------------------------*/
void
ShotTailMove( void )
{
int idx;
float ChkX,ChkY;
for(idx = 0; idx < 20; idx++){
if( mtx_shot[idx].tail_pattern == -1){
continue;
}
/* Get the vector of the shot tail from the head direction */
ChkX = cosf(2.0*M_PI/(360/mtx_shot[idx].tail_dir))*SHOT_SPEED;
ChkY = sinf(2.0*M_PI/(360/mtx_shot[idx].tail_dir))*SHOT_SPEED;
/* Move it practically */
mtx_shot[idx].pos_x += ChkX;
mtx_shot[idx].pos_y += ChkY;
/* Hit the wall or obstacle */
if(ShotTail2Wall( mtx_shot[idx].pos_x,mtx_shot[idx].pos_y ) ||
ShotTail2Obj( mtx_shot[idx].pos_x,mtx_shot[idx].pos_y ) != -1){
/* Bring back to the original position */
mtx_shot[idx].pos_x -= ChkX;
mtx_shot[idx].pos_y -= ChkY;
mtx_shot[idx].status = TAIL_WAITING;
}
/* Make the shot tail rotate */
mtx_shot[idx].rot_z += 10.0;
}
}
/*--------------------------------------*/
/* Display the self-machine (the head) */
/* IN: dp The dynamic pointer */
/* Padnum The player number */
/* RET:None */
/*--------------------------------------*/
void
DrawHead( Dynamic* dp, int PadNum )
{
/* The calculation of the model coordinate system */
guTranslate(&(dp->snake_trans[PadNum][0]),
Snake.pos_x[PadNum][0],
Snake.pos_y[PadNum][0],
Snake.pos_z[PadNum][0]);
guScale(&(dp->snake_scale[PadNum][0]),
Snake.size_x[PadNum][0],
Snake.size_y[PadNum][0],
Snake.size_z[PadNum][0]);
/* On fainting */
if((--Snake.sleepcnt[PadNum]) > 0){
if(0x2 > (nuScRetraceCounter & 0x2)) {
Snake.rot_y[PadNum][0] += 3.0;
}else{
Snake.rot_y[PadNum][0] -= 3.0;
}
}else{
Snake.sleepcnt[PadNum] = 0;
Snake.rot_y[PadNum][0] = 0.0;
}
guRotateRPY(&(dp->snake_rotate[PadNum][0]),
Snake.rot_x[PadNum][0]+90.0,
Snake.rot_y[PadNum][0],
Snake.rot_z[PadNum][0]+90.0);
/* Setting the model-matrix */
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->snake_trans[PadNum][0])),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->snake_scale[PadNum][0])),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->snake_rotate[PadNum][0])),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
/* No anti-ailiasing, the opaque surface */
gDPSetRenderMode(glistp++,G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);
/* Clear and set up of geometry */
gSPClearGeometryMode(glistp++,0xFFFFFFFF);
gSPSetGeometryMode(glistp++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH | G_LIGHTING |
G_CULL_BACK);
gDPSetCycleType(glistp++, G_CYC_1CYCLE);
/* Setting the combiner */
gDPSetCombineMode(glistp++,G_CC_DECALRGB, G_CC_DECALRGB);
/* The display list of the model */
switch(PadNum){
case 0:
gSPDisplayList(glistp++,kiyaata1_mdl_model0);
break;
case 1:
gSPDisplayList(glistp++,kiyaata2_mdl_model0);
break;
case 2:
gSPDisplayList(glistp++,kiyaata3_mdl_model0);
break;
case 3:
gSPDisplayList(glistp++,kiyaata4_mdl_model0);
break;
default:
break;
}
gDPPipeSync(glistp++);
}
/*--------------------------------------*/
/* Display the self-machine (the tail) */
/* IN: dp The dynamic pointer */
/* Padnum The player number */
/* RET:None */
/*--------------------------------------*/
void
DrawTail( Dynamic* dp, int PadNum )
{
int MaxTail,idx;
MaxTail = Snake.tailcnt[PadNum];
/* Draw from the most rear tail */
for(idx = MaxTail; idx >= 1; idx--){
/* The calculation of the model coordinate system */
guTranslate(&(dp->snake_trans[PadNum][idx]),
Snake.pos_x[PadNum][idx],
Snake.pos_y[PadNum][idx],
Snake.pos_z[PadNum][idx]
);
guScale(&(dp->snake_scale[PadNum][idx]),
Snake.size_x[PadNum][idx],
Snake.size_y[PadNum][idx],
Snake.size_z[PadNum][idx]
);
guRotateRPY(&(dp->snake_rotate[PadNum][idx]),
Snake.rot_x[PadNum][idx]+90.0,
Snake.rot_y[PadNum][idx],
Snake.rot_z[PadNum][idx]+90.0
);
/* Setting the model-matrix */
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->snake_trans[PadNum][idx])),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->snake_scale[PadNum][idx])),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->snake_rotate[PadNum][idx])),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
/* No anti-aliasing, the opaque surface */
gDPSetRenderMode(glistp++,G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);
/* Clear and set up the geometry */
gSPClearGeometryMode(glistp++,0xFFFFFFFF);
gSPSetGeometryMode(glistp++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH |
G_LIGHTING | G_CULL_BACK);
gDPSetCycleType(glistp++, G_CYC_1CYCLE);
/* Setting the combiner */
gDPSetCombineMode(glistp++,G_CC_DECALRGB, G_CC_DECALRGB);
/* The display list of the model*/
switch(Snake.tail_attr[PadNum][idx]){
case 0:
gSPDisplayList(glistp++,kiyadou1_mdl_model0);
break;
case 1:
gSPDisplayList(glistp++,kiyadou2_mdl_model0);
break;
case 2:
gSPDisplayList(glistp++,kiyadow3_mdl_model0);
break;
case 3:
gSPDisplayList(glistp++,kiyadow4_mdl_model0);
break;
default:
break;
}
gDPPipeSync(glistp++);
}
}
/*--------------------------------------*/
/* Record the head locus in the buffer */
/* IN: Padnum The player number */
/* RET:None */
/*--------------------------------------*/
void
RecordHeadPos( int PadNum )
{
snakemove[PadNum].SnakeX[Snake.bufidx[PadNum]] = Snake.pos_x[PadNum][0];
snakemove[PadNum].SnakeY[Snake.bufidx[PadNum]] = Snake.pos_y[PadNum][0];
snakemove[PadNum].SnakeRotZ[Snake.bufidx[PadNum]] = Snake.rot_z[PadNum][0];
if((--Snake.bufidx[PadNum]) < 0){
Snake.bufidx[PadNum] = TAIL_MOVE_BUF-1;
}
}
/*----------------------------------------------*/
/* Move of the tail (chase the head locus) */
/* IN: Padnum The player number */
/* RET:None */
/*----------------------------------------------*/
void
UpdateTailPos( int PadNum )
{
int MaxTail,idx;
MaxTail = Snake.tailcnt[PadNum];
for(idx = 1; idx <= MaxTail; idx++){
if((Snake.bufidx[PadNum] + SUB*idx) > TAIL_MOVE_BUF-1 ){
Snake.bufidx_wk[PadNum] = Snake.bufidx[PadNum] + SUB*idx - TAIL_MOVE_BUF;
}else{
Snake.bufidx_wk[PadNum] = Snake.bufidx[PadNum] + SUB*idx;
}
Snake.pos_x[PadNum][idx] = snakemove[PadNum].SnakeX[Snake.bufidx_wk[PadNum]];
Snake.pos_y[PadNum][idx] = snakemove[PadNum].SnakeY[Snake.bufidx_wk[PadNum]];
Snake.rot_z[PadNum][idx] = snakemove[PadNum].SnakeRotZ[Snake.bufidx_wk[PadNum]];
}
}
/*--------------------------------------*/
/* Display the shot tail */
/* IN: dp The dynamic pointer */
/* RET:None */
/*--------------------------------------*/
void
DrawShotTail( Dynamic* dp )
{
int idx;
for(idx = 0; idx < 20; idx++){
if(mtx_shot[idx].tail_pattern == -1){
continue;
}else{
guTranslate(&(dp->shot_trans[idx]),
mtx_shot[idx].pos_x,
mtx_shot[idx].pos_y,
mtx_shot[idx].pos_z
);
guScale(&(dp->shot_scale[idx]),
mtx_shot[idx].size_x,
mtx_shot[idx].size_y,
mtx_shot[idx].size_z
);
guRotateRPY(&(dp->shot_rotate[idx]),
mtx_shot[idx].rot_x+90.0,
mtx_shot[idx].rot_y,
mtx_shot[idx].rot_z
);
/* Setting the model-matrix */
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->shot_trans[idx])),
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->shot_rotate[idx])),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
gSPMatrix(glistp++, OS_K0_TO_PHYSICAL(&(dp->shot_scale[idx])),
G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH);
/* No anti-aliasing, the opaque surface */
gDPSetRenderMode(glistp++,G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);
/* Clear and set up the geometry */
gSPClearGeometryMode(glistp++,0xFFFFFFFF);
gSPSetGeometryMode(glistp++, G_ZBUFFER | G_SHADE | G_SHADING_SMOOTH |
G_LIGHTING | G_CULL_BACK);
gDPSetCycleType(glistp++, G_CYC_1CYCLE);
/* Setting the combiner */
gDPSetCombineMode(glistp++,G_CC_DECALRGB, G_CC_DECALRGB);
/* The display list of the model */
switch(mtx_shot[idx].tail_pattern){
case 0:
gSPDisplayList(glistp++,kiyadou1_mdl_model0);
break;
case 1:
gSPDisplayList(glistp++,kiyadou2_mdl_model0);
break;
case 2:
gSPDisplayList(glistp++,kiyadow3_mdl_model0);
break;
case 3:
gSPDisplayList(glistp++,kiyadow4_mdl_model0);
break;
default:
break;
}
gDPPipeSync(glistp++);
}
}
}
/*------------------------------------------------------*/
/* Make the head turn in the direction of the Control Stick (in 90 degree units)*/
/* IN: PadNum The registering player number */
/* RET: None */
/*------------------------------------------------------*/
void
ChgHeadDir( int PadNum, int stickx, int sticky )
{
Snake.head_dir[PadNum] = Atan2f((float)sticky,
(float)stickx);
if(stickx < 0 && sticky == 0){
Snake.head_dir[PadNum] += 180.0;
}
Snake.rot_z[PadNum][0] = Snake.head_dir[PadNum];
}
/*----------------------------------------------*/
/* Read the movie data */
/* IN: MovieNum The scene number of the movie */
/* dp The dynamic pointer */
/* RET:None */
/*----------------------------------------------*/
void
ReadMovie( int MovieNum, Dynamic* dp )
{
u32 r2rlen;
u32 onecutlen;
/* Compute the stored segment heads of the movie data */
r2rlen = _moviedataSegmentRomEnd - _moviedataSegmentRomStart;
/* Compute the length of each scene */
onecutlen = r2rlen / 16;
/* Copy data from ROM to RDRAM, practically */
nuPiReadRom( (u32)(_moviedataSegmentRomStart + onecutlen * MovieNum),
(void *)&(dp->MovieBuf[0]),
onecutlen
);
}
/*------------------------------*/
/* Display screen information */
/* IN: None */
/* RET:None */
/*------------------------------*/
void
DrawInfo( void )
{
sprintf(outstring,"TIME:%03llu", LapTime/1000);
Draw8Font(20,20, TEX_COL_WHITE, 0);
if(ReplayMode){
sprintf(outstring,"NOW PLAYING TRACE DATA");
Draw8Font(20,30, TEX_COL_WHITE, 0);
}
if(Pause){
if(0x30 > (nuScRetraceCounter & 0x30)){
sprintf(outstring,"PAUSE");
Draw8Font(141,111, TEX_COL_BLACK, 0);
sprintf(outstring,"PAUSE");
Draw8Font(140,110, TEX_COL_GREEN, 0);
}
}
}
/*------------------------------------------------------------------------------*/
/* Count the number of tails of each snake (for the judge of the game end) */
/* IN: ChkStat Checking contents for time-up, all got tails) */
/* RET: Result -1:A tie game 0:The normal game end 1:Win with perfect */
/* : Outside work Winner The winner number */
/*------------------------------------------------------------------------------*/
int
CheckTailNum( int ChkStat )
{
int idx, TailNumWk = 0;
if(ChkStat == TIME_UP){
if(Snake.tailcnt[0] == 5 &&
Snake.tailcnt[1] == 5 &&
Snake.tailcnt[2] == 5 &&
Snake.tailcnt[3] == 5){
Winner = -1;
return(-1);
}
for(idx = 0; idx < 4; idx++){
if(TailNumWk < Snake.tailcnt[idx]){
TailNumWk = Snake.tailcnt[idx];
Winner = idx;
}
}
return(0);
}else{
for(idx = 0; idx < 4; idx++){
if(Snake.tailcnt[idx] == 20){
Winner = idx;
return(1);
}
}
return(0);
}
}
/*------------------------------*/
/* Each initialization of parts of the main game */
/* IN: None */
/* RET:None */
/*------------------------------*/
void
InitGame( void )
{
InitSnake();
InitShotTail();
View = 0.0;
MovieNumber = 0;
StartTime = osGetTime();
NowTime = osGetTime();
NowPauseTime = 0;
Pause = 1;
TraceIdx = 0;
SaveIdx = 0;
SaveOfsIdx = 0;
UpTempo = 0;
}