しばらく先にかお見せ出来ないので、PSCデータのサンプルとして一部をお見せします。
// バトル制御データ
static PSCData_t s_PscData[] = {
//---------------------
// バトル開始
//---------------------
{ PSC_BattleIn }, //バトル開始エフェクト
{ PSC_AutoMsg,"%sがあらわれた! \n",PSCDATA_STR(PDS_MONSTER_NAME) }, //モンスター名が現れた。文字のあとの空白は間の調整
//==========================================================
// メインループ
//==========================================================
{ PSC_Label,"jp_メインループ" },//ラベル
//{
//---------------------
// 行動の選択処理
//---------------------
// 主人公パラメータの表示はシステム自動
{ PSC_CmdSelect},//動作の種類を選択「こうげき」「まほう」「アイテム」「にげる」
{ PSC_SelectJump,"jp_魔法の選択",PSC_VAR_CMD,PSC_CMD_SEL_MAGIC },//まほうの場合
{ PSC_SelectJump,"jp_アイテムの選択",PSC_VAR_CMD,PSC_CMD_SEL_ITEM },//アイテムの場合
{ PSC_Jump,"jp_攻撃開始"}, //ジャンプ。
バトル処理のヘッダ側です。
このファイルは新規作成です。
●先頭部分と定数
BattleState_tはバトル処理の戻り値です。
#ifndef INCLUDE_BATTLE_H
#define INCLUDE_BATTLE_H
#include "party.h"
//----------------------------------------------------------------------
// 定数
//----------------------------------------------------------------------
// バトル制御の戻り値
enum BattleState_t {
BATTLE_RET_BATTLEIN, //バトル開始エフェクト
BATTLE_RET_CONTINUE, //バトル継続
BATTLE_RET_GAMEOVER, //ゲームオーバー
BATTLE_RET_END, //戦闘終了
};
battle_Init()とbattle_End()は、最初と最後に呼び出してください。
battle_In()はバトル開始のための初期化関数です。
battle_Main()はバトルの処理全般を行いbattle_Draw()で描画します。
//----------------------------------------------------------------------
// 関数の宣言
//----------------------------------------------------------------------
// バトルの初期化
extern void battle_Init();
// バトルの終了処理
extern void battle_End();
// バトルの開始処理
extern void battle_In(int enemyType,int bBossEnemy);
// バトルの制御処理
extern int battle_Main(PlayerParam_t *playerParam,int masterFrame);
// バトルの描画処理
extern void battle_Draw();
#endif /*INCLUDE_BATTLE_H*/
バトル処理のプログラム側です。
このファイルは新規作成です。
●ヘッダのインクルード
ヘッダインクルードが多いです。バトルの複雑さを物語ってますね。
//------------------------------------------------------------------------------------
// バトルの制御は独自なPSCを使って行います。
// PSC(独自に命名)=プログラマブル・シーケンス・コマンド=programmable sequence command
// PSCは一般用語ではありませんので、ご注意下さい。
//------------------------------------------------------------------------------------
#include
#include
#include "main.h"
#include "battle.h"
#include "battlePSC.h"
#include "enemy.h"
#include "comsub.h"
#include "stateMng.h"
#include "winMng.h"
#include "data.h"
デバッグの用のマクロです。
要するにPSCの命令をどのタイミングで実行しているかトレースするのに使っています。
printfをしているので、コンソールが有効になっている必要があります。
//----------------------------------------------------------------------
// ●デバッグマクロ
//----------------------------------------------------------------------
// PSCのデバッグ用
#define DEBUG_PSC(format,p1,p2) { printf( "(%-6d)%s:", BattleData.masterFrame,__FUNCTION__); printf(format,p1,p2);printf("\n"); }
#define DEBUG_PSCP3(format,p1,p2,p3) { printf( "(%-6d)%s:", BattleData.masterFrame,__FUNCTION__); printf(format,p1,p2,p3);printf("\n"); }
内部関数はたくさん有るので細かい説明を省きますが、バトル補助、ウィンドウ関係(これが一番多い)、PSCの補助関数、レベルアップ関係に分かれています。
//----------------------------------------------------------------------
// ●内部関数の定義
//----------------------------------------------------------------------
// バトル補助
static void battle_LoadData(); // バトル関連のデータを読み込み
static void battle_DeleteData(); // バトル関連のデータを破棄
static void battle_DrawEnemyAndBg(); // 敵と背景を描画
static void battle_draw_in_effect(int frame); // バトル開始エフェクト処理
// ウィンドウ関係
static void battle_ActiveWnd(int wndType); // wndTypeで指定されたウィンドウを有効にする。
static void battle_WndOffset(int ofsx,int ofsy);// ウィンドウのオフセットを変更する。
static void battle_DelWnd(int wndType); // 指定されたウィンドウを閉じる。
static void battle_DelAllWnd(int bInit); // 全ウィンドウを閉じる。
static void battle_MakeHpMpList(PlayerParam_t *playerParam);//HPMP表示ウィンドウの更新
static void battle_NewWinHpMpList(); // HPMP表示ウィンドウの生成
static void battle_MenuListInit(); // メニュー専用の文字編集。初期化。
static char *battle_MenuListSprintf(char *format, ... );// メニュー専用の文字編集
// PSC補助関数
static void battle_MakePscMsg(char *buff, PSCData_t *pscData); // セリフを組み立てる。
static int battle_GetPscParam(int param,int *intData,char **strData,PSCData_t *pscData); //パラメータを解析して値を得る。
static char *battle_GetPscDataStr(int type,PSCData_t *pscData); // 文字列データの取得
static int battle_GetPscDataInt(int type); // 数値データの取得
// レベルアップ関係
static int battle_GetLevelupExpp(int level);// レベルアップに必要な経験値
static int battle_LevelScaler(int level,int min,int max);// レベルに合わせてパラメータを調整
BATTLE_DRAW_???は、バトルの描画モードを示す定数です。
PSC_RTN_???は、PSC関数の戻り値で次の動作などを示します。
PSC_WND_???は、メッセージウィンドウの種別です。
その他の細かいものとして、
BATTLE_IN_TIMEは、バトル開始エフェクトのフレーム時間。
BTL_MES_SPEEDは、バトルメッセージ速度。
MSG_BUFF_SIZEは、メッセージバッファのサイズ1行分、
PSC_CALL_STACK_MAXは、PSC_Callのコールスタックの深さでこれ以上ネスト出来ません。
LEVEL_MAXは、想定最大レベルです。
EFFECT_FRAMEは、バトル中のエフェクトのフレーム数です。
EFFECT_FRAME_FLASHは、バトル中のフラッシュ・エフェクトのフレーム数です。
//----------------------------------------------------------------------
// ●定数
//----------------------------------------------------------------------
// バトル描画の状態管理
enum {
BATTLE_DRAW_BATTLEIN, //バトル開始エフェクト
BATTLE_DRAW_BATTLE, //バトル中
BATTLE_DRAW_MAX,
};
// PSC実行関数の戻り値
enum {
PSC_RTN_CONTINUE, //同じPSCを継続。つまり一度メッセージループに戻るためreturnする。
PSC_RTN_BATTLEIN, //同じPSCを継続。バトル開始エフェクト中。メッセージループに戻るためreturnする。
PSC_RTN_NEXT, //次のPSCへ。これはメッセージループに戻らない。
PSC_RTN_END, //バトル終了。 バトルを抜ける。
PSC_RTN_GAMEVOER, //ゲームオーバー。バトルを抜ける。
};
// PSC用のウィンドウのタイプ
enum {
PSC_WND_HPMP, // HP/MPの表示用
PSC_WND_MSGD, // メッセージウィンドウ下段
PSC_WND_MENU, // メニュー用
PSC_WND_MAGIC, // まほう・メニュー用
PSC_WND_ITEM, // アイテム・メニュー用
PSC_WND_MAX, // ウィンドウの個数
};
// その他
#define BATTLE_IN_TIME (60) // バトル開始エフェクトの時間
#define BTL_MES_SPEED 5 // バトルメッセージ速度
#define MSG_BUFF_SIZE (256) // メッセージバッファのサイズ1行分
#define PSC_CALL_STACK_MAX (4) // PSC_Callのコールスタックの深さ
#define LEVEL_MAX (30) // 最大値LV
#define EFFECT_FRAME (6) // エフェクトのフレーム数
#define EFFECT_FRAME_FLASH (3) // フラッシュ・エフェクトのフレーム数
PDS_???は、PSCDATA_STR()で得られる文字列の種類を定義します。
PDI_???は、PSCDATA_INT()で得られる数値データの種類を定義します。
PARAM_TYPE_???は、パラメータのタイプを定義しています。PSCDATA_STR()とPSCDATA_INT()用です。
PSC_VAR_???はPSC関数の値を参照できるPSC変数の番号を示します。
PSC_CMD_SEL_???は、PSC_CmdSelectの戻り値です。
PSC_LEVELUP_???は、PSC_Levelupの戻り値です。
PSC_MAGIC_ACT_???は、PSC_MagicActionの戻り値です。
//----------------------------------------------------------------------
// ●PSCデータ用の定数
//----------------------------------------------------------------------
// PSCの文字列データ番号。PSCDATA_STR()
enum {
PDS_MONSTER_NAME, //モンスター名
PDS_CALL_STR_P1, //PSC_Callの文字列パラメータ1
PDS_STR0, //メッセージテーブル[0]
PDS_STR1, //メッセージテーブル[1]
PDS_STR2, //メッセージテーブル[2]
PDS_STR3, //メッセージテーブル[3]
PDS_MAX,
};
// PSCの数値データ番号。PSCDATA_INT()
enum {
PDI_PLAYER_DEF, //主人公防御力
PDI_PLAYER_ATK, //主人公攻撃力
PDI_ENEMY_DEF, //モンスター攻撃力
PDI_ENEMY_ATK, //モンスター防御力
PDI_DAMAGE, //ダメージ値
PDI_EXP, //経験値
PDI_MONEY, //お金
PDI_MAGIC_ATK, //魔法の攻撃力
PDI_CALL_P1, //PSC_Call数値パラメータ1
PDI_MAX,
};
// PSCパラメータタイプの識別番号
enum {
PARAM_TYPE_NON, //無効
PARAM_TYPE_PSCDATA_STR, //文字列データ
PARAM_TYPE_PSCDATA_INT, //数値データ
PARAM_TYPE_FIXED_INT, //数値定数
};
// PSC変数
enum {
PSC_VAR_RTN, //PSC_Returnの戻り値
PSC_VAR_CMD, //PSC_CmdSelectの値
PSC_VAR_MAGIC, //PSC_MagicSelectの値
PSC_VAR_ITEM, //PSC_ItemSelectの値
PSC_VAR_ENEMYATK, //PSC_EnemyAttackの値
PSC_VAR_LEVELUP, //PSC_Levelupの戻り値
PSC_VAR_MAGIC_ACT, //PSC_MagicActionの戻り値
PSC_VAR_MAX,
};
// PSC_CmdSelectの戻り値
enum {
PSC_CMD_SEL_ATTACK, //こうげき
PSC_CMD_SEL_MAGIC, //まほう
PSC_CMD_SEL_ITEM, //アイテム
PSC_CMD_SEL_ESCAPE, //にげる
};
// PSC_Levelupの戻り値
enum {
PSC_LEVELUP_RTN_NO, //レベルアップなし
PSC_LEVELUP_RTN_YES, //レベルアップした
PSC_LEVELUP_RTN_MAHOU, //レベルアップした。魔法も覚えた。
};
// PSC_MagicActionの戻り値
enum {
PSC_MAGIC_ACT_MSG, //メッセージ
PSC_MAGIC_ACT_FIRE, //攻撃魔法
};
メッセージ表示で使用するマクロです。
PSCDATA_STR()は、文字列変数の値を得るマクロです。
PSCDATA_INT()は、数値変数の値を得るマクロです。
FIXED_STR()は、文字列定数のマクロですが使われていません。
FIXED_INT()は、数値定数のマクロです。注意点として上位24から4ビットは識別に使われているので、そこまでの数値しか表せません。
// PSCパラメータタイプの識別番号を得る。
PSC_GETPARAM_TYPE()はPSCマクロの種別を得るためのマクロです。
PSC_GETPARAM_DATA()はPSCマクロのデータを得るためのマクロです。
//----------------------------------------------------------------------
// ●PSCデータ用のマクロ
//----------------------------------------------------------------------
// PSCパラメータマクロ。enumのPARAM_TYPE_???と合わせる。
#define PSCDATA_STR(var_no) ((PARAM_TYPE_PSCDATA_STR>24)&0xF) //識別番号を得る
#define PSC_GETPARAM_DATA(var) (((var))&0xFFFFFF) //データを得る。
PSC実行関数の宣言で、コメントでパラメータとかを説明してます。
C言語としては単なる内部関数の宣言です。
//------------------------------------------------------------------------------------
// ●PSC実行関数
//------------------------------------------------------------------------------------
// 関数 説明 str p1 p2 p3
//------------------------------------------------------------------------------------
// PSC_Exit バトルを抜ける。 終了code
// PSC_BattleIn バトル開始エフェクト なし
//-------------------------------------------------------------------
// PSC_AutoMsg バトルメッセージ自動送り format 表示p1 表示p2 使用不可
// PSC_KeyWaitMsg バトルメッセージ停止 format 表示p1 表示p2 使用不可
// PSC_ClearMsg バトルメッセージをクリア なし
//-------------------------------------------------------------------
// PSC_Label ラベル処理 ラベル
// PSC_Jump 無条件ジャンプ ラベル
// PSC_SelectJump 値条件ジャンプ ラベル PSC変数番号 値
// PSC_RandJump ランダムジャンプ ラベル 確率
// PSC_PlayerDeathJump 主人公の死亡ジャンプ ラベル
// PSC_EnemyDeathJump 敵の死亡ジャンプ ラベル
// PSC_Call 無条件CALL ラベル 引数1 引数2 引数3 文字列引数
// PSC_Return リターン 戻り値
//-------------------------------------------------------------------
// PSC_CmdSelect コマンド選択 なし
// PSC_MagicSelect まほう選択 なし
// PSC_ItemSelect アイテム選択 なし
//------------------------------------------------------------------
// PSC_DamageCalc ダメージ計算 防御力 補正値 攻撃力
// PSC_PlayerDamage主人公にダメージを与える なし
// PSC_EnemyDamage 敵にダメージを与える なし
//-------------------------------------------------------------------
// PSC_EnemyAI 敵の攻撃を決定 なし
// PSC_MagicAction 魔法の処理 なし
// PSC_ItemAction アイテムの処理 なし
//-------------------------------------------------------------------
// PSC_AttackEffect 攻撃エフェクト色 カラーコード・パラメータ
//-------------------------------------------------------------------
// PSC_Levelup レベルアップ なし
//-------------------------------------------------------------------
//------------------------------------------------------------------------------------
static int PSC_Exit(PSCData_t *pscData,int frame); //バトルを抜ける。
static int PSC_BattleIn(PSCData_t *pscData,int frame); //バトル開始エフェクト
//-------------------------------------------------------------------
static int PSC_AutoMsg(PSCData_t *pscData,int frame); //バトルメッセージ自動送り
static int PSC_KeyWaitMsg(PSCData_t *pscData,int frame);//バトルメッセージ停止
static int PSC_ClearMsg(PSCData_t *pscData,int frame); //バトルメッセージクリア
//-------------------------------------------------------------------
static int PSC_Label(PSCData_t *pscData,int frame); //ラベル処理
static int PSC_Jump(PSCData_t *pscData,int frame); //無条件ジャンプ
static int PSC_SelectJump(PSCData_t *pscData,int frame);//値条件ジャンプ
static int PSC_RandJump(PSCData_t *pscData,int frame); //ランダムジャンプ
static int PSC_PlayerDeathJump(PSCData_t *pscData,int frame); //主人公の死亡ジャンプ
static int PSC_EnemyDeathJump(PSCData_t *pscData,int frame); //敵の死亡ジャンプ
static int PSC_Call(PSCData_t *pscData,int frame); //無条件CALL
static int PSC_Return(PSCData_t *pscData,int frame); //リターン
//-------------------------------------------------------------------
static int PSC_CmdSelect(PSCData_t *pscData,int frame); //コマンド選択
static int PSC_MagicSelect(PSCData_t *pscData,int frame); //まほう選択
static int PSC_ItemSelect(PSCData_t *pscData,int frame); //アイテム選択
//-------------------------------------------------------------------
static int PSC_DamageCalc(PSCData_t *pscData,int frame); //ダメージ計算
static int PSC_PlayerDamage(PSCData_t *pscData,int frame); //主人公にダメージを与える
static int PSC_EnemyDamage(PSCData_t *pscData,int frame); //敵にダメージを与える
//------------------------------------------------------------------
static int PSC_EnemyAI(PSCData_t *pscData,int frame); //敵の攻撃を決定
static int PSC_MagicAction(PSCData_t *pscData,int frame); //魔法の処理
static int PSC_ItemAction(PSCData_t *pscData,int frame); //アイテムの処理
//-------------------------------------------------------------------
static int PSC_AttackEffect(PSCData_t *pscData,int frame); //攻撃エフェクト色
//-------------------------------------------------------------------
static int PSC_Levelup(PSCData_t *pscData,int frame); //レベルアップ
//-------------------------------------------------------------------
バトル制御データが大きくなりすぎたので別ファイルに分離しました。
雑にインクルードで組み込んでおります。
ヘッダをちゃんと整備してやればexternのテーブルにすることも出来ますが今回はしていません。
//##############################################################################
// ●バトル制御データ=PSCここから ↓↓↓
//##############################################################################
//------------------------------
// バトル制御データ
// 大きいので外部に移します。
//------------------------------
#include "battlePSCData.cpp"
//##############################################################################
// バトル制御データ=PSCここまで ↑↑↑
// ここから下はバトル制御のプログラムとテーブル
//##############################################################################
バトルは変数やテーブルが多いですよ。
バトル制御のBattleDataは構造体宣言と変数の宣言を兼ねて行っています。
各メンバ変数を説明します。
playerParamはおなじみの主人公パラメータのポインタですね。
BattleDrawStateObjは、バトル描画の状態管理オブジェクトです。
masterFrameは、PSC命令毎のフレーム数とは別のバトルのマスターフレーム数
winnoは、PSCで管理するウィンドウの情報です。
次は敵関連の管理用ですね。
EnemyTypeは敵の種類です。
bBossEnemyがボスフラグです。
enemyParamは敵パラメータのコピーですね。
imageEnemyCGは敵のCGのイメージです。
imageBGはバトル背景のイメージです。
バトルの中間処理データとしては
damageが計算したダメージ値を保持します。
MagicAtkは魔法攻撃力を一時的に保持する変数です。
続いてはダメージ・攻撃エフェクトの管理用の変数ですね。
PlayerDamageEffectCountは、主人公のダメージエフェクトの継続フレーム数のカウント用です。
EnemyDamageEffectCountは、敵のダメージエフェクトの継続フレーム数のカウント用です。
EnemyDamageEffectCountとattackEffectColorは、攻撃エフェクトの継続フレームカウントよエフェクト色です。
最後は、PSC動作時に使用する変数です。
pscVarは、PSCの変数で数値を保持します。
pscCallStackは、PSC_CallのコールスタックでpscCallStackPointはスタックのポインタです。
PSC_CallpscData;は、PSC_Call時のパラメータを保持します。
//----------------------------------------------------------------------
// ●変数/テーブル
//----------------------------------------------------------------------
// バトル管理構造体定義 兼 実体データ
static struct {
// 主人公の情報
PlayerParam_t *playerParam; // 主人公パラメータのポインタ
// バトル全体
STATEMNG_OBJECT BattleDrawStateObj; //バトル描画の状態管理オブジェクト
int masterFrame; //マスターフレーム数
int winno[PSC_WND_MAX]; // PSCで管理するウィンドウの情報
// 敵関連の管理
int EnemyType; //敵の種類
int bBossEnemy; //ボスフラグ
EnemyParam_t enemyParam;//敵パラメータ
int imageEnemyCG; //敵のCG
int imageBG; //バトル背景
// バトルの中間処理データ
int damage; //計算したダメージ値
int MagicAtk; //魔法攻撃力
// ダメージ・攻撃エフェクト
int PlayerDamageEffectCount; //主人公のダメージエフェクト
int EnemyDamageEffectCount; //敵のダメージエフェクト
int AttackEffectCount; //攻撃エフェクト
int attackEffectColor; //攻撃エフェクト色
// ワーク
int pscVar[PSC_VAR_MAX]; // バトル変数
int pscCallStack[PSC_CALL_STACK_MAX]; // コールスタック
int pscCallStackPoint; // コールスタックのポインタ
PSCData_t *PSC_CallpscData; // PSC_Callのパラメータ
} BattleData = {NULL}; //クリアのための初期値。
s_scnWndDataは、バトル中に使用するPSC_WND_???で指定されるメッセージウィンドウのパラメータです。
座標やサイズは、WMD_HPMP_SIZEXなどで#defineされますので都合によって変えてください。
s_HpMpListは、HP/MPを表示するためのリストです。
s_menuListは、メニュー用の文字列を格納するテーブルです。
s_menuAllocNoは、割り当て個数を最大MENU_STR_MAXまで割り当てることが出来ます。
s_msgTableは、メッセージを最大4セット持つことが出来るテーブルで512文字まで保存できます。PSC命令中にメッセージを作成して実際の出力は、PSC_AutoMsgなどが行います。
// ウィンドウのタイプ別のウィンドウデータ。並びはenumのPSC_WND_???に従ってください。
//HP/MPの表示用
#define WMD_HPMP_SIZEX (70)
#define WMD_HPMP_SIZEY (64)
#define WMD_HPMP_POSX (30)
#define WMD_HPMP_POSY (20)
//メニュー用
#define WND_MENU_SIZEX (110)
#define WND_MENU_SIZEY (120)
#define WND_MENU_POSX (15)
#define WND_MENU_POSY (SCREEN_Y-WND_MENU_SIZEY-10)
//メッセージ用ウィンドウ下段
#define WMD_MSG_POSX (WND_MENU_POSX+WND_MENU_SIZEX+10)
#define WMD_MSG_POSY (380)
#define WMD_MSG_SIZEX (SCREEN_X-WMD_MSG_POSX-15)
#define WMD_MSG_SIZEY (90)
const struct {
int px; //ウィンドウ座標X
int py; //ウィンドウ座標Y
int sizex; //ウィンドウサイズX
int sizey; //ウィンドウサイズY
char *name; //ウィンドウ名
} s_scnWndData[PSC_WND_MAX] = {
{WMD_HPMP_POSX,WMD_HPMP_POSY,WMD_HPMP_SIZEX,WMD_HPMP_SIZEY,"ステータス"},//PSC_WND_HPMP HP/MPの表示用
{WMD_MSG_POSX,WMD_MSG_POSY,WMD_MSG_SIZEX,WMD_MSG_SIZEY}, //PSC_WND_MSGD メッセージ用ウィンドウ下段
{WND_MENU_POSX,WND_MENU_POSY,WND_MENU_SIZEX,WND_MENU_SIZEY,"コマンド"}, //PSC_WND_MENU メニュー用
{WND_MENU_POSX,WND_MENU_POSY,WND_MENU_SIZEX,WND_MENU_SIZEY,"まほう"}, //PSC_WND_MAGIC まほう・メニュー用
{WND_MENU_POSX,WND_MENU_POSY,WND_MENU_SIZEX,WND_MENU_SIZEY,"アイテム"}, //PSC_WND_ITEM アイテム・メニュー用
};
// ステータス表示用のテーブル
#define HPMP_LIST_MAX 2
static char *s_HpMpList[HPMP_LIST_MAX+1] = {
}; // ステータス表示用のリスト
// メニュー用文字列格納テーブル
#define MENU_STR_MAX (30)
#define MENU_STR_LENGTH (32)
static char s_menuList[MENU_STR_MAX][MENU_STR_LENGTH];
static int s_menuAllocNo=-1; //割り当て済番号
// メッセージ格納テーブル
#define MSG_STRS_MAX (4)
#define MSG_STR_LEN_MAX (512)
static char s_msgTable[MSG_STRS_MAX][MSG_STR_LEN_MAX];
バトルの初期化は、バトル描画の状態管理オブジェクトの作成とbtlpsc_InitPSCでPSC環境の初期化を行っています。
//##############################################################################
// ●ここからバトル制御のプログラム
//##############################################################################
//----------------------------------------------------------------------
// バトルの初期化
//----------------------------------------------------------------------
void battle_Init()
{
//JUMP系の関数リスト
static PscFunc_t s_JpFuncs[] = {
PSC_Jump,
PSC_SelectJump,
PSC_RandJump,
PSC_PlayerDeathJump,
PSC_EnemyDeathJump,
PSC_Call,
NULL,//ストッパ
};
// バトル描画の状態管理オブジェクトの作成。
BattleData.BattleDrawStateObj = STM_Init(BATTLE_DRAW_MAX);
// バトル制御データ(PSC)の環境初期化
btlpsc_InitPSC(s_PscData,PSC_Label,s_JpFuncs);
}
バトル描画の状態管理オブジェクトの破棄が仕事です。
//----------------------------------------------------------------------
// バトルの終了処理
//----------------------------------------------------------------------
void battle_End()
{
// バトル描画の状態管理オブジェクトの破棄
STM_End(BattleData.BattleDrawStateObj);
}
バトルの開始処理。初期化関数です。
BattleDataに敵の種別(enemyType)やボスフラグ(bBossEnemy)を保存して、PSC_Callのスタックを初期化、バトル変数をクリアしてエフェクトを無効にします。
//----------------------------------------------------------------------
// バトルの開始処理
//----------------------------------------------------------------------
void battle_In(int enemyType,int bBossEnemy)
{
// 敵のタイプを保存する。
MACRO_ASSERT(enemyType>=0);
MACRO_ASSERT(enemyTypepscFunc!=NULL);
rtnPsc = (pscData->pscFunc)(pscData,btlpsc_GetFramePSC()); //引数はPSC情報と今のPSCフレーム
// PSCの戻り値がPSC_RTN_NEXTの場合はPSCを次に
if( rtnPsc == PSC_RTN_NEXT ) {
// 次のPSCに進める。
btlpsc_NextPSC();
}
// PSC命令位置更新かフレームのカウント。PSC命令位置更新ならTRUEが返る。
bNextPsc = btlpsc_UpdatePSCPointOrFrame();
// PSCの戻り値がPSC_RTN_NEXT以外の場合はループを中断する。
if( rtnPsc != PSC_RTN_NEXT ) {
break;
}
}
#if 0
// ↓仮の処理
// HIT ANY KEY
CenterDrawString( "HIT ANY KEY", 20, 320, GetColor(155,155,255) );
// 何かキーが押された?
if( g_MainData.AllKeyCount == 1 ) {
// バトルは抜ける。
bBtlExit = TRUE;
// バトル終了
rtnCode = BATTLE_RET_END;
// 抜ける。
rtnPsc = -1;
}
#endif
// PSCの戻り値で処理を分ける。
switch( rtnPsc ) {
case PSC_RTN_CONTINUE: //同じPSCを継続。つまり一度メッセージループに戻るためreturnする。
// バトルは抜けない。
bBtlExit = FALSE;
// バトル継続
rtnCode = BATTLE_RET_CONTINUE;
break;
case PSC_RTN_BATTLEIN: //同じPSCを継続。バトル開始エフェクト中。メッセージループに戻るためreturnする。
// バトルは抜けない。
bBtlExit = FALSE;
// バトル開始エフェクト中
rtnCode = BATTLE_RET_BATTLEIN;
break;
case PSC_RTN_END: //バトル終了。バトルを抜ける。
// バトルは抜ける。
bBtlExit = TRUE;
// バトル終了
rtnCode = BATTLE_RET_END;
break;
case PSC_RTN_GAMEVOER: //ゲームオーバー。バトルを抜ける。
// バトルは抜ける。
bBtlExit = TRUE;
// ゲームオーバー
rtnCode = BATTLE_RET_GAMEOVER;
break;
}
// バトルは抜ける?
if( bBtlExit ) {
// 全ウィンドウを破棄
battle_DelAllWnd(FALSE);
// バトル関連の画像を破棄
battle_DeleteData();
}
// 戻り値を返す。
return rtnCode;
}
バトル関連物を描画する処理です。
BattleDrawStateObjの状態でバトル開始エフェクト(battle_draw_in_effect)と通常の敵と背景の描画(battle_DrawEnemyAndBg)を切り分けています。
エフェクトとして、PlayerDamageEffectCountが有効期間だけ主人公のダメージとしてウィンドウをわずかにズラしています。
AttackEffectCountが有効な期間は指定カラーの半透明のエフェクトを上にかぶせます。
//----------------------------------------------------------------------
// バトルの描画処理
//----------------------------------------------------------------------
void battle_Draw()
{
// バトル描画状態の更新・フレームカウント
STM_UpdateState(BattleData.BattleDrawStateObj);
// 今のフレーム
int frame = STM_GetFrameCount(BattleData.BattleDrawStateObj);
// バトル描画の状態で振り分ける。
switch( STM_GetState(BattleData.BattleDrawStateObj) ) {
case BATTLE_DRAW_BATTLEIN: //バトル開始エフェクト
// バトル開始エフェクト処理
battle_draw_in_effect(frame);
break;
case BATTLE_DRAW_BATTLE: //バトル中
// 敵と背景を描画
battle_DrawEnemyAndBg();
break;
}
// ウィンドウのずれエフェクト
if( BattleData.PlayerDamageEffectCount > 0 ) {
// エフェクトのフレームをカウント
BattleData.PlayerDamageEffectCount--;
// ウィンドウのオフセットをずらす。
battle_WndOffset(-2,2);
} else {
// ウィンドウのオフセットを正位置に。
battle_WndOffset(0,0);
}
// 有効なウィンドウの描画
winmng_Draw();
// 上にかぶせる攻撃エフェクト
if( BattleData.AttackEffectCount > 0 ) {
// エフェクトのフレームをカウント
BattleData.AttackEffectCount--;
// 半透明の白枠
SetDrawBlendMode(DX_BLENDMODE_ALPHA,128); //アルファブレンド
DrawBox( 0,0,SCREEN_X,SCREEN_Y,BattleData.attackEffectColor, TRUE );
SetDrawBlendMode(DX_BLENDMODE_NOBLEND,255); //ノーマルブレンド
}
}
定義されているバトル用画像ファイル定義から敵の画像とバトル背景を読み込みます。
//----------------------------------------------------------------------
// (内部関数)バトル関連のデータを読み込み
//----------------------------------------------------------------------
static void battle_LoadData()
{
// 敵cgを読み込む
BattleData.imageEnemyCG = LoadGraph(g_EnemyFileDatas[BattleData.EnemyType].enemyCgName);
MACRO_ASSERT(BattleData.imageEnemyCG!=-1);
// 背景を読み込む
BattleData.imageBG = LoadGraph(g_EnemyFileDatas[BattleData.EnemyType].bgName);
MACRO_ASSERT(BattleData.imageBG!=-1);
}
敵の画像とバトル背景を破棄します。
//----------------------------------------------------------------------
// (内部関数)バトル関連のデータを破棄
//----------------------------------------------------------------------
static void battle_DeleteData()
{
// 敵cgを破棄
if( BattleData.imageEnemyCG != -1 ) {
DeleteGraph(BattleData.imageEnemyCG);
BattleData.imageEnemyCG = -1;
}
// 背景を破棄
if( BattleData.imageBG != -1 ) {
DeleteGraph(BattleData.imageBG);
BattleData.imageBG = -1;
}
}
敵の画像とバトル背景を描画します。
敵の座標は(0,0)で指定されていない場合は敵のCGサイズから中央よりやや下に表示される座標を決めて描画します。
指定されている場合はその座標を使います。
敵のダメージエフェクトとして、EnemyDamageEffectCountの期間中は、敵の画像を反転描画がします。
//----------------------------------------------------------------------
// (内部関数)敵と背景を描画
//----------------------------------------------------------------------
static void battle_DrawEnemyAndBg()
{
// 背景を描画
DrawGraph(0,0,BattleData.imageBG,TRUE); // 背景
// 敵の座標を得る。
int x = g_EnemyFileDatas[BattleData.EnemyType].x;
int y = g_EnemyFileDatas[BattleData.EnemyType].y;
// 座標が指定されていなかったら。
if( (x==0)&&(y==0) ) {
// 敵CGのサイズを得る。
int sizex,sizey;
GetGraphSize(BattleData.imageEnemyCG,&sizex,&sizey);
// 敵CGの表示場所を決めて描画。
#define OFFSET_Y (64)
x = (SCREEN_X-sizex)/2;//中央
y = (SCREEN_Y-sizey)*2/3;//中央より下。
}
// 敵のダメージエフェクト?
if( BattleData.EnemyDamageEffectCount>0 ) {
// エフェクトのフレームをカウント
BattleData.EnemyDamageEffectCount--;
// 敵を表示する。
SetDrawBlendMode(DX_BLENDMODE_INVSRC,255);//反転
DrawGraph(x,y,BattleData.imageEnemyCG,TRUE); // 敵
SetDrawBlendMode(DX_BLENDMODE_NOBLEND,255); //ノーマルブレンド
} else {
// 敵を表示する。
DrawGraph(x,y,BattleData.imageEnemyCG,TRUE); // 敵
}
}
バトル開始時のエフェクトです。
エフェクトの内容としては、移動用のマップ画像の上にバトル用背景の画像をランダムに表示する事で切り替わる事を表現しています。
表示する大きさはだんだんと大きくしています。それに加えて最初の小さいときは分かりづらいので半透明の白枠を表示します。
//----------------------------------------------------------------------
// (内部関数)バトル開始エフェクトの描画
//----------------------------------------------------------------------
static void battle_draw_in_effect(int frame)
{
// サイズはフレーム毎に大きくなる。
int size = frame;
// 透明度を決める。フレームが進むごとに透明化する。
int trans = (BATTLE_IN_TIME - frame);
if( trans hp); //HP
sprintf( s_MpStr," MP %d ", playerParam->mp); //MP
s_HpMpList[0] = s_HpStr;
s_HpMpList[1] = s_MpStr;
s_HpMpList[HPMP_LIST_MAX] = NULL;//ストッパ
// 全ウィンドウの色を変更する。
int color;
if( playerParam->hp > 0 ) {
color = GetColor(255,255,255);//白
} else {
color = GetColor(255,0,0);//赤
}
// 全ウィンドウ
for( int wn=0 ; wnp1,&intP1,&strP1,pscData);
// パラメータ2を解析して値を得る。
int intP2 = 0;
char *strP2 = NULL;
int bIntP2 = battle_GetPscParam(pscData->p2,&intP2,&strP2,pscData);
// パラメータの組み合わせで編集する。
if( bIntP1 && bIntP2 ) {
// 数値&数値
sprintf( buff, pscData->str, intP1, intP2 );
} else
if( bIntP1 && !bIntP2 ) {
// 数値&文字列
sprintf( buff, pscData->str, intP1, strP2 );
} else
if( !bIntP1 && bIntP2 ) {
// 文字列&数値
sprintf( buff, pscData->str, strP1, intP2 );
} else {
// 文字列&文字列
sprintf( buff, pscData->str, strP1, strP2 );
}
}
パラメータを解析して値を取り出します。
パラメータをPSC_GETPARAM_DATA()で値種別or数値を得ます。
PSC_GETPARAM_TYPE()でパラメータのタイプを判定。
PARAM_TYPE_NONは該当がないので0を返します。
PARAM_TYPE_PSCDATA_STRは文字列なので、bIntType=FALSEでbattle_GetPscDataStr(値種別)で文字列を得ます。
PARAM_TYPE_PSCDATA_INTは数値なので、bIntType=TRUEでbattle_GetPscDataInt(値種別)で値を得て数値引数に代入します。
PARAM_TYPE_FIXED_INTは数値なので、bIntType=TRUEでパラメータをPSC_GETPARAM_DATA()で取り出して数値引数に代入します。
戻り値としてbIntTypeを返します。
//----------------------------------------------------------------------
// (内部関数)PSC補助関数。パラメータを解析して値を得る。
//----------------------------------------------------------------------
static int battle_GetPscParam(int param,int *intData,char **strData,PSCData_t *pscData)
{
int bIntType = TRUE;//仮に数値であるとする。
// 値
int data = PSC_GETPARAM_DATA(param);
MACRO_ASSERT(data>=0);
// パラメータの種別ごとに処理
switch( PSC_GETPARAM_TYPE(param) ) {
case PARAM_TYPE_NON: //無効
if( NULL!=intData ) {//ポインタ有効?
// 0を返す。
*intData = 0;
}
break;
case PARAM_TYPE_PSCDATA_STR: //文字列データ
// 文字列データを得る。
MACRO_ASSERT(datastrP1!=NULL ) {
return BattleData.PSC_CallpscData->strP1;
}
// 無効なら空白
return "";
case PDS_STR0: //メッセージテーブル[0]
case PDS_STR1: //メッセージテーブル[1]
case PDS_STR2: //メッセージテーブル[2]
case PDS_STR3: //メッセージテーブル[3]
// メッセージテーブルの文字列を返す。
return s_msgTable[type-PDS_STR0];
}
// この値が返るのは何らかの間違い。
return NULL;
}
値種別(type)で指定された各々の値を持ち帰ります。
多いので細かく書きません。
//----------------------------------------------------------------------
// (内部関数)数値データの取得
//----------------------------------------------------------------------
static int battle_GetPscDataInt(int type)
{
// 種別別の値を持ち帰る。enumのPSC_DATA_INTと合わせてください。
switch( type ) {
case PDI_PLAYER_DEF: //主人公防御力
return BattleData.playerParam->def;
case PDI_PLAYER_ATK: //主人公攻撃力
return BattleData.playerParam->attack;
case PDI_ENEMY_DEF: //モンスター防御力
return BattleData.enemyParam.def;
case PDI_ENEMY_ATK: //モンスター攻撃力
return BattleData.enemyParam.attack;
case PDI_DAMAGE: //ダメージ値
return BattleData.damage;
case PDI_EXP: //経験値
return BattleData.enemyParam.expp;
case PDI_MONEY: //お金
return BattleData.enemyParam.money;
case PDI_MAGIC_ATK: //魔法の攻撃力
return BattleData.MagicAtk;
case PDI_CALL_P1: //PSC_Call数値パラメータ1
return BattleData.PSC_CallpscData->p1;
}
// 仮の値を返す。
return -1;
}
レベルアップに必要な経験値を計算する。
(レベル-1)の2.8乗にLEVEL_MAGIC_NOを書けた値が必要経験値とする。
//----------------------------------------------------------------------
// (内部関数)そのレベルになるのに必要な経験値を得る。
// 実際のゲームだと微調整のために、この値をテーブル化する事が多いです。
//----------------------------------------------------------------------
static int battle_GetLevelupExpp(int level)
{
// レベル1は経験値不要
if( level == 1 ) {
return 0;
} else {
// 経験値はマジックナンバーとlevelのn乗(適度になるように調整)
#define LEVEL_MAGIC_NO 6
level -= 1; //補正
int expp = (int)pow((double)level,2.8) * LEVEL_MAGIC_NO;
return expp;
}
}
指定されたレベルで得られるパラメータを計算する関数。
minにレベル1、maxにLEVEL_MAXの時点のパラメータ値を設定すれば線形的に上昇するパラメータ値が得られる。
//----------------------------------------------------------------------
// レベルに合わせてパラメータを調整
//----------------------------------------------------------------------
static int battle_LevelScaler(int level,int min,int max)
{
// 最大レベルならmax値を返す。
if( LEVEL_MAX <= level ) {
return max;
} else {
// 値の差分
int diff = (max - min);
// 現在レベルから最大レベルに向けて段階を追って最大値に近づくように計算
// 本来は(level-1) / LEVEL_MAX * diff + minと言う式だが割り算の切り捨てを考慮して。
int value = ((level-1) * diff) / LEVEL_MAX;
// 乱数でゆらぎを作る。90%~110%。
return ( value * (90 + GetRand(20)) ) / 100 + min;
}
}
次回は、PSC関数の説明です