Advertisement
Guest User

Untitled

a guest
Sep 27th, 2019
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 20.27 KB | None | 0 0
  1. #include "DxLib.h"
  2.  
  3. int Key[256];
  4.  
  5. int gpUpdateKey()
  6. {
  7.     char tmpKey[256];
  8.     GetHitKeyStateAll(tmpKey);
  9.     for (int i = 0; i < 256; i++)
  10.         (tmpKey[i] == 0) ? (Key[i] = 0) : Key[i]++;
  11.     return 0;
  12. }
  13.  
  14. int stage[4][7][2];  // 盤上のマスの格子点の座標
  15. int pos[3][6][2];    // キャラ描画座標
  16.  
  17. void init_stage()  // stage と pos を初期化する
  18. {
  19.     for (int j = 0; j < 7; j++) {
  20.         int w = (j - 3) * 100, h = 300;
  21.         for (int i = 4; --i >= 0; ) {
  22.             stage[i][j][0] = w + 400, stage[i][j][1] = h - 100;
  23.             w = w * 9 / 10, h = h * 9 / 10;
  24.         }
  25.     }
  26.     for (int i = 0; i < 3; i++)
  27.         for (int j = 0; j < 6; j++) {
  28.             pos[i][j][0] = (stage[i][j][0] + stage[i + 1][j + 1][0]) / 2 - 25;
  29.             pos[i][j][1] = (stage[i][j][1] + stage[i + 1][j + 1][1]) / 2 - 65;
  30.         }
  31. }
  32.  
  33. int White;
  34. int function_status;//戦闘画面中は1とするための変数function_statusの定義
  35.  
  36.  
  37.  
  38. int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
  39. {
  40.     SetGraphMode(780, 680, 32);         // ウィンドウの大きさを指定
  41.     ChangeWindowMode(TRUE);             // 全画面ではなくウインドウを使用
  42.     if (DxLib_Init() == -1) return -1;  // DXライブラリ初期化処理
  43.     SetDrawScreen(DX_SCREEN_BACK);      // 裏画面を使用する設定
  44.  
  45.     init_stage(); // stage, pos の初期化
  46.     int enemyX = 4, enemyY = 1;   // 敵の位置
  47.     int playerX = 1, playerY = 1;  // 俺の位置
  48.  
  49.     int enemyMove = 0;   // 敵の移動状態
  50.       // 俺の移動状態//1~21で右に振り向きのプログラム①が終わり、22になったら足踏みする②を実行するようにする。
  51.     int playerMove = 1;
  52.  
  53.     int lockonMove = 0;
  54.     int lockonHandle[3];
  55.  
  56.     function_status = 1;//最初は1にして戦闘画面状態にする。
  57.  
  58.  
  59.     int lock = 0;  // ロック状態
  60.  
  61.     int enemyGHandle[12];   // 敵のグラフィックハンドル格納用配列
  62.     int playerGHandle[12];  // 俺のグラフィックハンドル格納用配列
  63.             // 0-2:後ろ向き、3-5:右向き、6-8:前向き、9-11:左向き
  64.  
  65.     LoadDivGraph("charall.png", 12, 3, 4, 49, 66, enemyGHandle);
  66.     LoadDivGraph("charall.png", 12, 3, 4, 49, 66, playerGHandle);
  67.     SetTransColor(255, 255, 255); // 読み込む画像の前にこいつを置くことで透明化できる。ループ内にも書いて正しく動くが毎回読み込むようになってしまうため処理が遅くなる。
  68.     LoadDivGraph("lockon.bmp", 3, 3, 1, 23, 23, lockonHandle);//なので、一度読み込むだけ画像は使えるし、処理を遅くしないためにループに入る前かつWinMainの中に書いた。
  69.  
  70.     int enemyImage = enemyGHandle[11];    // 敵 左向き
  71.     int playerImage = playerGHandle[4];   // 俺 右向き
  72.     int lockImge = lockonHandle[3];
  73.     int preplayerX = 0;
  74.     int after = 0;
  75.     unsigned int count = 50;
  76.     int count2 = 50;
  77.     unsigned int count3 = 50;
  78.  
  79.     int Kcount = 50;//キック攻撃のゲージ
  80.     int Kcount2 = 50;
  81.  
  82.     int attackdamage = 0;//殴る際の攻撃判定として作った。
  83.     int addattacktime = 0;//追加攻撃をするための変数
  84.     int addattackimage = 20;//描画するための追加アタックのためのゲージ
  85.  
  86.     int zannzou = 20;
  87.     int  frames = 0; // フレーム数
  88.     int stopenemytime = 0;
  89.  
  90.     const int MOVE_INTERVAL = 1000; // 何ミリ秒ごとに移動処理をするか
  91.     int nextMoveTime = GetNowCount() + MOVE_INTERVAL; // 次回移動処理をする時刻
  92.     int stopCount = 0; // 動かないのがあと何回か
  93.  
  94.     int enemyHP = 300;
  95.  
  96.  
  97.  
  98.     while (ProcessMessage() == 0) {
  99.         gpUpdateKey();  // キーの入力状態を取得
  100.         if (Key[KEY_INPUT_X] == 1) { //キーXを押すとfunction_statusは0になる
  101.             function_status = 0;
  102.         }
  103.  
  104.         if (Key[KEY_INPUT_Y] == 1) { //キーYを押すとfunction_statusは1になる
  105.             function_status = 1;//戦闘画面に戻す
  106.         }
  107.  
  108.         else {//戦闘画面中は1とする
  109.             //gpUpdateKey();  // キーの入力状態を取得 上のifで既にgpUpdateKey();があり、elseはif以外の情報は引き継ぐので再びgpUpdateKey();書く必要はなかった。
  110.             // 俺の移動
  111.             if (Key[KEY_INPUT_RIGHT] == 1 && playerX < 2) { //キーを入力する以外にも押した後に早く画像を切り替えて足踏みするようにするために初期値にも1はあるがキーにもplayerMove=1を書いたり、キーを押したらどうしたいかをするためにplayerX++を書いている。
  112.                 playerMove = 1;  playerX++; playerImage = playerGHandle[2];
  113.             } //playerMove = 1;があると下に書いたplayerMoveより足踏みするplayerMoveが無いと初期値の1でそのまま足踏みするので遅く反応するのでは?
  114.             if (Key[KEY_INPUT_LEFT] == 1 && playerX > 0) {//キーにplayerMove=1を書くと初期値の1よりも早くキーに書いたplayerMoveの1が行くため早く足踏みに行くため、止まってから足踏みに行くまでの間にある向きを変える画像playerGHandle[2]が一瞬であるため、向きを変えるのが早く見えるのでは?足踏みを速く来るようにしたため。
  115.                 playerMove = 1; playerX--; playerImage = playerGHandle[9];//まあ、足踏みさせなくても、ただ書くだけでも方向を十分早く変えれる
  116.             }
  117.             if (Key[KEY_INPUT_UP] == 1 && playerY > 0) {
  118.                 playerMove = 1; playerY--; playerImage = playerGHandle[2];
  119.             }
  120.             if (Key[KEY_INPUT_DOWN] == 1 && playerY < 2) {
  121.                 playerMove = 1; playerY++; playerImage = playerGHandle[8];
  122.             }
  123.  
  124.  
  125.             //Rが一度押された上でフレームを利用してループさせるためにif文を新しく外に書いたのだ。
  126.             if (Key[KEY_INPUT_R] == 1 && playerY == enemyY) {
  127.                 DrawGraph(pos[enemyY][enemyX][0], pos[enemyY][enemyX][1],//多分ここはいらない下に描画するための関数を書くため
  128.                     lockImge, FALSE);   // ロックマークの描画
  129.                 lock = 1;//Key[KEY_INPUT_R] == 1 && playerY == enemyYの時、lockを1にする。lockを「何フレーム目の時」でも値を1として置いたため、条件式lockの入力キーAに呼び出せる。
  130.                 lockonMove = 1;
  131.             }
  132.             if (lockonMove > 0) {//lockonMoveが0より大きいならば++lockonMoveをする、
  133.                 ++lockonMove;
  134.             }
  135.             if (lockonMove == 10) {
  136.                 lockImge = lockonHandle[0];//情報lockonMove == 10やlockonHandle[0]を引き継いで下に書いた描画関数に入るため、ここには関数に入れる情報だけ入るのだ。
  137.                 //その時の情報lockonMove == 10やlockonHandle[0]以外の引き継がれたとうかその時の敵の座標なども関数に入る。関数が求めるものが入るので、関数に必要なものを揃える。
  138.             }
  139.             else if (lockonMove == 20) {
  140.                 lockImge = lockonHandle[1];
  141.  
  142.             }
  143.             else if (lockonMove == 30) {
  144.                 lockImge = lockonHandle[2];
  145.  
  146.  
  147.             }
  148.             else if (lockonMove == 40) {
  149.                 lockImge = lockonHandle[1];
  150.                 lockonMove = 1;
  151.             }
  152.  
  153.             if (playerY != enemyY) {
  154.                 lock = 0;
  155.                 lockonMove = 0;//敵が移動した場合ロックオンの画像が消えるようにlockonMoveを0にする。
  156.             }
  157.  
  158.  
  159.             //playerY != enemyYよりY座標が異なる場合を表す、Y座標が異なる場合はlockの値は0になる。要はロックが解除されてしまう。
  160.             if (lock) {
  161.  
  162.                 if (Key[KEY_INPUT_A] == 1 && count == 50) {  //殴る//(lock){}の中に書くとロックする度にcountが0になるので意味がない
  163.                     //count++;  ここにcount書くとifの条件よりcountが0の時の下のlockやplayerX = enemyX - 1など条件になるため、++でcountが1になったらロックできても攻撃できないんだ
  164.                     //ここのcountの情報がそのまま下の描画関数に渡されるだけ。
  165.                     //if (count >= 0 && ++count > 40) {//countが0から15になるまでを一フレームで表しただけでは?ようはcountを0~1にするのに15フレームかかっただけでは?いや、単純にここにフレームは働いていないなので++count > 40と書いて39回行うはずがフレームが働かないので1しか上がっていないので一回しか攻撃が出来ないのだ
  166.  
  167.                     lock = 0;//lock = 1の時の「lock!!」の描画を消すためにlockの値を0に変更。
  168.                     lockonMove = 0;//アタックする時 ロックオンの画像が消えるように値を0にする。
  169.                     preplayerX = playerX; // 元の位置を保持
  170.                     playerX = enemyX - 1; // 俺は敵の眼前へ
  171.                     if (playerX == enemyX - 1) { preplayerX; playerImage = playerGHandle[4]; }//敵の前に言ったら、移動する前の残像が残る。
  172.                     //after = 1;//アタック状態 ここまでをアタックとしてafter = 1と置いた。
  173.                     enemyImage = enemyGHandle[5];//攻撃を食らうと右向きになるようにする
  174.                     count = count - 50;//キーAを押すたびに10だけ引く
  175.                     addattacktime = 500;
  176.                     zannzou = 20;
  177.                     if (enemyGHandle[5]) { enemyHP = enemyHP - 50; }//if (Key[KEY_INPUT_A] == 1 && count <= 500)に直接enemyHP = enemyHP - 50;を書き込むか、殴るが成立した時にif (enemyGHandle[5]) { enemyHP = enemyHP - 50; }と書いても良い。
  178.                 }
  179.  
  180.             }
  181.  
  182.             //↓確認addattcktimeの—1について関係はない
  183.             //俺は敵の眼前へ言った後、このifの条件により続けて攻撃か元の位置に戻るかになる
  184.             if (addattacktime <= 500 && --addattacktime > 0)//addattacktimeが0になるまでの間に攻撃があればaddattacktimeは20に戻る
  185.                
  186.             {//★addattacktimeが500以下で0より大きい時—1されていく、そして500以下ならばかつ0より大きいならばずっと処理されるということ。
  187.  
  188.                 //addattackimage = addattackimage - 1;
  189.                 if (Key[KEY_INPUT_K] == 1 && Kcount == 50 && enemyImage == enemyGHandle[5]) {//攻撃がキックだった場合
  190.                     Kcount = Kcount - 50;//キーKを押すたびに50だけ引く
  191.                     enemyImage = enemyGHandle[5];
  192.                     if (enemyImage == enemyGHandle[5])//攻撃を食らうと右向きになるようにする
  193.                     {
  194.                         enemyHP = enemyHP - 50;
  195.                         playerImage = playerGHandle[4];
  196.                         addattacktime = 500;
  197.                     }
  198.                    
  199.                     }
  200.                 }
  201.             //pos[playerY][playerX + 1][0] == pos[enemyY][enemyX][0] && pos[playerY][playerX + 1][1] == pos[enemyY][enemyX + 1][1]
  202.             if (addattacktime < 0) {//addattacktime == 0だと初期値と被ってしまうので0より小さいとした。
  203.                 playerX = preplayerX;
  204.                 playerImage = playerGHandle[4];
  205.                 addattacktime = 0;//addattacktimeが0にると、元の位置に戻る
  206.  
  207.                 if (count < 50) ++count;//これにより連続で攻撃してもif (Key[KEY_INPUT_A] == 1 && enemyImage == enemyGHandle[5])を考慮して連続攻撃ができる!
  208.                 //★あるフレームが進んでから画像がを動くまでを遅くした、ならば、あるフレームが進んだら数字も次の数字に移るまで遅くできるのは?と考えた。
  209.                 //if (count < 50) ++frames;//framesが5で割りきれる時に+countが+1されいく。//countが50より小さい時、framesがフレームにより+1ずつされていき、10で割り切れる際にcountが50になるまで+1される、++により最初+1が追加され49かい+1されるので結果的にcountは50になる。
  210.                 //if (frames % 10 == 0) {
  211.                 //  ++count; if (count > 50) { count = 50; }//★上限はないためcountが49より大きくなったらcount = 50により50にする。
  212.                 //}
  213.                 if (Kcount < 50) ++frames;
  214.                 if (frames % 20 == 0) {
  215.                     ++Kcount; if (Kcount > 50) { Kcount = 50; }//★上限はないためcountが49より大きくなったらcount = 50により50にする。
  216.                 }//★++が>よりも優先順位により優先されるため、というか単純に+1されいくため、その先で条件によって(&&とは違い強制ではなく)Kcount > 50ならばcount = 50となっただけである。
  217.             }
  218.  
  219.         //  if (enemyImage == enemyGHandle[5]) {
  220.         //      stopenemytime = 1;
  221.         //      ++frames;
  222.         //      if (frames % 20 == 0) {
  223.         //          ++stopenemytime; if (stopenemytime > 50) { stopenemytime = 0; }//★上限はないためcountが49より大きくなったらcount = 50により50にする。
  224.         //      }//stopenemytimeが0になれば初期値扱いなので通常通りの動きとなる。enemyGHandle[5]のまま動くことは出来ないため、この方法の方が簡単かもしれない。
  225.  
  226.         //  }
  227.             //if (after > 0 && ++after > 15) {//afterが1より大きい時++afterが働き15より大きくなったら、
  228.                 ///ifの中にifを書いてしまうとその前のifを否定してしまうためデータが引き継げない。なので別のif文として書いた。←多分違う
  229.             //  playerX = preplayerX;//preplayerXの座標をplayerXに代入する。
  230.             //  playerImage = playerGHandle[4];
  231.             //  after = 0;//アタック解除
  232.  
  233.             //}
  234.  
  235.             // 敵の移動
  236.             int t = GetNowCount();
  237.             if (t >= nextMoveTime) { // 指定の時間が経ったら(1sごとに)
  238.                 nextMoveTime = t + MOVE_INTERVAL; // 次回移動処理をする時刻
  239.                 if (stopCount > 0) { // 停止中のとき
  240.                     stopCount--; // 止まっている残り時間(回数)を減らす
  241.                 }
  242.                 else { // 普通の状態のとき
  243.                     if (GetRand(99) < 10) { // たまに(10%の確率で)
  244.                         stopCount = GetRand(4); // 数秒間(1~5秒間)その場に止まる
  245.                     }
  246.                     else { // 9マス上のいずれかのパネルに移動させる
  247.                         int cy = enemyY, cx = enemyX;
  248.                         do {
  249.                             enemyY = GetRand(2);
  250.                             enemyX = GetRand(2) + 3;
  251.                         } while (enemyX == cx && enemyY == cy ||
  252.                             enemyX == playerX && enemyY == playerY);
  253.                         enemyImage = enemyGHandle[10];
  254.                         enemyMove = 1;
  255.                     }
  256.                 }
  257.             }
  258.  
  259.             if (playerMove > 0) {//1フレームで処理を終わらせるためifの後はelse ifを使った。//フレームがあってもplayerMove++を書かないと1ずつ上がらない。playerMove++をフレームの60回ループするするところに書くことで以下のように書いて足踏みしている画像が描けた。
  260.                 playerMove++;//60フレームの中で、このifで条件(playerMove > 0)が真であるためplayerMove++を「フレーム」と「条件式」により繰り返しplayerMove++して、
  261.                 if (playerMove == 10)//以前の文を否定しないelse ifが次にあるためplayerMoveの情報を引き継ぎplayerMove == 20となるまで繰り返しplayerMove++をした。次にもelse ifがあるので同様、、、
  262.                 {
  263.                     playerImage = playerGHandle[4];
  264.                 }
  265.                 else if (playerMove == 20)//条件式として書くため=は==と書いた。//else ifによりplayerMoveが20を超えて(20の場合を否定し)30の場合を表す。
  266.                 {
  267.                     playerImage = playerGHandle[5];
  268.                 }
  269.                 else if (playerMove == 40)//30まで上がったものが40に上がった時、playerGHandle[4]になる。if文の連続では文法のルールで前の文を否定するため連続的に画像が流れず足踏みできない、なのでelse ifにしたのだ。
  270.                 {
  271.                     playerImage = playerGHandle[4];
  272.                 }
  273.                 else if (playerMove == 60 * 4) {//下に書いているように60フレームないに納めないといけないため、50まで上がったところで終わっている。
  274.                     playerImage = playerGHandle[3];//上に書いてることには誤りがある、60フレームで1sなだけ、超えてもいい。
  275.                     playerMove = 1;//
  276.                 }
  277.  
  278.             }
  279.  
  280.  
  281.             //ループ内に書いたenemyMoveについてenemyMoveが0より大きくて40を超えたら{}の中身を実行。
  282.             //enemyMoveが0より大きいならば+1されて、40より大きい数値になれば両方の条件を満たすので+1される。40より大きい数値になったら敵の画像が変わる。
  283.             //enemyMoveが40より+1されて大きくなるために++enemyMove > 40
  284.             if (enemyMove > 0 && ++enemyMove > 40) {//pcが60フレームで一周するためenemyMoveが61以上だとenemyGHandle[8]が反映されず元のままで移動が終わる。なのでenemyMoveは60以下でなくてはならない
  285.                 enemyMove = 0; enemyImage = enemyGHandle[11];//60になる前に画像11を描画するようにしなければならないため、60より小さい40フレームにした。
  286.             }
  287.         }
  288.  
  289.         //これより以下は描画するためのプログラム
  290.         ClearDrawScreen();  // 裏画面を
  291.  
  292.  
  293.  
  294.         //if (function_status == 0) {//function_status = 0の時はメニュー画面でfunction_statusが1の時は戦闘画面とした。
  295.     //キーXを押すとfunction_statusを0とするように書いた
  296.         if (function_status == 0) {
  297.             White = GetColor(255, 255, 255);                    //色の取得
  298.             DrawString(100, 140, "攻撃方法の選択画面 (xをプッシュ)", White);
  299.  
  300.             //攻撃手段を選んでいる最中は0とする
  301.             ScreenFlip();  // 裏画面を表画面に反映
  302.         }
  303.  
  304.         else {// ステージの描画  ★function_status == 0の場合ではないし、0か1の二択しかため、function_statusの初期値は1であるためif (function_status == 0)は除外されelseの方が描画される。
  305.             int stageColor = GetColor(160, 64, 64);
  306.             for (int i = 0; i < 4; i++)
  307.                 DrawLine(stage[i][0][0], stage[i][0][1],
  308.                     stage[i][6][0], stage[i][6][1], stageColor, 5);
  309.             for (int j = 0; j < 7; j++)
  310.                 DrawLine(stage[0][j][0], stage[0][j][1],
  311.                     stage[3][j][0], stage[3][j][1], stageColor, 5);
  312.  
  313.             DrawGraph(pos[enemyY][enemyX][0], pos[enemyY][enemyX][1],
  314.                 enemyImage, true);   // 敵キャラの描画
  315.  
  316.             DrawGraph(pos[playerY][playerX][0], pos[playerY][playerX][1],
  317.                 playerImage, true);  // 俺キャラの描画
  318.  
  319.  
  320.             // 俺キャラ(敵の目の前に移動する際の残像)の描画
  321.             if (--zannzou > 0) { //★残像を出すためにRキーでAを押したら変数zannzouが20になり、zannouの変数が0より大きいならば—1をしていき、その間だけ画像を描画する。
  322.                 DrawGraph(pos[playerY][preplayerX][0], pos[playerY][preplayerX][1],
  323.                     playerImage, true);  
  324.             }//移動した一瞬に元の位置に自分を描画したい、しかしうまく機能していない。
  325.             ///★多分一瞬過ぎるのであえてcount < 8と範囲を付けることでほんの一瞬だが残像が見えるようにした。
  326.             ///攻撃してcountが50に溜まるまでの期間を利用した。
  327.  
  328.  
  329.             if (lock == 1) {
  330.                 DrawGraph(
  331.                     pos[enemyY][enemyX][0] + 13,//敵の中心にマークを持ってくるために+13した。
  332.                     pos[enemyY][enemyX][1] + 21,//敵の中心にマークを持ってくるために+21した。
  333.                     lockImge, true); // FALSE -> TRUE//ロックマーク中だけ描画するようにした。
  334.             }//ロックマークの描画
  335.             if (lock) DrawFormatString(100, 200, GetColor(255, 255, 255), "LOCK");//ループ内に書くと条件式lockのによりlockの値を0にしてもずっと表示されるため、必要な時に表示するようにここに書いた
  336.  
  337.             DrawFormatString(50, 300, GetColor(255, 0, 0), "%d/%d", count, count2);//1回殴った時にすべて消費して、再び溜まるまでの過程を表示するための関数
  338.             if (count < 50) {
  339.                 DrawFormatString(50, 300, GetColor(0, 255, 255), "%d", count);//ここでcountの情報だけを条件(count < 500)より呼び出して、countの色を変えた
  340.             }
  341.             //敵のHPの描画
  342.             DrawFormatString(pos[enemyY][enemyX][0] + 33, pos[enemyY][enemyX][1] - 49, GetColor(152, 251, 152), "HP%d", enemyHP);
  343.  
  344.             DrawFormatString(50, 400, GetColor(255, 0, 0), "%d/%d", Kcount, Kcount2);
  345.  
  346.  
  347.             //DrawFormatString(50, 500, GetColor(255, 0, 0), "%d", addattackimage);//★addattacktimeが攻撃に続けば500になるし、それ以外では初期値より0なのでずっと下がっているわけではない
  348.             if (addattacktime <= 500 && --addattacktime > 0) { DrawFormatString(50, 450, GetColor(255, 0, 0), "addattacktime%d", addattacktime); }//ロックオンして攻撃するまでの間のみ出てくる。
  349.         //★上限や下限はないが、変数の値をセットすることで切り替えることはできる。今回はそれを活用して変数の値を一時的に固定したり変えたりしている。
  350.            
  351.                 DrawFormatString(50, 470, GetColor(255, 0, 0), "確認addattacktime%d", addattacktime);
  352.                 DrawFormatString(50, 500, GetColor(255, 0, 0), "stopenemytime%d", stopenemytime);
  353.        
  354.         }
  355.         ScreenFlip();  // 裏画面を表画面に反映
  356.     }
  357.  
  358.  
  359.     DxLib_End();  // DXライブラリ使用の終了処理
  360.     return 0;  // ソフトの終了
  361.  
  362. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement