トップページ > 記事閲覧
ジャンプ処理について
名前:たき 日時: 2022/07/28 08:29

初投稿になります。 現在、管理人様並びに他所様が公開しているサンプルプログラムを参考に2Dゲームぽい物を試しに組んでみましたら、 操作するキャラクター(DrawBox)のジャンプ処理が管理人様のサンプルのようにジャンプはしますがスペースキーを長押ししますと キャラクターが上へ上へと上がりそのまま画面外に出てしまいました。 この場合どう修正すればいいかが思いつかず、、、勉強不足で大変恐縮ですがご教授いただけますと幸いです。 綺麗でなないですが下記にてコードを記載いたします。 #include <algorithm> //std::maxを使用するため #define NOMINMAX #include "DxLib.h" //当たり判定を行う関数 // // ブロック 左 x1 //        上 y1 //        横幅 w1 //        縦幅 h1 // // キャラクター 左 x2 //        上 y2 //        横幅 w2 //        縦幅 h2 int CheckHit(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) { float L1 = x1; // 左 float R1 = x1 + w1; // 右(左+横幅) float L2 = x2; // 左 float R2 = x2 + w2; // 右(左+横幅) if (R1 <= L2) return 0; //< 線上も当たらないことにする if (R2 <= L1) return 0; //< 線上も当たらないことにする float U1 = y1; // 上 float D1 = y1 + h1; // 下(上+縦幅) float U2 = y2; // 上 float D2 = y2 + h2; // 下(上+縦幅) if (D1 <= U2) return 0; //< 線上も当たらないことにする if (D2 <= U1) return 0; //< 線上も当たらないことにする // それ以外の場合は当たっている return 1; } /*-----定義-----*/ //スクリーンの縦、横の大きさ #define SCEEN_HEIGHT     640 #define SCEEN_WIDTH 480 //================================================================= //ステージ用変数と定義 //================================================================= //ステージの縦横幅 #define STAGE_HEIGHT     15 #define STAGE_WIDTH 20 //ブロックの大きさ #define BLOCK_SIZE 32 int g_NUM_MAP_X = 20; int g_NUM_MAP_Y = 15; int g_stage[]= { 0,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,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, }; //================================================================= //プレイヤー用変数と定義 //================================================================= //プレイヤーの大きさ #define PLAYER_SIZE 32 //プレイヤーのX,Y軸 float g_PlayerX; float g_PlayerY; //ジャンプ関数 float g_JumpPower; //プレイヤーの前回位置 float g_old_x = 0.0f; float g_old_y = 0.0f; //キー入力用キャラ型 char g_Key[256]; //ーーーーーーーーーーー //キャラの操作 //ーーーーーーーーーーー void PlayerMove() { //キーボードの入力値を入手する GetHitKeyStateAll(g_Key); // 前回の位置を覚えておく(関数内宣言ではない) //これが無くなると当たり判定がめちゃくちゃになる g_old_x = g_PlayerX; g_old_y = g_PlayerY; //落下処理 g_PlayerY -= g_JumpPower; //落下加速度を加える g_JumpPower -= 1.0f; //右矢印を押したら右に進 if (g_Key[KEY_INPUT_RIGHT]) { g_PlayerX += 3; } //左矢印を押したら左に進 if (g_Key[KEY_INPUT_LEFT]) { g_PlayerX -= 3; } //スペースを押したらジャンプ if (g_Key[KEY_INPUT_SPACE]){ g_JumpPower = 7.0f; //ボタンが機能しているか確認する為のボックス DrawBox(0, 0, 32, 32, GetColor(255, 255, 0), TRUE); } // プレイヤーのy軸が449以上の場合止まる // プレイヤーのy軸が0以下の場合止まる if (g_PlayerY > 449) { g_PlayerY = 449; } else if (g_PlayerY < 0) { g_PlayerY = 0; } } //ーーーーーーーーーーー //キャラの更新 //ーーーーーーーーーーー void PlayerUpdate() { PlayerMove(); } //ーーーーーーーーーーー //キャラ描画 //ーーーーーーーーーーー void PlayerDraw() { // プレイヤー描画 DrawBox(g_PlayerX, g_PlayerY, g_PlayerX + BLOCK_SIZE, g_PlayerY+ BLOCK_SIZE, GetColor(255, 255, 0), TRUE); } //ーーーーーーーーーーー //地形当たり判定 //ーーーーーーーーーーー void StageHitCheck() { //ブロックの当たり判定 for (int height = 0; height < g_NUM_MAP_Y; height++) { for (int width = 0; width < g_NUM_MAP_X; width++) { int BlockNumber = g_stage[width + height * g_NUM_MAP_X]; if (BlockNumber > 0 && BlockNumber < 2) { if (CheckHit(width * BLOCK_SIZE, height * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE,g_PlayerX, g_PlayerY, PLAYER_SIZE, PLAYER_SIZE)) { //上から当たっているか if (g_PlayerY >= g_old_y) { if (height * BLOCK_SIZE - PLAYER_SIZE >= g_old_y) { g_old_y = height * BLOCK_SIZE - PLAYER_SIZE ; g_PlayerY = g_old_y; g_JumpPower = 0.0f; } else { int CollPlayerX = std::max(g_PlayerX, g_old_x); CollPlayerX /= BLOCK_SIZE; CollPlayerX *= BLOCK_SIZE; g_PlayerX = CollPlayerX; g_old_x = g_PlayerX; } } //下から当たっている else if (g_PlayerY < g_old_y) { if ((height + 1) * BLOCK_SIZE <= g_old_y) { g_old_y = (height + 1) * BLOCK_SIZE; g_PlayerY = g_old_y; g_JumpPower = 0.0f; } else { int CollPlayerX = std::max(g_PlayerX, g_old_x); CollPlayerX /= BLOCK_SIZE; CollPlayerX *= BLOCK_SIZE; g_PlayerX = CollPlayerX; g_old_x = g_PlayerX; } } //当たり判定が機能しているか確認用 DrawBox(0, 0, 32, 32, GetColor(255, 0,0), TRUE); } } } } } //================================================================= //メイン //================================================================= int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { ChangeWindowMode(TRUE); SetGraphMode(640, 480, 16); if (DxLib_Init() == -1) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } // 描画先画面を裏画面にセット SetDrawScreen(DX_SCREEN_BACK); // キャラクターの初期位置 g_PlayerX = 0.0f; g_PlayerY = 449.0f; // ループ while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0) { // 画面を初期化する ClearDrawScreen(); ; //ステージ描画 for (int width = 0; width < g_NUM_MAP_X; width++) { for (int height = 0; height < g_NUM_MAP_Y; height++) { int MapNumber = g_stage[width + height * g_NUM_MAP_X]; if (MapNumber == 0) { DrawBox(width * BLOCK_SIZE, height * BLOCK_SIZE, width * BLOCK_SIZE + BLOCK_SIZE, height * BLOCK_SIZE + BLOCK_SIZE, GetColor(255, 255, 255), FALSE); } if (MapNumber == 1) { DrawBox(width * BLOCK_SIZE, height * BLOCK_SIZE, width * BLOCK_SIZE + BLOCK_SIZE , height * BLOCK_SIZE + BLOCK_SIZE , GetColor(255, 255, 255), TRUE); } } } //当たり判定 StageHitCheck(); //プレイヤーの描画 PlayerDraw(); //プレイヤーの更新 PlayerUpdate(); // 裏画面の内容を表画面に反映させる ScreenFlip(); } DxLib_End(); // DXライブラリ使用の終了処理 return 0; // ソフトの終了 }
メンテ

