Quantcast
Channel: 初心者タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 21081

ウィザードリィのような疑似3DダンジョンをC言語初心者のおっさんが作ってみた(マップを表示した)

$
0
0

これは、ゲーム作りはおろかC言語初心者である40過ぎのおっさんがウィザードリィーのような疑似3D迷路を作ってみたいと思い試行錯誤を繰り返し奮闘した記録である。
今回Qiitaで執筆に至った経緯はよく「プログラミングの上達はアウトプットが云々」とブログ等で見かけるのでそれが本当かどうか確かめる意味も込めてやってみようと思った次第である。

私が使ったもの

  • Windows 10のパソコン
  • VisualStudio2019
  • C言語
  • Dxライブラリ
  • 高機能ドット絵エディタ EDGE

参考にしたもの

14歳からはじめるC言語わくわくゲームプログラミング教室

EKVvf9YVAAAYzgz.jpg
この書物はゲーム作りはおろかプログラミング素人の私にとって神のような書物である。
学習にはVisual Studio 2013を使っているのだけれども、同じVisual Studioだし、なんとかなるだろうと思った。そしてなんとかなった。
前半でC言語を教えてもらい、その後パズルゲーム、横スクロールゲーム、そして今回の目標である疑似3D迷路の作り方を教えてくれた。
この場をお借りして著者に感謝申し上げたい。
そしてこの書物をアマゾンで買ってくれたかーちゃんにも感謝申し上げたい。

ゲエム道館館長の動画

ウィザードリィを小一時間で作ってみた【プログラミング実況】Programming Wizardry

この動画と出会わなければゲームを自分で作ってみようと思うことはなかったであろう。私はすでにこの動画を数十回繰り返し再生している。
特に参考になった部分は先に述べた「14歳からはじめる…」ではふれられていなかった1マス毎の上下左右の壁の考え方やドアシステムの箇所である。
館長にも感謝申し上げたい。
2020年2月現在、館長はweb dbpressでJava scriptでのゲーム作りを執筆されるとのことなので、必読書となるのは間違い無いであろう。

成果物

先に現在まででどのようなものが出来上がったのか紹介させていただく。

作っていった流れ

これからソースコードを掲載してみようと思うがなにせ当方素人なのでツッコミどころは満載だろうがご容赦頂きたい。

必要であろう変数とか定数?、関数などを定義する

gamemap.h
#define CHIPSIZE 20 //2Dの1マスの大きさ
#define MAP_WIDTH 100 //マップの横幅
#define MAP_HEIGHT 100 //マップの縦幅
#define WALL_THICKNESS 3 //2Dマップ用の壁の厚さ
#define MOVERATE 8 //移動の制限のための値
#define DEPTH 3 //3D用の見える奥行き
#define START_2DX 800 //2Dを実際描画するためのx座標
externcharg_mapdata[MAP_HEIGHT][MAP_WIDTH];externcharg_doordata[MAP_HEIGHT][MAP_WIDTH];externcharg_s_doordata[MAP_HEIGHT][MAP_WIDTH];externintg_margeMapData[MAP_HEIGHT][MAP_WIDTH][4];externintg_trapData[MAP_HEIGHT][MAP_WIDTH];enumclassPlayMode{PGM_EVENT,PGM_EXPLORE};structStageData{intmapwidth,mapheight;intstagenum;PlayModeplaymode;};externStageDatastageData;structPlayerData{unsignedintx,y,movecounter,direction,max_hp,hp,deadtime;BOOLdeadflag;};externPlayerDataplayerData;voidGameMain();voidInitMap();voidInitPlayer();voidDraw2DMap();voidDraw3DMap();voidDrawPlayer();voidCheckCurrent();voidShowEvent();voidDeadEvent();

次にプレイヤーの座標等の初期化処理を行う

