main01.c 7.88 KB
/*============================================================================

		NINTENDO64 TECHNICAL SUPPORT CENTER 
		
		    NINTENDO64 SAMPLE PROGRAM 1

		Copyright (C) 1997, NINTENDO Co,Ltd.

============================================================================*/

#include <ultra64.h>
#include <PR/ramrom.h>
#include <assert.h>

#include "def.h"
#include "vram.h"
#include "segment.h"
#include "message.h"
#include "nnsched.h"
#include "main.h"
#include "audio.h"
#include "controller.h"
#include "graphic.h"
#include "main01.h"

/* 自機のパラメータ */
CFiter fiter[2];

/*
   弾の発射位置の修正値
   4個所から順番に弾が発射されるようにするための修正値
*/
short gun_pos[4][3] = {
  { 14,  4, 7},
  {-10, -4, 7},
  { 10, -4, 7},
  {-14,  4, 7},
};

u32 threadpri_flag = 0;


void InitFiter(CFiter *);
void fiter_move(CFiter *,int);
void bullet_move(CBullet *);
void lookat_move(int );

/* 外部変数宣言 */
extern Gfx fiter_1_dl[];
extern Gfx fiter_2_dl[];

/*--------------------------
  main01 test stage

  return: next stage no
--------------------------*/
int main01(NNSched* sched)
{

  OSMesgQueue  msgQ;
  OSMesg       msgbuf[MAX_MESGS];
  NNScClient   client;
  u32          controller_num;
  u32          endflag;
  u32          cnt;


  if(numControllers > 2){
    controller_num = 2;
  } else {
    controller_num = numControllers;
  }

  /* create message queue for VI retrace */
  osCreateMesgQueue(&msgQ, msgbuf, MAX_MESGS);

  /* add client to shceduler */
  nnScAddClient(sched, &client, &msgQ);

  /* 自機 のパラメータの初期化 */
  InitFiter(&fiter[0]);  /* 1号機 */
  fiter[0].pos.x = 45.0;
  fiter[0].dlist_ptr = fiter_1_dl;        /* ディスプレイリストの設定 */
  fiter[0].dlist_buf = (Gfx*)gfx_dlist_buf[0]; /* ディスプレイリストバッファ */

  /* ディスプレイリストの読み込み */
  auRomRead((u32)_fiter1SegmentRomStart, gfx_dlist_buf[0],
	    (u32)_fiter1SegmentRomEnd - (u32)_fiter1SegmentRomStart);

  InitFiter(&fiter[1]); /* 2号機 */
  fiter[1].pos.x = 360.0-45.0;
  fiter[1].dlist_ptr = fiter_2_dl;  /* ディスプレイリストの設定 */
  fiter[1].dlist_buf = (Gfx*)gfx_dlist_buf[1]; /* ディスプレイリストバッファ */

  /* ディスプレイリストの読み込み */
  auRomRead((u32)_fiter2SegmentRomStart, gfx_dlist_buf[1],
	    (u32)_fiter2SegmentRomEnd - (u32)_fiter2SegmentRomStart);

  /* 視点の設定 */
  lookat.eye_x = 00.0;
  lookat.eye_y = 0.0;
  lookat.eye_z = -20.0;
  lookat.at_x = 0.0;
  lookat.at_y = 0.0;
  lookat.at_z = 0.0;
  lookat.up_x = 0.0;
  lookat.up_y = 1.0;
  lookat.up_z = 0.0;
  lookat.pitch = 5.0;
  lookat.yaw =  0.0;
  lookat.roll = 0.0;
  lookat.dist = -40.0;

  /* シーケンスデータの読み込み */
  auSeqPlayerSetFile(1,0);
  auSeqPlayerPlay(1);


  /* グラフィックの表示開始 */
  graphic_no = GFX_01;
  endflag =0;

  while(!endflag){
    (void) osRecvMesg(&msgQ, NULL, OS_MESG_BLOCK);

    for(cnt = 0; cnt < controller_num; cnt++){

      fiter_move(&fiter[cnt],cnt);
      lookat_move(cnt);

      /* スタートボタンを押すと終了 */
      if(controllerdataTriger[cnt].button & START_BUTTON){
	 endflag++;
       }

      /* グラフィックスレッドのプライオリティをあげる */
      if(controllerdata_ptr[cnt]->button & Z_TRIG){
	 threadpri_flag = 1;
      } else {
	threadpri_flag = 0;
      }
    }
  }

  /* シーケンスの停止 */
  auSeqPlayerStop(1);
  graphic_no = GFX_NULL;

  /* グラフィックタスク・オーディオタスク終了待ち */
  while((auSeqPlayerState(0) != AL_STOPPED) || (pendingGFX != 0)){
    (void) osRecvMesg(&msgQ, NULL, OS_MESG_BLOCK);
  };

  /* remove client to shceduler */
  nnScRemoveClient(sched, &client);

  return MAIN_00;
}

/*-----------------------------------------------------------------------------
  ファイターのパラメータの初期化
  CFiter *fiter  : ファイター構造体へのポインタ
-----------------------------------------------------------------------------*/
void InitFiter(CFiter *fiter)
{
  u32 cnt;

  fiter->pos.x = 0.0;
  fiter->pos.y = -40.0;
  fiter->pos.z = 0.0;
  fiter->pos.roll = 0.0;
  fiter->pos.pitch = 0.0;
  fiter->pos.yaw =  0.0;
  fiter->pos.size = 0.1;
  fiter->flag = FITER_FLAG_START;
  fiter->bullet_cnt = 0;

  /* 弾の状態の初期化 */
  for(cnt =0; cnt < FITER_BULLET_NUM; cnt++){
    fiter->bullet[cnt].flag = FITER_BULLET_FLAG_NONE;
  }
}

