サンプルプログラム:4 テニスゲームっぽい何か。


速度合わせを終えました。



「おそい」  :16フレーム
「少しはやい」:8フレーム


と来たので、「はやい」:4フレーム かな?っと思ったのですが
体感的に5フレームが丁度良く感じたので5フレで決定としました。


エミュレータ上で)マウスでテストプレイはしんどかったです。


繰り返し記述が一部あるのですが
このモジュール以外で用途がない為、
たかだか2箇所くらいならと関数化しませんでした。
これ以上の発展の見込みも考えてないのでそこは妥協で進めてます。


GMLファイルロード部は週末の休み中に片す予定です。


そろそろ説明書を書かねばと。これがまた大変だったり…。
GMC4WIN の、だんさん氏の PDF マニュアルのような
ビシッ!と決まったものだと凄く素敵なのですがまだスキルが足りません(苦笑)。


焦らず急いで、まずは必要最低限の説明書きがされている
テキストマニュアルから作ってこうと思います。


TennisGame.h

/*---------------------------------------------------------------------------------
	
	Sample4 TennisGame module header
	
	version 0.01
	Dec 03, 2009
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _TENNIS_GAME_H_
#define _TENNIS_GAME_H_


#ifdef __cplusplus
extern "C" {
#endif


void TennisGame_Update(void);
void TennisGame_Clear(void);
bool TennisGame_IsExit(void);


#ifdef __cplusplus
}
#endif

#endif	//_TENNIS_GAME_H_


TennisGame.c

/*---------------------------------------------------------------------------------
	
	Sample4 TennisGame  module routine
	
	version 0.01
	Dec 03, 2009
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <string.h>

#include <nds/ndstypes.h>

#include "TennisGame.h"

#include "Outport.h"
#include "Key.h"
#include "KeyState.h"
#include "Amp.h"


#define SCORE_MAX 7

typedef enum{
	SPEED_STOP   =  0, 
	SPEED_HIGH   =  5, 
	SPEED_MIDDLE =  8, 
	SPEED_LOW    = 16
}SPEED_VAL;


typedef enum{
	
	TENNIS_GAME_INIT, 
	TENNIS_GAME_PLAY, 
	TENNIS_GAME_EXIT
	
}TENNIS_GAME_ACT;

typedef enum{
	
	TENNIS_GAME_PLAY_INIT, 
	TENNIS_GAME_PLAY_START, 
	TENNIS_GAME_PLAY_READY, 
	TENNIS_GAME_PLAY_EXEC, 
	TENNIS_GAME_PLAY_STOP, 
	TENNIS_GAME_PLAY_END
	
}TENNIS_GAMEPLAY_ACT;


typedef struct{
	
	u16 act;
	u16 play_act;
	
	u8 ball;
	u32 speed;
	
	bool serve; //0:左コート側のサーブ, 1:右コート側のサーブ
	u8 receive[2];
	u8 score[2];
	
}TennisGameStatus;


static TennisGameStatus st_tennis_game;


void tennisGame_Init(void);
void tennisGame_Play(void);
void tennisGame_Exit(void);


//---------------------------------------------------------------------------------
void tennisGame_Init(void) {
//---------------------------------------------------------------------------------
	
	memset(&st_tennis_game, 0, sizeof(st_tennis_game));
	st_tennis_game.act = TENNIS_GAME_PLAY;
	
}

//---------------------------------------------------------------------------------
void tennisGame_Play(void) {
//---------------------------------------------------------------------------------
	
	u8 key;
	static u32 frame = 0;
	
	
	if(frame){
		frame--;
	}
	
	
	switch(st_tennis_game.play_act){
		
		
	//ゲーム初期化
	case TENNIS_GAME_PLAY_INIT:
		
		st_tennis_game.score[0] = st_tennis_game.score[1] = 0;
		
		st_tennis_game.serve = 0;
		st_tennis_game.ball = 0x40;
		frame = 0;
		
		Outport_ShowBinLED(st_tennis_game.ball);
		Outport_HideNumLED();
		
		st_tennis_game.play_act = TENNIS_GAME_PLAY_START;
		
		break;
		
		
	//ゲーム開始
	case TENNIS_GAME_PLAY_START:
		
		st_tennis_game.receive[0] = st_tennis_game.receive[1] = 0x00;
		st_tennis_game.speed = SPEED_MIDDLE;
		st_tennis_game.play_act = TENNIS_GAME_PLAY_READY;
		
		break;
		
		
	//ゲーム対戦待ち
	case TENNIS_GAME_PLAY_READY:
		
		if(Amp_IsStopSound()){
			
			if(Key_IsKeyDown()){
				
				key = Key_GetKeyValue();
				
				//左コートのサーブ待ち
				if(!st_tennis_game.serve){
					if( (key == KEYPAD_0) || (key == KEYPAD_4) || (key == KEYPAD_8) || (key == KEYPAD_C) ){
						frame = st_tennis_game.speed;
						st_tennis_game.play_act = TENNIS_GAME_PLAY_EXEC;
					}
					
				//左コートのサーブ待ち
				}else{
					if( (key == KEYPAD_3) || (key == KEYPAD_7) || (key == KEYPAD_B) || (key == KEYPAD_F) ){
						frame = st_tennis_game.speed;
						st_tennis_game.play_act = TENNIS_GAME_PLAY_EXEC;
					}
					
				}
				
			}
			
		}
		
		break;
		
		
	//ゲーム対戦実行
	case TENNIS_GAME_PLAY_EXEC:
		
		//ボール移動処理
		if(!frame){
			
			//右コートがサーブ、左コートがレシーブの場合
			if(st_tennis_game.serve){
				
				//ボールがコート端の場合、ボールの跳ね返しを調べる
				if(st_tennis_game.ball == 0x40){
					
					switch(st_tennis_game.receive[0]){
						
					case 0x10://おそい
						st_tennis_game.speed = SPEED_LOW;
						break;
						
					case 0x20://少しはやい
						st_tennis_game.speed = SPEED_MIDDLE;
						break;
						
					case 0x40://はやい
						st_tennis_game.speed = SPEED_HIGH;
						break;
						
					default://ミス
						st_tennis_game.speed = SPEED_STOP;
						break;
						
					}
					
					//跳ね返し成功
					if(st_tennis_game.speed){
						
						Amp_HitSound();
						
						st_tennis_game.receive[0] = 0x00;
						st_tennis_game.serve = 1;
						frame = st_tennis_game.speed;
						
					//跳ね返しミス
					}else{
						
						st_tennis_game.score[1]++;
						
						if(st_tennis_game.score[1] < SCORE_MAX){
							Amp_CallErrorSound();
							st_tennis_game.play_act = TENNIS_GAME_PLAY_START;
							
						}else{
							Amp_CallEndSound();
							st_tennis_game.play_act = TENNIS_GAME_PLAY_STOP;
						}
						
					}
					
					st_tennis_game.serve = 0;
					
				//ボールがコート端じゃない場合、ボールの移動を進める
				}else{
					frame = st_tennis_game.speed;
					st_tennis_game.ball = st_tennis_game.ball << 1;
					Amp_BeepSound();
					
				}
				
			//左コートがサーブ、右コートがレシーブの場合
			}else{
				
				//ボールがコート端の場合、ボールの跳ね返しを調べる
				if(st_tennis_game.ball == 0x01){
					
					switch(st_tennis_game.receive[1]){
						
					case 0x04://おそい
						st_tennis_game.speed = SPEED_LOW;
						break;
						
					case 0x02://少しはやい
						st_tennis_game.speed = SPEED_MIDDLE;
						break;
						
					case 0x01://はやい
						st_tennis_game.speed = SPEED_HIGH;
						break;
						
					default://ミス
						st_tennis_game.speed = SPEED_STOP;
						break;
						
					}
					
					//跳ね返し成功
					if(st_tennis_game.speed){
						
						Amp_HitSound();
						st_tennis_game.receive[1] = 0x00;
						st_tennis_game.serve = 0;
						frame = st_tennis_game.speed;
						
					//跳ね返しミス
					}else{
						
						st_tennis_game.score[0]++;
						
						if(st_tennis_game.score[0] < SCORE_MAX){
							Amp_CallErrorSound();
							st_tennis_game.play_act = TENNIS_GAME_PLAY_START;
							
						}else{
							Amp_CallEndSound();
							st_tennis_game.play_act = TENNIS_GAME_PLAY_STOP;
						}
						
					}
					
					st_tennis_game.serve = 1;
					
				//ボールがコート端じゃない場合、ボールの移動を進める
				}else{
					frame = st_tennis_game.speed;
					st_tennis_game.ball = st_tennis_game.ball >> 1;
					Amp_BeepSound();
					
				}
				
			}
			
			//ボールを描画する
			Outport_ShowBinLED( st_tennis_game.ball );
			
		}
		
		//キー入力処理
		if(Key_IsKeyDown()){
			
			key = Key_GetKeyValue();
			
			//右コートがサーブ、左コートがレシーブの場合
			if(st_tennis_game.serve){
				
				if( (key == KEYPAD_0) || (key == KEYPAD_4) || (key == KEYPAD_8) || (key == KEYPAD_C) ){
					
					//キーの入力は1回までとする
					if(!st_tennis_game.receive[0]){
						st_tennis_game.receive[0] = st_tennis_game.ball;
					}
					
				}
				
			//左コートがサーブ、右コートがレシーブの場合
			}else{
				
				if( (key == KEYPAD_3) || (key == KEYPAD_7) || (key == KEYPAD_B) || (key == KEYPAD_F) ){
					
					//キーの入力は1回までとする
					if(!st_tennis_game.receive[1]){
						st_tennis_game.receive[1] = st_tennis_game.ball;
					}
					
				}
				
			}
			
		}
		
		break;
		
		
	//ゲーム終了
	case TENNIS_GAME_PLAY_STOP:
		
		//得点を2進LEDへ表示する
		if(Amp_IsStopSound()){
			Outport_ShowBinLED( (st_tennis_game.score[0] << 4) | st_tennis_game.score[1] );
			st_tennis_game.play_act = TENNIS_GAME_PLAY_END;
		}
		
		break;
		
		
	//ゲームの再スタート/モニタへ戻る かの選択を待つ
	case TENNIS_GAME_PLAY_END:
		
		if(Key_IsKeyDown()){
			
			key = Key_GetKeyValue();
			
			//RUNならゲームを再スタートする
			if(key == KEYPAD_RUN){
				st_tennis_game.play_act = TENNIS_GAME_PLAY_INIT;
				
			//RESETならゲーム終了してモニタへ戻る
			}else if(key == KEYPAD_RESET){
				st_tennis_game.act = TENNIS_GAME_EXIT;
				
			}
			
		}
		
		break;
		
		
	}
	
}

//---------------------------------------------------------------------------------
void tennisGame_Exit(void) {
//---------------------------------------------------------------------------------
	
	st_tennis_game.act = TENNIS_GAME_INIT;
	
}



//---------------------------------------------------------------------------------
void TennisGame_Update(void) {
//---------------------------------------------------------------------------------
	
	switch(st_tennis_game.act){
		
	case TENNIS_GAME_INIT:
		tennisGame_Init();
		break;
		
	case TENNIS_GAME_PLAY:
		tennisGame_Play();
		break;
		
	case TENNIS_GAME_EXIT:
		tennisGame_Exit();
		break;
		
	}
	
}

//---------------------------------------------------------------------------------
void TennisGame_Clear(void) {
//---------------------------------------------------------------------------------
	
	st_tennis_game.act = TENNIS_GAME_INIT;
	
}

//---------------------------------------------------------------------------------
bool TennisGame_IsExit(void) {
//---------------------------------------------------------------------------------
	
	return (st_tennis_game.act == TENNIS_GAME_INIT) ? true:false;
	
}

//---------------------------------------------------------------------------------