/*第6回配布用.穴埋め済みの完全版です*/ #include "DxLib.h" #include #define WINDOW_WIDTH 640 //ウィンドウの大きさ(横) #define WINDOW_HEIGHT 480 //ウィンドウの大きさ(縦) #define GRA 1 //重力加速度 #define MAXSPEEDY 20 //自由落下の最高速度 #define CENTER 288 //主人公の中央座標 #define HERO_SIZE 32 //主人公の大きさ #define ATTACK_SIZE 32 //攻撃の大きさ #define WIDTH_SIZE 35 //スクロールの幅(横) #define HEIGHT_SIZE 15 //スクロールの幅(縦) #define BLOCK 32 //タイルの大きさ[px] #pragma warning(disable : 4996)//fopen,fscanfでエラーが出るのを防ぐ //このエラーの原因は「マイクロソフトの余計なおせっかい」です struct SImg { int migi; int r_attack; int kabe; int yuka; int goal; int r_enemy; int gameover; int title; int clear; int clear2; int haikei; int null; }; //主人公関連の構造体 struct SPlayer { int x, y; //主人公のX,Y座標 int vx, vy; //主人公のX,Y軸方向の速度 int jfly; //飛んでいるかどうかの判別 0:着地/1:それ以外 int dire; //主人公の向いている方向 0:右/1:左 int attack; //攻撃中かどうかの判別 0:通常/1:攻撃中 int kabe_r; //右方向に壁があるかどうかの判定 int kabe_l; //左方向に壁があるかどうかの判定 int kakusi; }; //敵関連の構造体 struct SEnemy { int x, y; //敵のX,Y座標 int vx, vy; //敵のX,Y軸方向の速度 int life; //敵の体力 int size_x, size_y; //敵の大きさ int count; //敵の動く際のカウント int dire; //敵の向いている方向 0:右/1:左 }; //構造体の宣言 struct SImg img; struct SPlayer player; struct SEnemy enemy; int map[WIDTH_SIZE][HEIGHT_SIZE]; char keyState[256]; //マップチップの読み込み void Map(void) { FILE *file; if ((file=fopen("map/map_proto.txt","r"))== NULL) { OutputDebugString("MapData Read Error\n"); //もしマップデータが開くことが出来なかったらデバッグ画面に"Map Data Read Error"と表示 exit(EXIT_FAILURE); } for (int j = 0; j < HEIGHT_SIZE; j++) { for (int i = 0; i < WIDTH_SIZE; i++) { fscanf(file, "%d,", &map[i][j]);//カンマに気を付けてください } } fclose(file); } //画像読み込み void image(void) { img.migi = LoadGraph("img/migi.png"); img.r_attack = LoadGraph("img/r_attack.png"); img.kabe = LoadGraph("img/kabe.png"); img.yuka = LoadGraph("img/yuka.png"); img.goal = LoadGraph("img/goal.png"); img.r_enemy = LoadGraph("img/r_enemy.png"); img.gameover = LoadGraph("img/gameover.png"); img.title = LoadGraph("img/title.png"); img.clear = LoadGraph("img/clear.png"); img.clear2 = LoadGraph("img/clear2.png"); img.haikei = LoadGraph("img/haikei.png"); img.null = LoadGraph("img/null.png"); } //変数の初期化 void init(void) { player.x = 32; //主人公の初期x座標 player.y = 400; //主人公の初期y座標 player.vx = 0; player.vy = 0; player.jfly = 0; player.dire = 0; player.attack = 0; player.kabe_r = 0; player.kabe_l = 0; player.kakusi = 0; enemy.size_x = 32; enemy.size_y = 32; enemy.x = 300; enemy.y = 480 - BLOCK - enemy.size_y; enemy.vx = 0; enemy.vy = 0; enemy.count = 0; enemy.life = 1; enemy.dire = 0; } void title(void) { ClearDrawScreen(); DrawGraph(0, 0, img.title, TRUE); //タイトル画面を描画 ScreenFlip(); while (keyState[KEY_INPUT_ESCAPE] != 1 && keyState[KEY_INPUT_X] != 1) { //エスケープかつXが押されていないとき GetHitKeyStateAll(keyState); if (ProcessMessage() == -1) //エラーが発生したらループを抜ける break; } } //ゲームオーバー画面の表示+マップのリロード+変数の初期化 void gameover(void) { init(); //変数の初期化 ClearDrawScreen(); DrawGraph(0, 0, img.gameover, TRUE); //ゲームオーバー画面を描画 ScreenFlip(); while (keyState[KEY_INPUT_ESCAPE] != 1 && keyState[KEY_INPUT_X] != 1) { //エスケープかつXが押されていないとき GetHitKeyStateAll(keyState); if (ProcessMessage() == -1) break; //エラーが発生したらループを抜ける } Map(); //マップのリロード } //壁判定 (上下判定/ブロックの上に乗る) void judge_v(int blx, int bly) { if (blx < (player.x + HERO_SIZE) && player.x < (blx + BLOCK) && bly <= (player.y + HERO_SIZE) && player.y < (bly + BLOCK)) { if (player.vy >= 0) {//落ちてる最中あるいはy方向には動いていないなら player.jfly = 0; player.y = (bly - HERO_SIZE); player.vy = 0; } else {//上向きに動いてるなら player.vy = 0; player.y = (bly + BLOCK); } } int white = GetColor(255, 255, 255); DrawFormatString(550, 120, white, "J2:%4d", map[blx / BLOCK][blx / BLOCK]); } //プレイヤーの移動 void move(void) { player.vx = 0; //横移動リセット if (player.jfly != 0 && player.vy < MAXSPEEDY) //重力(空中にいれば重力を働かせる) player.vy += 1; player.kabe_l = 0; //壁判定リセット player.kabe_r = 0; GetHitKeyStateAll(keyState); //キーボードのすべてのキーの状態を取得 //その状態は変数keyStateに記録される if (keyState[KEY_INPUT_LEFT]) { //主人公の左向き操作(もし左ボタンが押されていたら) if (player.kabe_l == 0 && player.x > 0) { player.vx -= 4; //主人公をx方向に移動させる } player.dire = 1;//主人公は左向き } if (keyState[KEY_INPUT_RIGHT]) { //主人公の右向き操作(もし右ボタンが押されていたら) if (player.kabe_r == 0 && player.x + HERO_SIZE <= BLOCK * WIDTH_SIZE) { player.vx += 4; } player.dire = 0;//主人公は右向き } if (player.jfly == 0 && keyState[KEY_INPUT_X]) { //主人公のジャンプ操作(空中にいないときにXキーが押されたら) player.jfly = 1; player.vy -= 15; //主人公のy速度を変化させる(上方向の速さ) } if (keyState[KEY_INPUT_R]) //デバッグ用ジャンプ player.vy = -5; player.jfly = 1; player.x += player.vx; player.y += player.vy; for (int j = 0; jWINDOW_HEIGHT) {//画面の外に出たら(下に落ちたら)ゲームオーバー gameover(); } if (player.x == 0 && (player.y > 400 && player.y < 402)) player.kakusi += 1; } //敵キャラの移動 void enemymove(void) { if (enemy.life != 0) { //敵が存在していて if (enemy.vx >= 0) { //敵の速度が右向きなら enemy.vx = 2; //速度は右向き enemy.count++; enemy.dire = 0; //敵は右を向く } else { //敵の速度が左向きなら enemy.vx = -2; //速度は左向き enemy.count--; enemy.dire = 1; //敵は左を向く } } if (enemy.count >= 100) enemy.vx = -2; else if (enemy.count <= 0) enemy.vx = 2; enemy.x += enemy.vx; //敵のx座標に速度を加算する enemy.y += enemy.vy; //敵のy座標に速度を加算する if (player.attack) {//もし主人公が攻撃中で if ((player.dire == 0 && (enemy.x < player.x + HERO_SIZE + ATTACK_SIZE && player.x + ATTACK_SIZE < enemy.x + enemy.size_x) && (enemy.y < player.y + HERO_SIZE && player.y < enemy.y + enemy.size_y)) || //右を向いていた時の処理(攻撃が敵に当たれば) (player.dire == 1 && (enemy.x < player.x + HERO_SIZE - ATTACK_SIZE && player.x - ATTACK_SIZE < enemy.x + enemy.size_x) && (enemy.y < player.y + HERO_SIZE && player.y < enemy.y + enemy.size_y))) //左を向いていた時の処理(攻撃が敵に当たれば) enemy.life = 0; } } //主人公キャラの攻撃 void attack(void) { GetHitKeyStateAll(keyState); if (keyState[KEY_INPUT_Z]) { //Zキーが押されていたら if (player.attack == 0) player.attack = 1; } else player.attack = 0; } void draw(void) { //画面クリア ClearDrawScreen(); //背景の描画 for (int j = 0; j < BLOCK; j++) DrawGraph(j * BLOCK, 0, img.haikei, TRUE); //マップチップからの描画 for (int j = 0; j < HEIGHT_SIZE; j++) { for (int i = (player.x / BLOCK) -9; i < (player.x / BLOCK) + 12; i++) { if (i < WIDTH_SIZE && i >= 0) { //横の部分より狭い範囲でマップ判断 switch (map[i][j]) { case 0: break; case 1: DrawGraph(i*BLOCK - player.x + CENTER, j * BLOCK, img.yuka, TRUE); break; //床 case 2: DrawGraph(i*BLOCK - player.x + CENTER, j * BLOCK, img.kabe, TRUE); break; //壁 case 3: DrawGraph(i*BLOCK - player.x + CENTER, j * BLOCK, img.goal, TRUE); break; //ゴール旗(触れたらゴール) default: DrawGraph(i*BLOCK - player.x + CENTER, j * BLOCK, img.null, TRUE); break; //null } } else if (j == 14) DrawGraph(i*BLOCK - player.x + CENTER, j * BLOCK, img.yuka, TRUE); //最下段は床を描画 else DrawGraph(i*BLOCK - player.x + CENTER, j * BLOCK, img.kabe, TRUE); } } if (player.dire == 0) //主人公の描画 DrawGraph(CENTER, player.y, img.migi, TRUE); //右向き else DrawTurnGraph(CENTER, player.y, img.migi, TRUE); //DrawTurnGraphでその画像を左右反転 //させて表示させる if (player.attack) { //攻撃の描画 if (player.dire == 0) DrawGraph(CENTER + ATTACK_SIZE, player.y, img.r_attack, TRUE); else DrawTurnGraph(CENTER - ATTACK_SIZE, player.y, img.r_attack, TRUE); } if (enemy.life > 0) { //敵の描画 if (enemy.dire == 0) //向きの判別 DrawGraph(enemy.x - player.x + CENTER, enemy.y, img.r_enemy, TRUE); else DrawTurnGraph(enemy.x - player.x + CENTER, enemy.y, img.r_enemy, TRUE); } //デバッグ用の変数描画 int white = GetColor(255, 255, 255); DrawFormatString(450, 20, white, "X :%4d", player.x); DrawFormatString(550, 20, white, "Y :%4d", player.y); DrawFormatString(450, 40, white, "VX:%4d", player.vx); DrawFormatString(550, 40, white, "VY:%4d", player.vy); DrawFormatString(450, 60, white, "右壁:%4d", player.kabe_r); DrawFormatString(550, 60, white, "左壁:%4d", player.kabe_l); if (player.dire) { DrawString(450, 80, "左向き", white); } else { DrawString(450, 80, "右向き", white); } if (player.jfly) { DrawString(550, 80, "空中", white); } else { DrawString(550, 80, "着地", white); } if (player.attack) { DrawString(450, 100, "攻撃", white); } else { DrawString(450, 100, "通常", white); } ScreenFlip(); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ipCmdLine, int nShowCmd) { //ウィンドウのタイトルを変更 SetMainWindowText("action"); //ウィンドウモードに変更 ChangeWindowMode(TRUE); //解像度とカラービット数を設定 SetGraphMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32); SetWindowSizeChangeEnableFlag(TRUE); //初期化に失敗したらやめる if (DxLib_Init() == -1) { return -1; } ////マップチップ読み込み Map(); //画像のロード image(); //変数の初期化 init(); SetDrawScreen(DX_SCREEN_BACK); //タイトル表示 title(); /************************** ゲームループ *****************************/ while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0) { //動き move(); enemymove(); //攻撃 attack(); //描画 draw(); } /************************ ゲームループおわり ************************/ //DXライブラリ使用の終了処理 DxLib_End(); //SOFTの終了 return 0; }