今回もどうかお知恵を拝借願いたくお願い申し上げます。
現在、文字だけで構成されたダンジョンゲームを作っていまして、
マップ上を敵が徘徊し、当たるとバトルに移行する仕組みになっています。
ただ、敵が急に現れるといった仕組みがあった方がオモシロいと、
移動してきた敵コマが隠れられるブロック『森』を
マップ上に作ろうと思いました。
森森森
△ 森森←敵 (敵が森ブロックに入ると)
↓
森森森 (森の中に姿が隠れて見えなくなる。)
△ 森森 ((森の方が優先的に描画される))
しかしいざ実装しようとしてみても
森森森
△ 森森←敵 (敵が森ブロックに入ると)
↓
森森森
△ 森[敵]
森の上に敵が描画されてしまいます。
どうか森ブロックの方を敵より優先的に描画できる方法を教えていただけませんでしょうか?
ちなみにソースコードはこちらです
3つのファイルに分割おり「main.cpp」がマップ描画に関わる部分になります。
また、特にマップの表示に関わる部分は「main.cpp」の215行目からになります。
マップの「0」が何もない部分
「1」が障害物
「2」が問題の『森』ブロック になります。
また敵は「WF」=オオカミ
「DG」=ドラゴン
としています。
↓ 「All.h」
/*--ヘッダ インクルード-----------------------------------------*/
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
/*--定数---------------------------------------------------------*/
#define dx_max 16
#define dy_max 12
#define TEKI_MAX 4
/*--ゲーム状態遷移-----------------------------------------------*/
typedef enum Scene{
S_TITLE,
S_GAME,
S_BATTLE,
S_OVER,
S_CLEAR,
S_END
}scene;
/*--構造体型定義------------------------------------------------*/
typedef struct Model{
char *n;
int ux, uy; //現座標
int pre_x,pre_y; //前座標
int encount_flg; //当たった敵の判定
int event_flg; //イベントフラグ
}model;
// battle.cppから
typedef struct Character
{
int lp; // 体力
int str; //攻撃力
int def; //防御力
int speed; //素早さ
int state; //コマンド状態
}character;
/*--関数プロトタイプ--------------------------------------------*/
int keyCtrl(model *); //キー入力
void view_dungeon(model *, model *, int[][dx_max]); //表示
int hitTest(model *, int[][dx_max],int); //壁との当たり判定
void title(void);
void g_main(void);
void g_battle(void);
void g_over(void);
void g_clear(void);
void my_srand(int); //シード値セット
long xor128(void); //乱数生成
void e_Ctrl(model *); //敵コントロール
//battle.cppから
void set_parameter();
int strdef();
void attack();
void attackofcharacter();
void firstattacker();
int isdead();
void isdeadmessage();
int battleMain();
/*--グローバル変数----------------------------------------------*/
extern int dungeon[dy_max][dx_max];
extern scene g_Sequence;
extern model init_jiki;
extern model jiki;
extern model init_teki[];
extern model teki[TEKI_MAX];
extern int seed; //乱数のシード値
extern int e_flg;
/*--ヘッダ インクルード-----------------------------------------*/
#include"all.h"
/*--グローバル変数----------------------------------------------*/
int init_dungeon[dy_max][dx_max] = {
//0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1},
{ 1, 0, 2, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 0, 1},
{ 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 2, 2, 1},
{ 1, 0, 2, 2, 2, 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 1},
{ 1, 0, 2, 0, 0, 2, 0, 2, 2, 0, 0, 2, 0, 2, 0, 1},
{ 1, 0, 2, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 0, 1},
{ 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1},
{ 1, 0, 2, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 1},
{ 1, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1},
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
int dungeon[dy_max][dx_max];
scene g_Sequence = S_TITLE;
model init_jiki = { "jiki", 1,1,0,0,0};
model jiki;
model init_teki[] ={ //構造体の配列化
{"Walf", 1,7,0,0,0,0},
{"Walf", 3,5,0,0,0,0},
{"Walf", 8,1,0,0,0,0},
{"Dragon", 9,9,0,0,0,0},
};
model teki[TEKI_MAX];
int seed; //乱数のシード値
int e_flg=0;
/*--エントリーポイント------------------------------------------*/
void main(void)
{
for(;;){ //ゲームループ
switch(g_Sequence){ //状態遷移
case S_TITLE: title();
break;
case S_GAME: g_main();
break;
case S_BATTLE: g_battle();
break;
case S_OVER: g_over();
break;
case S_CLEAR: g_clear();
break;
default: break;
}
//終了
if(g_Sequence==S_END){ //if(g_Sequenceの == を = だけで記述したら、ゲームが始まった瞬間 S_END へと向かいました)
printf("ゲームを終了します\n Please press any key. \n");
getch();
break;
}
}
}
/*--関数本体定義-------------------------------------------------*/
//タイトル画面
void title(void){
int i,s_cnt = 0;
system("cls");
printf("TITLE\n");
printf(" Push Any Key \n");
//シード値カウント
s_cnt++;
if(s_cnt>256){s_cnt=0;} //256越えたらゼロクリア
if(kbhit()){
//データ初期化
my_srand(s_cnt); //シード値セット
jiki = init_jiki; //自機初期化
for(i=0; i<TEKI_MAX; i++){
teki[i]=init_teki[i]; //敵の初期値を一括代入で初期化
}//これ参考
//ゲーム本体へ
g_Sequence = S_GAME;
}
}
void g_main(void){
int btn=0;
/*--入力-*/
btn =keyCtrl(&jiki); //player は model型の変数なので、参照には「&」をつける
/*--処理--*/
if(hitTest(&jiki, dungeon,1)){ //壁当たり判定
//壁なら前座標に戻す
jiki.ux = jiki.pre_x;
jiki.uy = jiki.pre_y;
}
if(hitTest(&jiki, dungeon, 3)){
teki->ux = teki->pre_x;
teki->uy = teki->pre_y;
jiki.encount_flg = 1;
teki->encount_flg = 1;
g_Sequence = S_BATTLE;
}
if(hitTest(&jiki, dungeon, 4)){
teki->ux = teki->pre_x;
teki->uy = teki->pre_y;
jiki.encount_flg = 2;
teki->encount_flg = 1;
g_Sequence = S_BATTLE;
}
//敵が動き回る
e_Ctrl(teki);
//ゲームオーバー
if(btn==2){g_Sequence = S_END;} //ゲーム終了(btn==2はesc , keyCtrl()で紐づけ)
/*--表示--*/
view_dungeon(&jiki, teki, dungeon);
}
void g_battle(void){
int i;
system("cls");
battleMain();
printf("Push anykey");
getch();
jiki.ux = jiki.pre_x;
jiki.uy = jiki.pre_y;
}
void g_over(void){
system("cls");
printf("GAME_OVER\n");
printf("Push AnyKey");
getch();
g_Sequence = S_TITLE; //タイトルへ
}
void g_clear(void){
system("cls");
printf("GAME_CLEAR\n ! congratulations ! \n Push anykey");
getch();
g_Sequence = S_TITLE;
}
//--------------------------------------------------------------------
//キー入力
int keyCtrl(model *us)
{
int key; //キー入力
//前情報の取得
us->pre_x=us->ux;
us->pre_y=us->uy;
//キー入力
//if(kbhit()){
key = getch();
if(key == 56 && us->uy>0){us->uy--;} //8↑
if(key == 50 && us->uy<(dy_max-1)){us->uy++;} //2↓
if(key == 52 && us->ux>0){us->ux--;} //4←
if(key == 54 && us->ux<(dx_max-1)){us->ux++;} //6→
if(key == 27){return 2;} //esc:終了
//}
return 0;
}
//当たり判定////////////////////////////////////////////////////
//壁との当たり判定
int hitTest(model *us, int d_dat[][dx_max], int id){
if(d_dat[us->uy][us->ux]==id){
return 1; //当たっている
}else{
return 0; //当たっていない
}
}
//表示//////////////////////////////////////////////////////////
//マップ表示
void view_dungeon(model *usr, model *teki, int d_dat[][dx_max])
{
int i, j, k; //カウンタ用
for(i=0;i<dy_max;i++){//y
for(j=0;j<dx_max;j++){ //x
dungeon[i][j] = init_dungeon[i][j]; //ダンジョンデータを初期化に
for(k=0; k<TEKI_MAX; k++){
if(j == (teki + k)->ux && i == (teki+k)->uy){
if(*(teki+k)->n=='D'){dungeon[i][j] = 3;} //ドラゴンを書き込む
if(*(teki+k)->n=='W'){dungeon[i][j] = 4;} //オオカミの位置を書きこむ
//(enemy+k)は「*」をつける前に()で囲むこと(kは配列を動かす参照にされている)※教科書p189
}
}
}
}
system("cls");
for(i=0; i<dy_max; i++){//y軸
for(j=0; j<dx_max; j++){//x軸
if(j == usr->ux && i == usr->uy && e_flg==0 ){printf("人");}
else if(d_dat[i][j] == 0/* && e_flg==0*/){printf(" ");}//床
else if(d_dat[i][j] == 1){printf("山");}//山
else if(d_dat[i][j] == 2){printf("森");}//森
else if(d_dat[i][j] == 3){printf("DR");}//ドラゴン
else if((d_dat[i][j] == 4)&&(d_dat[i][j] != 2)){printf("WF");}//オオカミ
//else if(d_dat[i][j] == 2 || d_dat[i][j] || d_dat[i][j] == 4){printf("森");}
}
printf("\n");//改行
}
}
//乱数/////////////////////////////////////////////////////////////
void my_srand(int s)
{
seed = s;
}
long xor128(void)
{
long t;
static long x=123456789, y=362436069, z=521288629,w;
w^= (long)seed*1812433253;
t=(x^(x<<11));
x=y;y=z;z=w;
return( w=(w^(w>>19))^(t^(t>>8)) );
}
//敵コントロール///////////////////////////////////////////////////
void e_Ctrl(model *en)
{
int k, mov_flg;
for(k=0; k<TEKI_MAX; k++){
//前座標の取得
(en+k)->pre_x = (en+k)->ux;
(en+k)->pre_y = (en+k)->uy;
mov_flg = xor128()%4; //0-3
switch(mov_flg){
case 0: //↑
(en+k)->uy--;
break;
case 1: //↓
(en+k)->uy++;
break;
case 2: //←
(en+k)->ux--;
break;
case 3: //→
(en+k)->ux++;
break;
}
//更新座標が壁に当たっていたら戻す
if(hitTest((en+k), init_dungeon, 1))
{
(en+k)->ux = (en+k)->pre_x;
(en+k)->uy = (en+k)->pre_y;
}
//
if((en+k)->ux<1){(en+k)->ux=1;}
if((en+k)->ux>15){(en+k)->ux=15;}
if((en+k)->uy<1){(en+k)->uy=1;}
if((en+k)->uy>12){(en+k)->uy=12;}
}
}
#include"all.h"
/*
typedef struct
{
int lp; // 体力
int str; //攻撃力
int def; //防御力
int speed; //素早さ
int state; //コマンド状態
}character;
*/
void set_parameter(character* param, int lp, int str, int def, int speed, int state)
{
param->lp = lp;
param->str = str;
param->def = def;
param->speed = speed;
param->state = 0;
}
//プレイヤーの攻撃力より敵の防御力が低いときにダメージ
int strdef(int player_str, int enemy_def)
{
if(player_str < enemy_def)
{
return 0;
}else{
return(player_str - enemy_def);
}
}
//ダメージ処理 プレイヤー→敵
void attack(character* player, character* enemy)
{
if(player->state == 0)
{
enemy->lp -= strdef(player->str, enemy->def);
}else{
//防御時
enemy->lp -= strdef(player->str,(enemy->def*2));
}
}
void attackofcharacter(character* attacker, character* defender, int command)
{
if(command % 2 == 0)
{
attacker->state = 0;
attack(attacker, defender);
}
if(command % 2 == 1)
{
attacker->state = 1;
}
}
void firstattacker(character* attacker, character* defender, int command)
{
//自分の素早さ > 相手の素早さのとき
if(attacker->speed > defender->speed)
{
printf("あなたの先攻\n");
attackofcharacter(attacker, defender, command);
attackofcharacter(defender, attacker, rand());
}else{
printf("敵の先攻\n");
attackofcharacter(defender, attacker, rand());
attackofcharacter(attacker, defender, command);
}
}
//死亡かどうかの判定
int isdead(int lp)
{
if(lp < 1)
{
return 1;
}else{
return 0;
}
}
//死亡時のメッセージの表示
void isdeadmessage(character player, character enemy)
{
//プレイヤーの死亡判定
if(isdead(player.lp) == 1)
{
printf("あなたはヤラレタ\n");
}
//敵の死亡判定
if(isdead(enemy.lp) == 1)
{
printf("敵をやっつけた!\n");
}
}
int battleMain()
{
character player;
character enemy;
int command = 0;
set_parameter(&player, 100, 30, 15, 30, 0);
int i;
system("cls");
switch(jiki.encount_flg){
case 1:
printf("ボスの『ドラゴン』が現れた!\n");
getch();
printf("こいつを倒せば終わりだ!!\n");
break;
case 2:
printf("『オオカミ』が現れた!\n");
break;
}
switch(jiki.encount_flg){
{
case 1: set_parameter(&enemy, 150, 30, 15, 20, 0);
break;
case 2: set_parameter(&enemy, 60, 30, 15, 40, 0);
break;
default: break;
}
}
while(1)
{
if(isdead(player.lp) == 1 || isdead(enemy.lp) == 1)
{
isdeadmessage(player, enemy);
break;
}
printf("プレイヤーの残り体力: 『 %d 』, 敵の残り体力:『 %d 』\n", player.lp, enemy.lp);
scanf("%d", &command);
firstattacker(&player, &enemy,command);
if(player.lp<1){g_Sequence = S_OVER; break;}
if(enemy.lp<1){
switch(jiki.encount_flg){
case 1: g_Sequence = S_CLEAR;
break;
case 2: g_Sequence = S_GAME;
break;
}
for(i=0; i<TEKI_MAX; i++)
{
if(teki[i].encount_flg=1){teki[i] = init_teki[i];}
//if((teki[i].ux==jiki.ux)&&(teki[i].uy==jiki.uy)){teki[i]=init_teki[i];}
}
}
}
return 1;
}