Page: 1 |

Re: ジャンプ処理について ( No.1 )
名前:たろう 日時:2022/07/28 14:06

たきさんのコードの関係のある箇所だけ抜き出すと、下のようになったのですが スペースキー長押しでg_JumpPowerがつねに7になってしまいます。 するとg_PlayerY-=g_JumpPowerでずっとキャラY位置が7引かれるので上り続けます。 なのでキャラが地面にあるときだけg_JumpPowerを7にするように変える(※コメントアウトしてある箇所) といいと思いますm(_ _)m #include "DxLib.h" float g_PlayerY = 449.0f; float g_JumpPower = 0.0f; char g_Key[256]; void PlayerMove() { GetHitKeyStateAll(g_Key); g_PlayerY -= g_JumpPower; g_JumpPower -= 1.0f; if(g_Key[KEY_INPUT_SPACE]){g_JumpPower=7.0f;} //if(g_Key[KEY_INPUT_SPACE]&&g_PlayerY>448){g_JumpPower=7.0f;} if (g_PlayerY>449){g_PlayerY=449;} } int WINAPI WinMain(HINSTANCE , HINSTANCE ,LPSTR , int ) { ChangeWindowMode(1);SetGraphMode(640,480,16);DxLib_Init();SetDrawScreen(DX_SCREEN_BACK); while (ProcessMessage()==0 && CheckHitKey(KEY_INPUT_ESCAPE)==0) { ClearDrawScreen(); DrawBox(0,g_PlayerY, 32,g_PlayerY+32, GetColor(255,255,0),1); PlayerMove(); ScreenFlip(); } DxLib_End();return 0; }
メンテ
Re: ジャンプ処理について ( No.2 )
名前:たき 日時:2022/07/28 22:53