gamemap.cpp
voidInitPlayer(){playerData.x=0;//プレイヤーの初期位置XplayerData.y=19;//プレイヤーの初期位置YplayerData.direction=(int)Direction::NORTH;//プレイヤーの初期の向きplayerData.deadflag=FALSE;//プレイヤーの死んでるかどうかフラグplayerData.max_hp=GetRand(20)+9;//プレイヤーの最大HP(当分使わない)playerData.hp=playerData.max_hp;//プレイヤーの現在のHPplayerData.deadtime=0;//プレイヤーの死んだ回数stageData.playmode=PlayMode::PGM_EXPLORE;//現在のゲームモード(冒険中)}

2Dで作ってみる

「14歳からはじめる…」でも最初は疑似3Dではなく2Dでマップ作成していたのでそれに合わせて2Dマップを描画させてみた。
書籍では壁のマス、通路のマスを0,1で表現していたのだが、ウィザードリィ風にする場合は1マス毎に上下左右の方向があるため少し工夫してみた。

1マス毎の壁のパターン作成

floor.h
externintg_wall[][4];
floor.cpp
intg_wall[][4]={//上、左、下、右{0,0,0,0},//0 無、無、無、無{1,1,1,1},//1 上、左、下、右{1,0,0,0},//2 上、無、無、無{1,1,0,0},//3 上、左、無、無 {1,0,1,0},//4 上、無、下、無{1,0,0,1},//5 上、無、無、右{1,1,1,0},//6 上、左、下、無 {1,0,1,1},//7 上、無、下、右{1,1,0,1},//8 上、左、無、右{0,1,0,0},//9 無、左、無、無{0,1,1,0},//: 無、左、下、無{0,1,0,1},//; 無、左、無、右{0,1,1,1},//< 無、下、左、右{0,0,1,0},//= 無、無、下、無{0,0,1,1},//> 無、無、下、右{0,0,0,1},//? 無、無、無、右};

上記の様にマス目ごとに壁のパターンを定義し、マップデータの文字、0~?に対応する配列を作った

次に読み込み用のマップデータの作成を行った。

stage1.txt(Wizardry#1の壁データ)
6711113251;867673511
67624790?3?;1167:>35
111;67:=>9?;886767:>
325<32588<;;;;376735
90?190?;;3?;;;;867:>
:=>8:=>;;9?;;;;;6711
164?186>;9>;;;;;6735
32595;35<95;;;;;88:>
:=>:><:>19?;;;;;<;11
6444444440?<<<<<1<67
6444444479=444444447
344244247<8344442447
;35;37<653?;1165;345
;9?;;325;9?;111<;;8;
;9?;;:=>;9?;1135;;;;
;9><:222?9?;119?;;;;
;;3259==>9?;11:><;;;
;;:=>;3259?;11116>;;
;:444>:=>9?:444444><
:44444447:?644444447
d_stage1.txt(Wizardry#1のドアデータ)
02=?=?000?9?:>9?90==
=?602?900000220=0022
29209000=0009?959?90
000=0009200000900=00
00?190000000000?95:=
00020000000000009022
?=00200000000000:>90
0200?;90=000000022==
00000=00200000000022
00000200000=0=0=?=02
0000000000020202020?
00000000?90000000000
000000=00000?=900000
0000002000002?==0000
0000000000002?320000
000=000000002?909000
0002000000002?:=0000
00000000000029989000
00000=0=00000000000=
00000002000900000000
sd_stage1.txt(Wizardry#1のシークレットドアデータ)
000?0?000000==0000==
0?9000000000220=0022
09009000=00000020000
00000009000000000000
000000000000000000==
00000000000000009022
?0002000000000000000
000000000000000000==
00000000000000000022
00000000000000000000
0000000000000000000?
00000000000000000000
000000000000?=000000
0000000000002?000000
00000000000020000000
00000000000020009000
00000000000020000000
00000000000029990000
00000000000000000000
00000000000000000000

これらのデータを読み込みマップを作ってみた。

gamemap.cpp
voidInitMap(){charbuf[256];//マップ壁データ sprintf_s(buf,256,"media\\stage%d.txt",stage_num);intfh=FileRead_open(buf);intmap_y=0;while(FileRead_eof(fh)==0){FileRead_gets(g_mapdata[map_y],MAP_WIDTH,fh);map_y++;}FileRead_close(fh);stageData.mapwidth=(int)strlen(g_mapdata[0]);stageData.mapheight=map_y;//マップドアデータsprintf_s(buf,256,"media\\d_stage%d.txt",stage_num);fh=FileRead_open(buf);map_y=0;while(FileRead_eof(fh)==0){FileRead_gets(g_doordata[map_y],MAP_WIDTH,fh);map_y++;}FileRead_close(fh);//マップ隠しドアデータsprintf_s(buf,256,"media\\sd_stage%d.txt",stage_num);fh=FileRead_open(buf);map_y=0;while(FileRead_eof(fh)==0){FileRead_gets(g_s_doordata[map_y],MAP_WIDTH,fh);map_y++;}FileRead_close(fh);//それぞれのデータを1つの変数 g_margeMapData にまとめるfor(inty=0;y<stageData.mapheight;y++){for(intx=0;x<stageData.mapwidth;x++){intwall=g_mapdata[y][x]-'0';intdoor=g_doordata[y][x]-'0';ints_door=g_s_doordata[y][x]-'0';//X,Y座標に加え上下左右のデータも入れていくfor(inti=0;i<4;i++){intmarge_wall=g_wall[wall][i]+g_door[door][i]+g_door[s_door][i];g_margeMapData[y][x][i]=marge_wall;}}}}

似たような処理を3回も書いてるのでもっとキレイに出来そうな気もするのだが、今回始めてのC言語プログラミングだから気にしないこととする。
上記の処理でg_margeMapDataに座標と、その座標に対しての「無、壁、ドア、シークレットドア(0,1,2,3)」のデータを保持させた。

そのデータを用いて2Dマップを描画してみる

gamemap.cpp
voidDraw2DMap(){for(inty=0;y<stageData.mapheight;y++){for(intx=0;x<stageData.mapwidth;x++){for(inti=0;i<(int)Direction::DIRECTION_MAX;i++){if(g_margeMapData[y][x][i]>=1){unsignedintCr=0;switch(g_margeMapData[y][x][i]){case1://壁のときは赤色Cr=GetColor(255,0,0);break;case2://ドアのときは緑色Cr=GetColor(0,200,0);break;case3://シークレットドアのときは黄色Cr=GetColor(255,255,0);break;}intwall_thickness;switch(i){case0:case1:wall_thickness=WALL_THICKNESS;break;case2:case3:wall_thickness=WALL_THICKNESS*-1;}if(i%2==0){//横線DrawBox(x*CHIPSIZE+START_2DX,y*CHIPSIZE+(CHIPSIZE*i/2),x*CHIPSIZE+CHIPSIZE+START_2DX,y*CHIPSIZE+(CHIPSIZE*i/2)+wall_thickness,Cr,TRUE);}else{//縦線DrawBox(x*CHIPSIZE+(CHIPSIZE*(i-1)/2)+START_2DX,y*CHIPSIZE,x*CHIPSIZE+(CHIPSIZE*(i-1)/2)+wall_thickness+START_2DX,y*CHIPSIZE+CHIPSIZE,Cr,TRUE);}}}}}//player自身の描画DrawBox(playerData.x*CHIPSIZE+3+START_2DX,playerData.y*CHIPSIZE+3,playerData.x*CHIPSIZE+CHIPSIZE-3+START_2DX,playerData.y*CHIPSIZE+CHIPSIZE-3,GetColor(255,255,255),TRUE);//player方向の描画DrawBox((playerData.x+g_mv[playerData.direction][0])*CHIPSIZE+8+START_2DX,(playerData.y+g_mv[playerData.direction][1])*CHIPSIZE+8,(playerData.x+g_mv[playerData.direction][0])*CHIPSIZE+CHIPSIZE-8+START_2DX,(playerData.y+g_mv[playerData.direction][1])*CHIPSIZE+CHIPSIZE-8,GetColor(0,210,255),TRUE);}

これをメイン関数で呼び出すと下記のような2D画像ができる。

2d.png

続いて移動処理を作った流れを書いていこうかと思ったのだが、疲れたので次の機会に書いてみるかもしれない。

拙い私のソースコード

とりあえず3D描画含めすべてのソースは下記の通りである。
自信の無いソースコードを晒すという行為は不特定多数の方々に恥部を見られるような気持ちである:cherries:

画像を読み込むヘッダー

loading.h
#ifndef __LOADING_H__
#define __LOADING_H__
#include <DxLib.h>
#define LOCATION 12
enumclassDirection{NORTH,WEST,SOUTH,EAST,DIRECTION_MAX};structImageHandles{intwalls[LOCATION*4];intdoors[LOCATION*4];intdark[4];intchara;intfloor;inttitle;intwindow;intwindow_l;intparson;};externImageHandlesg_imagehandles;BOOLLoadGameImage();#endif

実際に画像を読み込む処理

loading.cpp
#include "loading.h"
ImageHandlesg_imagehandles;BOOLLoadGameImage(){for(inti=0;i<LOCATION*4;i++){g_imagehandles.walls[i]=-1;g_imagehandles.doors[i]=-1;}for(inti=0;i<4;i++){g_imagehandles.dark[i]=-1;}//左手前 0//0if((g_imagehandles.walls[0*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\0_n.png"))==-1)returnFALSE;//3if((g_imagehandles.walls[0*4+(int)Direction::EAST]=LoadGraph("media\\wall\\0_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[0*4+(int)Direction::EAST]=LoadGraph("media\\wall\\0_door_e.png"))==-1)returnFALSE;//中手前 1//4if((g_imagehandles.walls[1*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\1_n.png"))==-1)returnFALSE;if((g_imagehandles.doors[1*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\1_door_n.png"))==-1)returnFALSE;//5if((g_imagehandles.walls[1*4+(int)Direction::WEST]=LoadGraph("media\\wall\\1_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[1*4+(int)Direction::WEST]=LoadGraph("media\\wall\\1_door_w.png"))==-1)returnFALSE;//7if((g_imagehandles.walls[1*4+(int)Direction::EAST]=LoadGraph("media\\wall\\1_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[1*4+(int)Direction::EAST]=LoadGraph("media\\wall\\1_door_e.png"))==-1)returnFALSE;//右手前 2//8if((g_imagehandles.walls[2*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\2_n.png"))==-1)returnFALSE;//9if((g_imagehandles.walls[2*4+(int)Direction::WEST]=LoadGraph("media\\wall\\2_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[2*4+(int)Direction::WEST]=LoadGraph("media\\wall\\2_door_w.png"))==-1)returnFALSE;//左中央 3//12if((g_imagehandles.walls[3*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\3_n.png"))==-1)returnFALSE;if((g_imagehandles.doors[3*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\3_door_n.png"))==-1)returnFALSE;//14if((g_imagehandles.walls[3*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\3_s.png"))==-1)returnFALSE;//15if((g_imagehandles.walls[3*4+(int)Direction::EAST]=LoadGraph("media\\wall\\3_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[3*4+(int)Direction::EAST]=LoadGraph("media\\wall\\3_door_e.png"))==-1)returnFALSE;//中中央 4//16if((g_imagehandles.walls[4*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\4_n.png"))==-1)returnFALSE;if((g_imagehandles.doors[4*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\4_door_n.png"))==-1)returnFALSE;//17if((g_imagehandles.walls[4*4+(int)Direction::WEST]=LoadGraph("media\\wall\\4_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[4*4+(int)Direction::WEST]=LoadGraph("media\\wall\\4_door_w.png"))==-1)returnFALSE;//18if((g_imagehandles.walls[4*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\4_s.png"))==-1)returnFALSE;if((g_imagehandles.doors[4*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\4_door_s.png"))==-1)returnFALSE;//19if((g_imagehandles.walls[4*4+(int)Direction::EAST]=LoadGraph("media\\wall\\4_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[4*4+(int)Direction::EAST]=LoadGraph("media\\wall\\4_door_e.png"))==-1)returnFALSE;//右中央 5//20if((g_imagehandles.walls[5*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\5_n.png"))==-1)returnFALSE;if((g_imagehandles.doors[5*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\5_door_n.png"))==-1)returnFALSE;//21if((g_imagehandles.walls[5*4+(int)Direction::WEST]=LoadGraph("media\\wall\\5_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[5*4+(int)Direction::WEST]=LoadGraph("media\\wall\\5_door_w.png"))==-1)returnFALSE;//22if((g_imagehandles.walls[5*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\5_s.png"))==-1)returnFALSE;//左奥 6//24if((g_imagehandles.walls[6*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\6_n.png"))==-1)returnFALSE;if((g_imagehandles.doors[6*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\6_door_n.png"))==-1)returnFALSE;//26if((g_imagehandles.walls[6*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\6_s.png"))==-1)returnFALSE;if((g_imagehandles.doors[6*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\6_door_s.png"))==-1)returnFALSE;//27if((g_imagehandles.walls[6*4+(int)Direction::EAST]=LoadGraph("media\\wall\\6_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[6*4+(int)Direction::EAST]=LoadGraph("media\\wall\\6_door_e.png"))==-1)returnFALSE;//中奥 7//28if((g_imagehandles.walls[7*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\7_n.png"))==-1)returnFALSE;if((g_imagehandles.doors[7*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\7_door_n.png"))==-1)returnFALSE;//29if((g_imagehandles.walls[7*4+(int)Direction::WEST]=LoadGraph("media\\wall\\7_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[7*4+(int)Direction::WEST]=LoadGraph("media\\wall\\7_door_w.png"))==-1)returnFALSE;//30if((g_imagehandles.walls[7*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\7_s.png"))==-1)returnFALSE;if((g_imagehandles.doors[7*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\7_door_s.png"))==-1)returnFALSE;//31if((g_imagehandles.walls[7*4+(int)Direction::EAST]=LoadGraph("media\\wall\\7_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[7*4+(int)Direction::EAST]=LoadGraph("media\\wall\\7_door_e.png"))==-1)returnFALSE;//右奥 8//32 if((g_imagehandles.walls[8*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\8_n.png"))==-1)returnFALSE;if((g_imagehandles.doors[8*4+(int)Direction::NORTH]=LoadGraph("media\\wall\\8_door_n.png"))==-1)returnFALSE;//33if((g_imagehandles.walls[8*4+(int)Direction::WEST]=LoadGraph("media\\wall\\8_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[8*4+(int)Direction::WEST]=LoadGraph("media\\wall\\8_door_w.png"))==-1)returnFALSE;//34if((g_imagehandles.walls[8*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\8_s.png"))==-1)returnFALSE;if((g_imagehandles.doors[8*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\8_door_s.png"))==-1)returnFALSE;//左最奥 9//38if((g_imagehandles.walls[9*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\9_s.png"))==-1)returnFALSE;if((g_imagehandles.doors[9*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\9_door_s.png"))==-1)returnFALSE;//39if((g_imagehandles.walls[9*4+(int)Direction::EAST]=LoadGraph("media\\wall\\9_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[9*4+(int)Direction::EAST]=LoadGraph("media\\wall\\9_door_e.png"))==-1)returnFALSE;//中最奥 10//41if((g_imagehandles.walls[10*4+(int)Direction::WEST]=LoadGraph("media\\wall\\10_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[10*4+(int)Direction::WEST]=LoadGraph("media\\wall\\10_door_w.png"))==-1)returnFALSE;//42if((g_imagehandles.walls[10*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\10_s.png"))==-1)returnFALSE;if((g_imagehandles.doors[10*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\10_door_s.png"))==-1)returnFALSE;//43if((g_imagehandles.walls[10*4+(int)Direction::EAST]=LoadGraph("media\\wall\\10_e.png"))==-1)returnFALSE;if((g_imagehandles.doors[10*4+(int)Direction::EAST]=LoadGraph("media\\wall\\10_door_e.png"))==-1)returnFALSE;//右最奥 11//45if((g_imagehandles.walls[11*4+(int)Direction::WEST]=LoadGraph("media\\wall\\11_w.png"))==-1)returnFALSE;if((g_imagehandles.doors[11*4+(int)Direction::WEST]=LoadGraph("media\\wall\\11_door_w.png"))==-1)returnFALSE;//46if((g_imagehandles.walls[11*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\11_s.png"))==-1)returnFALSE;if((g_imagehandles.doors[11*4+(int)Direction::SOUTH]=LoadGraph("media\\wall\\11_door_s.png"))==-1)returnFALSE;//床if((g_imagehandles.floor=LoadGraph("media\\wall\\floor_2.png"))==-1)returnFALSE;if((g_imagehandles.dark[0]=LoadGraph("media\\wall\\0_d_n.png"))==-1)returnFALSE;if((g_imagehandles.dark[1]=LoadGraph("media\\wall\\1_d_n.png"))==-1)returnFALSE;if((g_imagehandles.dark[2]=LoadGraph("media\\wall\\4_d_n.png"))==-1)returnFALSE;if((g_imagehandles.dark[3]=LoadGraph("media\\wall\\7_d_n.png"))==-1)returnFALSE;//ウィンドウif((g_imagehandles.window=LoadGraph("media\\wall\\mess_m.png"))==-1)returnFALSE;if((g_imagehandles.window_l=LoadGraph("media\\wall\\mess_l.png"))==-1)returnFALSE;if((g_imagehandles.parson=LoadGraph("media\\parson\\parson.png"))==-1)returnFALSE;returnTRUE;}

ゲーム全体の処理のヘッダー

main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <DxLib.h>
#include "loading.h"
#include "gamemap.h"
#include "floor.h"
externintg_lasttime;externfloatg_frametime;externintg_timerstart;enumclassGameState{GAME_TITLE,GAME_MAIN,GAME_CLEAR,GAME_OVER};externGameStategamestate;externBOOLg_akey_prev;externintg_middlefont;externintg_smallfont;externintg_largefont;voidDrawGameTitle();voidDrawGameMain();voidDrawGameClear();voidDrawGameOver();BOOLIsAkeyTrigger(intkey);#endif

ゲーム全体の処理の中身

main.cpp
#include "main.h"
GameStategamestate=GameState::GAME_TITLE;intg_lasttime=0;floatg_frametime=0;intg_timerstart;BOOLg_akey_prev;intg_middlefont;intg_largefont;intg_smallfont;intWINAPIWinMain(_In_HINSTANCEhInstance,_In_opt_HINSTANCEhp,_In_LPSTRlpC,_In_intnC){ChangeWindowMode(TRUE);SetGraphMode(1400,600,32);if(DxLib_Init()==-1){return-1;}if(LoadGameImage()==FALSE)return-1;g_middlefont=CreateFontToHandle("メイリオ",42,-1,DX_FONTTYPE_ANTIALIASING);g_largefont=CreateFontToHandle("メイリオ",90,-1,DX_FONTTYPE_ANTIALIASING);g_smallfont=CreateFontToHandle("メイリオ",17,-1,DX_FONTTYPE_ANTIALIASING);SetDrawScreen(DX_SCREEN_BACK);g_lasttime=GetNowCount()&INT_MAX;while(ProcessMessage()==0&&CheckHitKey(KEY_INPUT_ESCAPE)==0){intcurrenttime=GetNowCount();g_frametime=(float)(currenttime-g_lasttime)/1000.f;ClearDrawScreen();switch(gamestate){caseGameState::GAME_TITLE:DrawGameTitle();break;caseGameState::GAME_MAIN:DrawGameMain();break;caseGameState::GAME_CLEAR:DrawGameClear();break;caseGameState::GAME_OVER:DrawGameOver();break;default:break;}ScreenFlip();}WaitKey();DxLib_End();return0;}voidDrawGameTitle(){DrawGraph(0,45,g_imagehandles.window,TRUE);DrawStringToHandle(CHIPSIZE*10,CHIPSIZE*10,"スーパー3Dダンジョン:例の迷宮",GetColor(255,255,255),g_smallfont);DrawStringToHandle(370,480,"Zキーでスタート",GetColor(255,255,255),g_middlefont);DrawStringToHandle(370,528,"カーソルキーで左右に移動",GetColor(255,255,255),g_middlefont);DrawStringToHandle(CHIPSIZE*4,CHIPSIZE*25,"やったるでい!",GetColor(255,255,255),g_smallfont);DrawGraph(CHIPSIZE,CHIPSIZE*25,g_imagehandles.parson,TRUE);intkey=GetJoypadInputState(DX_INPUT_KEY_PAD1);if(IsAkeyTrigger(key)){gamestate=GameState::GAME_MAIN;InitMap();InitPlayer();}}voidDrawGameMain(){GameMain();}voidDrawGameClear(){}voidDrawGameOver(){}BOOLIsAkeyTrigger(intkey){if(key&PAD_INPUT_A){if(g_akey_prev==FALSE){g_akey_prev=TRUE;returnTRUE;}}else{g_akey_prev=FALSE;}returnFALSE;}

マップ用のデータのヘッダー

floor.h
#ifndef __TRAP_H__
#define __TRAP_H__
typedefstruct{intfloor,x,y;charmess[256];}Events;externintg_door[][4];externintg_wall[][4];externintstair[][4];externintevents[][4];externintdark[][3];externintheal[][3];externintwarp[][5];externintdark[][3];externEventsnew_event[];externintwarp_len;externintdark_len;externintstair_len;externintevent_len;externintheal_len;#endif

マップ用のデータ

floor.cpp
#include "floor.h"
////int stair[][4]{//   {1, 1, 0, 19},//   { 1,0,0,9 }//};intg_wall[][4]={//上、左、下、右{0,0,0,0},//0 無、無、無、無{1,1,1,1},//1 上、左、下、右{1,0,0,0},//2 上、無、無、無{1,1,0,0},//3 上、左、無、無 {1,0,1,0},//4 上、無、下、無{1,0,0,1},//5 上、無、無、右{1,1,1,0},//6 上、左、下、無 {1,0,1,1},//7 上、無、下、右{1,1,0,1},//8 上、左、無、右{0,1,0,0},//9 無、左、無、無{0,1,1,0},//: 無、左、下、無{0,1,0,1},//; 無、左、無、右{0,1,1,1},//< 無、下、左、右{0,0,1,0},//= 無、無、下、無{0,0,1,1},//> 無、無、下、右{0,0,0,1},//? 無、無、無、右};intg_door[][4]={{0,0,0,0},//0 無、無、無、無{1,1,1,1},//1 上、左、下、右{1,0,0,0},//2 上、無、無、無{1,1,0,0},//3 上、左、無、無 {1,0,1,0},//4 上、無、下、無{1,0,0,1},//5 上、無、無、右{1,1,1,0},//6 上、左、下、無 {1,0,1,1},//7 上、無、下、右{1,1,0,1},//8 上、左、無、右{0,1,0,0},//9 無、左、無、無{0,1,1,0},//: 無、左、下、無{0,1,0,1},//; 無、左、無、右{0,1,1,1},//< 無、左、下、右{0,0,1,0},//= 無、無、下、無{0,0,1,1},//> 無、無、下、右{0,0,0,1},//? 無、無、無、右};Eventsnew_event[5]{{1,9,7,"壁に貼ってある大きな看板が次のように告げている。\n***回廊の終端を超えようとしています 引き返しなさい! ***"},{1,13,14,"フードを被った人間型の大きな彫像が見える。\nフードの穴の中からはキン色の光が漏れていて、\n彫像にはさまざまなかたちの宝石が散りばめられている。\n彫像の前には祭壇があり、新しい香が焚かれている。"},{1,13,16,"部屋の中には、頭がネコで、からだがニワトリの異様なけだものの彫像\nがある。彫像はブロンズで、台座はオニキスでできている。\n飾り台の上には不自然な傷痕がある。"},{1,13,1,"部屋の中には、ツノと長いキバをもつ牡豚のギンの像がある。\n彫像の横の壁には、通りすがりのエルフが、書き残していったらしい、\n消えかけたイタズラ書きがある。ほとんど読めないが、どうやら\n死霊や悪魔がいるとの警告らしい。"},{1,9,0,"この部屋からは、何か妖しげな明かりが発せられている。\n中央で長い法衣を着た小柄な男が冒険者たちをふりかえり叫んだ。\n“異邦人たちよ、去りたまえ!”彼は手を振りはじめ、そして、念じた。\n“マピロ マハマ ディロマト”"}};intstair[][4]={{1,1,0,19},{1,0,0,9}};intevents[][4]={{1,0,9,7},};intheal[][3]={{1,0,19}};intwarp[][5]={//階数、スタートx,スタートy,エンドx,エンドy{1,5,10,15,15},{1,13,15,15,15},{1,9,0,0,19},};intdark[][3]={//階数,x,y{1,9,6},{1,9,5},{1,9,4},{1,9,3},{1,9,2},{1,9,1},{1,10,6},{1,10,5},{1,10,4},{1,10,3},{1,10,2},{1,10,1},{1,10,0},{1,9,19},{1,9,18},{1,9,17},{1,9,16},{1,9,15},{1,9,14},{1,9,13},{1,9,12},{1,10,19},{1,10,18},{1,10,17},{1,10,16},{1,10,15},{1,10,14},{1,10,13},{1,10,12},{1,11,19},{1,12,19},{1,13,19},{1,14,19},{1,15,19},{1,16,19},{1,17,19},{1,18,19},{1,19,19},};intwarp_len=sizeof(warp)/sizeof(*warp);intdark_len=sizeof(dark)/sizeof(*dark);intstair_len=sizeof(stair)/sizeof(*stair);intevent_len=sizeof(new_event)/sizeof(*new_event);intheal_len=sizeof(heal)/sizeof(*heal);

ゲーム開始後のヘッダー

gamemap.h
# ifndef __GAME_MAP_H__
#define __GAME_MAP_H__
#include <DxLib.h>
#include "main.h"
#define CHIPSIZE 20
#define MAP_WIDTH 100
#define MAP_HEIGHT 100
#define WALL_THICKNESS 3
#define MOVERATE 8
#define DEPTH 3
#define START_2DX 800
externcharg_mapdata[MAP_HEIGHT][MAP_WIDTH];externcharg_doordata[MAP_HEIGHT][MAP_WIDTH];externcharg_s_doordata[MAP_HEIGHT][MAP_WIDTH];externintg_margeMapData[MAP_HEIGHT][MAP_WIDTH][4];externintg_trapData[MAP_HEIGHT][MAP_WIDTH];enumclassPlayMode{PGM_EVENT,PGM_EXPLORE};structStageData{intmapwidth,mapheight;intstagenum;PlayModeplaymode;};externStageDatastageData;structPlayerData{unsignedintx,y,movecounter,direction,max_hp,hp,deadtime;BOOLdeadflag;};externPlayerDataplayerData;voidGameMain();voidInitMap();voidInitPlayer();voidDraw2DMap();voidDraw3DMap();voidDrawPlayer();voidCheckCurrent();voidShowEvent();voidDeadEvent();#endif

実際のゲーム中の処理

gamemap.cpp
#include "gamemap.h"
intg_mv[4][2]={//x,y{0,-1},//NORTH{-1,-0},//WEST{0,1},//SOUTH{1,0},//EAST};StageDatastageData;PlayerDataplayerData;charg_mapdata[MAP_HEIGHT][MAP_WIDTH];charg_doordata[MAP_HEIGHT][MAP_WIDTH];charg_s_doordata[MAP_HEIGHT][MAP_WIDTH];intg_margeMapData[MAP_HEIGHT][MAP_WIDTH][4];intg_trapData[MAP_HEIGHT][MAP_WIDTH];intstage_num=1;voidGameMain(){playerData.movecounter++;playerData.movecounter%=MOVERATE;if(stageData.playmode==PlayMode::PGM_EXPLORE){unsignedintw=0;intkey=GetJoypadInputState(DX_INPUT_KEY_PAD1);if(playerData.movecounter==0){inthx=playerData.x;inthy=playerData.y;if(key&PAD_INPUT_LEFT){playerData.direction++;playerData.direction=playerData.direction%4;}if(key&PAD_INPUT_RIGHT){playerData.direction--;playerData.direction=(playerData.direction+4)%4;}if(key&PAD_INPUT_DOWN){playerData.direction-=2;playerData.direction=(playerData.direction+4)%4;}if(key&PAD_INPUT_UP||key&PAD_INPUT_10){hx+=g_mv[playerData.direction][0];hy+=g_mv[playerData.direction][1];w=g_margeMapData[playerData.y][playerData.x][playerData.direction];if(w==2||w==3){if(key&PAD_INPUT_10){w=0;}}if(hx>=0||hx<stageData.mapwidth||hy>=0||hy<stageData.mapheight){if(w==0){for(inti=0;i<event_len;i++){if(new_event[i].floor==stage_num&&new_event[i].x==hx&&new_event[i].y==hy){stageData.playmode=PlayMode::PGM_EVENT;}}playerData.x=hx;playerData.y=hy;if(hx>=stageData.mapwidth){playerData.x=0;}if(hx<0){playerData.x=stageData.mapwidth-1;}if(hy>=stageData.mapheight){playerData.y=0;}if(hy<0){playerData.y=stageData.mapheight-1;}if(playerData.hp>0){playerData.hp--;}}}}}}Draw3DMap();Draw2DMap();CheckCurrent();DrawPlayer();if(playerData.hp==0){stageData.playmode=PlayMode::PGM_EVENT;playerData.deadflag=TRUE;playerData.deadtime++;}if(stageData.playmode==PlayMode::PGM_EVENT){if(playerData.deadflag==FALSE){ShowEvent();}else{DeadEvent();}}}voidShowEvent(){DrawGraph(0,0,g_imagehandles.window_l,TRUE);for(inti=0;i<event_len;i++){if(new_event[i].floor==stage_num&&new_event[i].x==playerData.x&&new_event[i].y==playerData.y){DrawStringToHandle(CHIPSIZE*5,CHIPSIZE*2,new_event[i].mess,GetColor(255,255,255),g_smallfont);}}intkey=GetJoypadInputState(DX_INPUT_KEY_PAD1);if(IsAkeyTrigger(key)==TRUE){stageData.playmode=PlayMode::PGM_EXPLORE;}}voidDeadEvent(){DrawGraph(0,0,g_imagehandles.window_l,TRUE);if(playerData.deadtime<3){playerData.x=0;playerData.y=19;playerData.hp=playerData.max_hp;DrawStringToHandle(CHIPSIZE*5,CHIPSIZE*2,"迷宮に充満した毒ガスで気を失ったあなたは気がついたら入り口の階段\nを枕に倒れ込んでいた。\n一体誰がどうやってあなたを運んだのだろうか。\n\nいずれにしてもこのような幸運が今後も起こるとは限らないだろう。",GetColor(255,255,255),g_smallfont);intkey=GetJoypadInputState(DX_INPUT_KEY_PAD1);if(IsAkeyTrigger(key)==TRUE){stageData.playmode=PlayMode::PGM_EXPLORE;playerData.deadflag=FALSE;}}else{DrawStringToHandle(CHIPSIZE*5,CHIPSIZE*2,"やはり何度も幸運は起きることはなかったようだ。\nゲームオーバー",GetColor(255,255,255),g_smallfont);}}voidDrawPlayer(){DrawGraph(CHIPSIZE,CHIPSIZE*25,g_imagehandles.parson,TRUE);intstart_hp_x=CHIPSIZE*5;intmax_hp_x=CHIPSIZE*5+playerData.max_hp;intcurrent_hp_x;if(playerData.hp>0){current_hp_x=CHIPSIZE*5+playerData.hp;}else{current_hp_x=start_hp_x;}DrawBox(start_hp_x,CHIPSIZE*26,max_hp_x,CHIPSIZE*26+CHIPSIZE,GetColor(255,0,0),TRUE);DrawBox(start_hp_x,CHIPSIZE*26,current_hp_x,CHIPSIZE*26+CHIPSIZE,GetColor(0,0,255),TRUE);}intg_view[4][3][2]={//視点からのマップの横の座標// 左[0],中[1],右[2]{{-1,0},{0,0},{1,0}},//NORTH{{0,1},{0,0},{0,-1}},//WEST{{1,0},{0,0},{-1,0}},//SOUTH{{0,-1},{0,0},{0,1}},//EAST};voidDraw3DMap(){DrawGraph(0,0,g_imagehandles.floor,FALSE);intdir=playerData.direction;for(inty=3;y>=0;y--){for(intx=2;x>=0;x--){intsortx=(x+1)%3;//0,2,1intview_x=playerData.x+g_view[dir][sortx][0]+g_mv[dir][0]*y;intview_y=playerData.y+g_view[dir][sortx][1]+g_mv[dir][1]*y;if(view_x<0){view_x=stageData.mapwidth-view_x;}if(view_x>=stageData.mapwidth){view_x=0+view_x-stageData.mapwidth;}if(view_y<0){view_y=stageData.mapheight-view_y;}if(view_y>=stageData.mapheight){view_y=0+view_y-stageData.mapheight;}intmin_block_num=(y*3+sortx)*4;intmax_block_num=min_block_num+3;for(inti=0;i<(int)Direction::DIRECTION_MAX;i++){intw=g_margeMapData[view_y][view_x][i];if(w>0){intiw=min_block_num+i;switch(dir){case0:break;case1:iw--;if(iw<min_block_num){iw=max_block_num;}break;case3:iw++;if(iw>max_block_num){iw=min_block_num;}break;case2:iw+=2;if(iw>max_block_num){iw=min_block_num+i-dir;}break;}if(w==2&&g_imagehandles.doors[iw]>-1){DrawGraph(0,0,g_imagehandles.doors[iw],TRUE);}elseif(g_imagehandles.walls[iw]>-1){DrawGraph(0,0,g_imagehandles.walls[iw],TRUE);}}}//暗闇for(inti=0;i<dark_len;i++){if(dark[i][0]==stage_num&&dark[i][1]==view_x&&dark[i][2]==view_y&&sortx==1){DrawGraph(0,0,g_imagehandles.dark[y],TRUE);if(dark[i][1]==playerData.x&&dark[i][2]==playerData.y){DrawGraph(0,45,g_imagehandles.window,TRUE);DrawStringToHandle(CHIPSIZE*16,CHIPSIZE*10,"まっくらやみだ",GetColor(255,255,255),g_smallfont);}}}}}}voidCheckCurrent(){////ワープif(stageData.playmode==PlayMode::PGM_EXPLORE){for(inti=0;i<warp_len;i++){if(warp[i][0]==stage_num&&warp[i][1]==playerData.x&&warp[i][2]==playerData.y){playerData.x=warp[i][3];playerData.y=warp[i][4];}}}//階段for(inti=0;i<stair_len;i++){if(stair[i][0]==stage_num&&stair[i][2]==playerData.x&&stair[i][3]==playerData.y){DrawGraph(0,45,g_imagehandles.window,TRUE);if(stair[i][1]==0){DrawStringToHandle(CHIPSIZE*12,CHIPSIZE*10,"したにおりるかいだんがあります。",GetColor(255,255,255),g_smallfont);}else{DrawStringToHandle(CHIPSIZE*12,CHIPSIZE*10,"うえにのぼるかいだんがあります。",GetColor(255,255,255),g_smallfont);}}}for(inti=0;i<heal_len;i++){if(heal[i][0]==stage_num&&heal[i][1]==playerData.x&&heal[i][2]==playerData.y){playerData.hp=playerData.max_hp;}}}voidDraw2DMap(){for(inty=0;y<stageData.mapheight;y++){for(intx=0;x<stageData.mapwidth;x++){for(inti=0;i<(int)Direction::DIRECTION_MAX;i++){if(g_margeMapData[y][x][i]>=1){unsignedintCr=0;switch(g_margeMapData[y][x][i]){case1:Cr=GetColor(255,0,0);break;case2:Cr=GetColor(0,200,0);break;case3:Cr=GetColor(255,255,0);break;}intwall_thickness;switch(i){case0:case1:wall_thickness=WALL_THICKNESS;break;case2:case3:wall_thickness=WALL_THICKNESS*-1;}if(i%2==0){//横線DrawBox(x*CHIPSIZE+START_2DX,y*CHIPSIZE+(CHIPSIZE*i/2),x*CHIPSIZE+CHIPSIZE+START_2DX,y*CHIPSIZE+(CHIPSIZE*i/2)+wall_thickness,Cr,TRUE);}else{//縦線DrawBox(x*CHIPSIZE+(CHIPSIZE*(i-1)/2)+START_2DX,y*CHIPSIZE,x*CHIPSIZE+(CHIPSIZE*(i-1)/2)+wall_thickness+START_2DX,y*CHIPSIZE+CHIPSIZE,Cr,TRUE);}}}}}//player自身の描画DrawBox(playerData.x*CHIPSIZE+3+START_2DX,playerData.y*CHIPSIZE+3,playerData.x*CHIPSIZE+CHIPSIZE-3+START_2DX,playerData.y*CHIPSIZE+CHIPSIZE-3,GetColor(255,255,255),TRUE);//player方向の描画DrawBox((playerData.x+g_mv[playerData.direction][0])*CHIPSIZE+8+START_2DX,(playerData.y+g_mv[playerData.direction][1])*CHIPSIZE+8,(playerData.x+g_mv[playerData.direction][0])*CHIPSIZE+CHIPSIZE-8+START_2DX,(playerData.y+g_mv[playerData.direction][1])*CHIPSIZE+CHIPSIZE-8,GetColor(0,210,255),TRUE);}voidInitPlayer(){playerData.x=0;playerData.y=19;playerData.max_hp=GetRand(20)+9;playerData.hp=playerData.max_hp;playerData.direction=(int)Direction::NORTH;playerData.deadflag=FALSE;playerData.deadtime=0;stageData.playmode=PlayMode::PGM_EXPLORE;}voidInitMap(){//マップ基本データcharbuf[256];sprintf_s(buf,256,"media\\stage%d.txt",stage_num);intfh=FileRead_open(buf);intmap_y=0;while(FileRead_eof(fh)==0){FileRead_gets(g_mapdata[map_y],MAP_WIDTH,fh);map_y++;}FileRead_close(fh);stageData.mapwidth=(int)strlen(g_mapdata[0]);stageData.mapheight=map_y;//マップドアデータsprintf_s(buf,256,"media\\d_stage%d.txt",stage_num);fh=FileRead_open(buf);map_y=0;while(FileRead_eof(fh)==0){FileRead_gets(g_doordata[map_y],MAP_WIDTH,fh);map_y++;}FileRead_close(fh);//マップ隠しドアデータsprintf_s(buf,256,"media\\sd_stage%d.txt",stage_num);fh=FileRead_open(buf);map_y=0;while(FileRead_eof(fh)==0){FileRead_gets(g_s_doordata[map_y],MAP_WIDTH,fh);map_y++;}FileRead_close(fh);//それぞれのデータを1つの変数 g_margeMapData にまとめるfor(inty=0;y<stageData.mapheight;y++){for(intx=0;x<stageData.mapwidth;x++){intwall=g_mapdata[y][x]-'0';intdoor=g_doordata[y][x]-'0';ints_door=g_s_doordata[y][x]-'0';for(inti=0;i<4;i++){intmarge_wall=g_wall[wall][i]+g_door[door][i]+g_door[s_door][i];g_margeMapData[y][x][i]=marge_wall;}}}}

いやーゲーム作りって難しいですね!
でも実際に動くとすごい嬉しかったです!


Viewing all articles
Browse latest Browse all 21081

Trending Articles