/*-----------------------------------------------------------------------------
  ファイターの移動
  CFiter *fiter  : ファイター構造体へのポインタ
  int pad_no     : コントローラーの番号
-----------------------------------------------------------------------------*/
void fiter_move(CFiter *fiter,int pad_no)
{

  int pos_x;
  float pos_z;
  int cnt;
  int bullet_cnt;


  switch(fiter->flag){
    
  case FITER_FLAG_START:   /* 画面外から画面内へ */
    if(fiter->pos.z < 40.0){
      fiter->pos.z += 3.0;
    } else {
      fiter->pos.z = 40.0;
      fiter->flag = FITER_FLAG_PLAYER;
    }
    break;

  case FITER_FLAG_PLAYER:  /* 通常の状態。コントローラの処理 */

    /* ファイターのZ軸移動 */
    pos_z = fiter->pos.z;
    pos_z += controllerdata_ptr[pad_no]->stick_y/10;
    if(pos_z < 0.0) {
      fiter->pos.z = 0.0;
    } else if( pos_z >500.0){
      fiter->pos.z = 500.0;
    } else {
      fiter->pos.z = pos_z;
    }

    /* ファイターのX軸移動 (回転角) */
    pos_x = fiter->pos.x;
    pos_x -= controllerdata_ptr[pad_no]->stick_x/10;
    fiter->pos.x = (float)(pos_x % 360);
    
    /* ファイターの弾の移動 */
    for(cnt = 0; cnt < FITER_BULLET_NUM; cnt++){
      bullet_move(&fiter->bullet[cnt]);
    }

    /* 弾の発射 */
    if(controllerdataTriger[pad_no].button & A_BUTTON){
      /* 
	 空きバッファのサーチ
	 リスト構造にしたほうが効率が良いが、弾数が少ない間は
         総当たりで十分。
      */
      for(cnt = 0; cnt < FITER_BULLET_NUM; cnt++){
	if(fiter->bullet[cnt].flag == FITER_BULLET_FLAG_NONE){
	  /* 弾の初期位置の設定 */
	  bullet_cnt = fiter->bullet_cnt;
	  fiter->bullet_cnt++;
	  fiter->bullet_cnt &= 0x03;
	  fiter->bullet[cnt].flag = FITER_BULLET_FLAG_FIRE;
	  fiter->bullet[cnt].pos.x = fiter->pos.x + gun_pos[bullet_cnt][0];
	  fiter->bullet[cnt].pos.y = fiter->pos.y + gun_pos[bullet_cnt][1];
	  fiter->bullet[cnt].pos.z = fiter->pos.z + gun_pos[bullet_cnt][2];

	  /* 弾の音。分かりやすいようにコントローラによって音を変える */
	  auSndPlay(pad_no+2);
	  break;
	}
      } 
    }
    break;
  } /* end of switch */
}

/*-----------------------------------------------------------------------------
  ファイターの弾の移動
  CBullet* bullet : 弾の構造体のポインタ
-----------------------------------------------------------------------------*/
void bullet_move(CBullet *bullet)
{

  /* 弾の状態フラグをチェックして、各処理をする */
  switch(bullet->flag){
  case FITER_BULLET_FLAG_NONE:   /* 弾が発射されていない */
    return;
  case FITER_BULLET_FLAG_FIRE:   /* 弾が飛んでいる */

    bullet->pos.z += 20.0;

    /* 弾の位置のチェックもし1000.0以上なら消す */
    if(bullet->pos.z >1000.0 ){
      bullet->flag = FITER_BULLET_FLAG_NONE;
    }
    break;
  }
}
/*-----------------------------------------------------------------------------
  視点の移動
  一応パッドごとに視点移動を計算
-----------------------------------------------------------------------------*/
void lookat_move(int pad_no)
{

  /* C-UPボタン */
  if(controllerdata_ptr[pad_no]->button & U_CBUTTONS){
    lookat.pitch++;
    if(lookat.pitch > 89.0) {
      lookat.pitch = 89.0;
    }
  }

  /* C-DOWNボタン */
  if(controllerdata_ptr[pad_no]->button & D_CBUTTONS){
    lookat.pitch--;
    if(lookat.pitch < -89.0) {
      lookat.pitch = -89.0;
    }
  }

  /* C-RIGHTボタン */
  if(controllerdata_ptr[pad_no]->button & R_CBUTTONS){
    lookat.yaw++;
    if(lookat.yaw > 360.0) {
      lookat.yaw = 0.0;
    }
  }

  /* C-LEFTボタン */
  if(controllerdata_ptr[pad_no]->button & L_CBUTTONS){
    lookat.yaw--;
    if(lookat.yaw < 0.0) {
      lookat.yaw = 360.0;
    }
  }

  /* 十字キーUPボタン */
  if(controllerdata_ptr[pad_no]->button & U_JPAD){
    if(lookat.dist < -20.0) {
      lookat.dist++;
    }
  }

  /* 十字キーDOWNボタン */
  if(controllerdata_ptr[pad_no]->button & D_JPAD){
    lookat.dist--;
  }

}