たろうさん 返信に遅くなり申し訳ございません。 コメントアウトの部分を入力してみましたらサンプル通りの動きをしてくれました。ご教授ありがとうございます。! もう一点 気になった事があるのですが、たろうさんがご教授くださったジャンプ処理は 「もしスペースボタンを押して且プレイヤーのY座標が448以上だった場合ジャンプする」←表現が間違っていましたら申し訳ございません でありますが、もしジャンプをして着地した先のY軸が448以上だった場合、再度スペースボタンを押しても当然何も起こらないです。 初心者ながら安直な考えで、同じジャンプ処理の着地地点のY軸の数値を追加するのが正解かと考えたのですが不正解でして、 自分なりに色々考えてみたのですがアイディアが思いつかず、、、大変申し訳ないのですが、ヒントをいただいてもよろしいでしょうか もし今やろうとしている事が実は今の私のレベルでは無理でしたら、先にこれを理解/勉強したほうがいい物がございましたらご教授いただけますと幸いです。 勉強して理解しましたら再度チャレンジします!
メンテ
Re: ジャンプ処理について ( No.3 )
名前:たろう 日時:2022/07/29 01:29

すみません、よく確認せず 横移動とか天井の当たり判定まで、しっかり作ってあるとは気づきませんでしたm(_ _)m 逆にここまでできるのであればすごく簡単だと思うのですが 1 キャラが着地している(ブロックの上に立っている)とき1 落下中は0という変数(grnd)を作る 2 その変数が1のときだけジャンプできるようにする 下は一応動きましたが、数行追加しただけです。 全体を把握せず書きましたので、お手数ですがご確認の上お使いいただければと思いますm(_ _)m #include <algorithm> //std::maxを使用するため #define NOMINMAX #include "DxLib.h" //当たり判定を行う関数 // // ブロック 左 x1 //        上 y1 //        横幅 w1 //        縦幅 h1 // // キャラクター 左 x2 //        上 y2 //        横幅 w2 //        縦幅 h2 int CheckHit(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) { float L1 = x1; // 左 float R1 = x1 + w1; // 右(左+横幅) float L2 = x2; // 左 float R2 = x2 + w2; // 右(左+横幅) if (R1 <= L2) return 0; //< 線上も当たらないことにする if (R2 <= L1) return 0; //< 線上も当たらないことにする float U1 = y1; // 上 float D1 = y1 + h1; // 下(上+縦幅) float U2 = y2; // 上 float D2 = y2 + h2; // 下(上+縦幅) if (D1 <= U2) return 0; //< 線上も当たらないことにする if (D2 <= U1) return 0; //< 線上も当たらないことにする // それ以外の場合は当たっている return 1; } /*-----定義-----*/ //スクリーンの縦、横の大きさ #define SCEEN_HEIGHT     640 #define SCEEN_WIDTH 480 //================================================================= //ステージ用変数と定義 //================================================================= //ステージの縦横幅 #define STAGE_HEIGHT     15 #define STAGE_WIDTH 20 //ブロックの大きさ #define BLOCK_SIZE 32 int g_NUM_MAP_X = 20; int g_NUM_MAP_Y = 15; int g_stage[]= { 0,0,0,0,0, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,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, }; //================================================================= //プレイヤー用変数と定義 //================================================================= //プレイヤーの大きさ #define PLAYER_SIZE 32 //プレイヤーのX,Y軸 float g_PlayerX; float g_PlayerY; //ジャンプ関数 float g_JumpPower; //プレイヤーの前回位置 float g_old_x = 0.0f; float g_old_y = 0.0f; //キー入力用キャラ型 char g_Key[256]; int grnd=0; //ーーーーーーーーーーー //キャラの操作 //ーーーーーーーーーーー void PlayerMove() { //キーボードの入力値を入手する GetHitKeyStateAll(g_Key); // 前回の位置を覚えておく(関数内宣言ではない) //これが無くなると当たり判定がめちゃくちゃになる g_old_x = g_PlayerX; g_old_y = g_PlayerY; //落下処理 g_PlayerY -= g_JumpPower; //落下加速度を加える g_JumpPower -= 1.0f; //右矢印を押したら右に進 if (g_Key[KEY_INPUT_RIGHT]) { g_PlayerX += 3; } //左矢印を押したら左に進 if (g_Key[KEY_INPUT_LEFT]) { g_PlayerX -= 3; } //スペースを押したらジャンプ if ((grnd||g_PlayerY>448)&&g_Key[KEY_INPUT_SPACE]){ g_JumpPower = 17.0f; //ボタンが機能しているか確認する為のボックス DrawBox(0, 0, 32, 32, GetColor(255, 255, 0), TRUE); } // プレイヤーのy軸が449以上の場合止まる // プレイヤーのy軸が0以下の場合止まる if (g_PlayerY > 449) { g_PlayerY = 449; } else if (g_PlayerY < 0) { g_PlayerY = 0; } } //ーーーーーーーーーーー //キャラの更新 //ーーーーーーーーーーー void PlayerUpdate() { PlayerMove(); } //ーーーーーーーーーーー //キャラ描画 //ーーーーーーーーーーー void PlayerDraw() { // プレイヤー描画 DrawBox(g_PlayerX, g_PlayerY, g_PlayerX + BLOCK_SIZE, g_PlayerY+ BLOCK_SIZE, GetColor(255, 255, 0), TRUE); } //ーーーーーーーーーーー //地形当たり判定 //ーーーーーーーーーーー void StageHitCheck() {grnd=0; //ブロックの当たり判定 for (int height = 0; height < g_NUM_MAP_Y; height++) { for (int width = 0; width < g_NUM_MAP_X; width++) { int BlockNumber = g_stage[width + height * g_NUM_MAP_X]; if (BlockNumber > 0 && BlockNumber < 2) { if (CheckHit(width * BLOCK_SIZE, height * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE,g_PlayerX, g_PlayerY, PLAYER_SIZE, PLAYER_SIZE)) { //上から当たっているか if (g_PlayerY >= g_old_y) { if (height * BLOCK_SIZE - PLAYER_SIZE >= g_old_y) { g_old_y = height * BLOCK_SIZE - PLAYER_SIZE ; g_PlayerY = g_old_y; g_JumpPower = 0.0f;grnd=1; } else { int CollPlayerX = std::max(g_PlayerX, g_old_x); CollPlayerX /= BLOCK_SIZE; CollPlayerX *= BLOCK_SIZE; g_PlayerX = CollPlayerX; g_old_x = g_PlayerX; } } //下から当たっている else if (g_PlayerY < g_old_y) { if ((height + 1) * BLOCK_SIZE <= g_old_y) { g_old_y = (height + 1) * BLOCK_SIZE; g_PlayerY = g_old_y; g_JumpPower = 0.0f; } else { int CollPlayerX = std::max(g_PlayerX, g_old_x); CollPlayerX /= BLOCK_SIZE; CollPlayerX *= BLOCK_SIZE; g_PlayerX = CollPlayerX; g_old_x = g_PlayerX; } } //当たり判定が機能しているか確認用 DrawBox(0, 0, 32, 32, GetColor(255, 0,0), TRUE); } } } } } //================================================================= //メイン //================================================================= int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { ChangeWindowMode(TRUE); SetGraphMode(640, 480, 16); if (DxLib_Init() == -1) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } // 描画先画面を裏画面にセット SetDrawScreen(DX_SCREEN_BACK); // キャラクターの初期位置 g_PlayerX = 0.0f; g_PlayerY = 449.0f; // ループ while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0) { // 画面を初期化する ClearDrawScreen(); ; //ステージ描画 for (int width = 0; width < g_NUM_MAP_X; width++) { for (int height = 0; height < g_NUM_MAP_Y; height++) { int MapNumber = g_stage[width + height * g_NUM_MAP_X]; if (MapNumber == 0) { DrawBox(width * BLOCK_SIZE, height * BLOCK_SIZE, width * BLOCK_SIZE + BLOCK_SIZE, height * BLOCK_SIZE + BLOCK_SIZE, GetColor(255, 255, 255), FALSE); } if (MapNumber == 1) { DrawBox(width * BLOCK_SIZE, height * BLOCK_SIZE, width * BLOCK_SIZE + BLOCK_SIZE , height * BLOCK_SIZE + BLOCK_SIZE , GetColor(255, 255, 255), TRUE); } } } //当たり判定 StageHitCheck(); //プレイヤーの描画 PlayerDraw(); //プレイヤーの更新 PlayerUpdate(); // 裏画面の内容を表画面に反映させる ScreenFlip(); } DxLib_End(); // DXライブラリ使用の終了処理 return 0; // ソフトの終了 }
メンテ
Re: ジャンプ処理について ( No.4 )
名前:たき 日時:2022/07/29 18:31

たろうさん 確認してみました所無事ブロックの上でもジャンプができました!!(*T▽T*) まさか変数を1つ追加して数行追加するだけだとは、、、 ご教授してもらったのみならず回答まで書いていただき誠にありがとうございます!m(_ _)m 
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存