一定速度で上昇して、ある高さまで行ったら落ちてくる処理
(ジャンプって呼べるのかなぁ)

Listing. 1: ただ上がって下がる(軌道が三角になる。。。)
"theMain.cpp"
#include "DxLib.h"
#include "Input.h"
 
//位置を表す構造体
struct Vec2D
{
	float x;
	float y;
};
 
enum CHR_STATE
{
	IDLE, //アイドリング
	WALK, //歩き
	MAX_CHR_STATE //最大値
};
 
 
namespace
{
	const int WIN_WIDTH = 1024;
	const int WIN_HEIGHT = 768;
	int hGroundImage = -1;
	float groundH = 600;
	int BoxW = 64;
	int BoxH = 128;
	Vec2D BoxPos = { 100, groundH - BoxH };
	float speed = 0;
	float accel = 300;
	float friction = 600;
	const float MAX_SPEED = 500;//最大スピード
	CHR_STATE myState = IDLE;
	int crrTime;
	int prevTime;
	bool isJump = false;//false:ジャンプしてない true:ジャンプしてる
	const float jumpH = 300;
	int jsign = -1;//上昇中か、下降中か
}
 
void DxInit()
{
	ChangeWindowMode(true);
	SetWindowSizeChangeEnableFlag(false, false);
	SetMainWindowText("TITLE");
	SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32);
	SetWindowSizeExtendRate(1.0);
	SetBackgroundColor(255, 250, 205);
 
	// DXライブラリ初期化処理
	if (DxLib_Init() == -1)
	{
		DxLib_End();
	}
 
	SetDrawScreen(DX_SCREEN_BACK);
 
}
 
 
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
	DxInit();
 
	hGroundImage = LoadGraph("Image\\bg_dote.jpg");
 
	crrTime = GetNowCount();
	prevTime = GetNowCount();
	bool isAccOff = false;//偽を入れておく true:アクセルオフ, false:アクセルオン
 
	while (true)
	{
		ClearDrawScreen();
		Input::KeyStateUpdate();
 
		//ここにやりたい処理を書く
		//画像自体を画面の大きさに合わせてもいいよ
		//DrawRotaGraph(WIN_WIDTH /2, WIN_HEIGHT /2, 
		//	          WIN_WIDTH /(float)groundH, 0, hGroundImage, FALSE, FALSE);
 
		static float chrSpeed = 0;//歩いてたらspeed,歩いてなかったら0
		static float sign = 0; //右向いてるか左向いてるか 右 1, 左 -1
 
 
		crrTime = GetNowCount();
		float deltaTime = (crrTime - prevTime) / 1000.0;//フレーム間時間(s)
 
 
		DrawExtendGraph(0, 0, WIN_WIDTH, WIN_HEIGHT + 1, hGroundImage, FALSE);
		DrawLine(0, groundH, WIN_WIDTH, groundH, GetColor(255, 0, 0), 2);
		if (Input::IsKeyDown(KEY_INPUT_LEFT) || Input::IsKeyDown(KEY_INPUT_A)) {
			myState = WALK;
			sign = -1.0;
			isAccOff = false;
		}
		else if (Input::IsKeyDown(KEY_INPUT_RIGHT) || Input::IsKeyDown(KEY_INPUT_D))
		{
			myState = WALK;
			sign = 1.0f;
			isAccOff = false;
		}
 
		if (Input::IsKeyUP(KEY_INPUT_LEFT) || Input::IsKeyUP(KEY_INPUT_A)) {
			isAccOff = true;
		}
		else if (Input::IsKeyUP(KEY_INPUT_RIGHT) || Input::IsKeyUP(KEY_INPUT_D))
		{
			isAccOff = true;
		}
 
		if (Input::IsKeyDown(KEY_INPUT_SPACE))
		{
			isJump = true;
		}
 
		if (myState == WALK)
		{
			if (isAccOff == true) {
				speed -= friction * deltaTime;
				if (speed <= 0) {
					speed = 0;
					isAccOff = false;
					myState = IDLE;
				}
				chrSpeed = speed;
			}
			else {
				speed += accel * deltaTime;
				chrSpeed = min(MAX_SPEED, speed);//これspeedそのまま使えばよくね?
				//min(a,b)はaとbの小さいほうを返す(a,b)の型は同じ
			}
		}
		else {
			speed = 0;
			chrSpeed = 0;
		}
 
		BoxPos.x = BoxPos.x + sign * chrSpeed * deltaTime;
		if (isJump == true)
		{
 
			if (jsign == -1 && BoxPos.y < groundH - BoxH - jumpH)
				jsign =  1;
 
			if (jsign == 1 && BoxPos.y > groundH - BoxH)
			{
				jsign = -1;
				isJump = false;
				BoxPos.y = groundH - BoxH;
			}
 
			BoxPos.y = BoxPos.y + jsign * MAX_SPEED * deltaTime;
 
		}
 
 
		DrawBox(BoxPos.x, BoxPos.y, BoxPos.x + BoxW, BoxPos.y + BoxH, GetColor(0, 255, 0), TRUE);
		DrawFormatString(20, 20, GetColor(0, 0, 0), "%d", myState);
 
		DrawFormatString(20, 50, GetColor(0, 0, 0), "%lf", deltaTime);
 
		ScreenFlip();
		WaitTimer(16);
 
		prevTime = crrTime;
 
		if (ProcessMessage() == -1)
			break;
		if (CheckHitKey(KEY_INPUT_ESCAPE) == 1)
			break;
	}
 
	DxLib_End();
	return 0;
}

物理の式を使ったジャンプを実装していく

Listing. 2: 鉛直投げ上げの式からジャンプの軌道を描く(準備)
"theMain.cpp"
#include "DxLib.h"
#include "Input.h"
 
//位置を表す構造体
struct Vec2D
{
	float x;
	float y;
};
 
enum CHR_STATE
{
	IDLE, //アイドリング
	WALK, //歩き
	MAX_CHR_STATE //最大値
};
 
 
namespace
{
	const int WIN_WIDTH = 1024;
	const int WIN_HEIGHT = 768;
	int hGroundImage = -1;
	float groundH = 600;
	int BoxW = 64;
	int BoxH = 128;
	Vec2D BoxPos = { 100, groundH - BoxH };
	float speed = 0;
	float accel = 300;
	float friction = 600;
	const float MAX_SPEED = 500;//最大スピード
	CHR_STATE myState = IDLE;
	int crrTime;
	int prevTime;
	bool isJump = false;//false:ジャンプしてない true:ジャンプしてる
	const float jumpH = 300;
	int jsign = -1;//上昇中か、下降中か
}
 
void DxInit()
{
	ChangeWindowMode(true);
	SetWindowSizeChangeEnableFlag(false, false);
	SetMainWindowText("TITLE");
	SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32);
	SetWindowSizeExtendRate(1.0);
	SetBackgroundColor(255, 250, 205);
 
	// DXライブラリ初期化処理
	if (DxLib_Init() == -1)
	{
		DxLib_End();
	}
 
	SetDrawScreen(DX_SCREEN_BACK);
 
}
 
 
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
	DxInit();
 
	hGroundImage = LoadGraph("Image\\bg_dote.jpg");
 
	crrTime = GetNowCount();
	prevTime = GetNowCount();
	bool isAccOff = false;//偽を入れておく true:アクセルオフ, false:アクセルオン
 
	while (true)
	{
		ClearDrawScreen();
		Input::KeyStateUpdate();
 
		//ここにやりたい処理を書く
		//画像自体を画面の大きさに合わせてもいいよ
		//DrawRotaGraph(WIN_WIDTH /2, WIN_HEIGHT /2, 
		//	          WIN_WIDTH /(float)groundH, 0, hGroundImage, FALSE, FALSE);
 
		static float chrSpeed = 0;//歩いてたらspeed,歩いてなかったら0
		static float sign = 0; //右向いてるか左向いてるか 右 1, 左 -1
 
 
		crrTime = GetNowCount();
		float deltaTime = (crrTime - prevTime) / 1000.0;//フレーム間時間(s)
 
 
		DrawExtendGraph(0, 0, WIN_WIDTH, WIN_HEIGHT + 1, hGroundImage, FALSE);
		DrawLine(0, groundH, WIN_WIDTH, groundH, GetColor(255, 0, 0), 2);
		if (Input::IsKeyDown(KEY_INPUT_LEFT) || Input::IsKeyDown(KEY_INPUT_A)) {
			myState = WALK;
			sign = -1.0;
			isAccOff = false;
		}
		else if (Input::IsKeyDown(KEY_INPUT_RIGHT) || Input::IsKeyDown(KEY_INPUT_D))
		{
			myState = WALK;
			sign = 1.0f;
			isAccOff = false;
		}
 
		if (Input::IsKeyUP(KEY_INPUT_LEFT) || Input::IsKeyUP(KEY_INPUT_A)) {
			isAccOff = true;
		}
		else if (Input::IsKeyUP(KEY_INPUT_RIGHT) || Input::IsKeyUP(KEY_INPUT_D))
		{
			isAccOff = true;
		}
 
		if (Input::IsKeyDown(KEY_INPUT_SPACE))
		{
			isJump = true;
		}
 
		if (myState == WALK)
		{
			if (isAccOff == true) {
				speed -= friction * deltaTime;
				if (speed <= 0) {
					speed = 0;
					isAccOff = false;
					myState = IDLE;
				}
				chrSpeed = speed;
			}
			else {
				speed += accel * deltaTime;
				chrSpeed = min(MAX_SPEED, speed);//これspeedそのまま使えばよくね?
				//min(a,b)はaとbの小さいほうを返す(a,b)の型は同じ
			}
		}
		else {
			speed = 0;
			chrSpeed = 0;
		}
 
		BoxPos.x = BoxPos.x + sign * chrSpeed * deltaTime;
		if (isJump == true)
		{
			static float jtime = 0;
			//この間で時間と位置の式でジャンプする
 
			//if (jsign == -1 && BoxPos.y < groundH - BoxH - jumpH)
			//	jsign =  1;
 
			//if (jsign == 1 && BoxPos.y > groundH - BoxH)
			//{
			//	jsign = -1;
			//	isJump = false;
			//	BoxPos.y = groundH - BoxH;
			//}
 
			//BoxPos.y = BoxPos.y + jsign * MAX_SPEED * deltaTime;
			jtime = jtime + deltaTime;
			//地面より下に行っちゃったら、jtime=0; isJump=false;
		}
 
 
		DrawBox(BoxPos.x, BoxPos.y, BoxPos.x + BoxW, BoxPos.y + BoxH, GetColor(0, 255, 0), TRUE);
		DrawFormatString(20, 20, GetColor(0, 0, 0), "%d", myState);
 
		DrawFormatString(20, 50, GetColor(0, 0, 0), "%lf", deltaTime);
 
		ScreenFlip();
		WaitTimer(16);
 
		prevTime = crrTime;
 
		if (ProcessMessage() == -1)
			break;
		if (CheckHitKey(KEY_INPUT_ESCAPE) == 1)
			break;
	}
 
	DxLib_End();
	return 0;
}
  • game-engineer/classes/2024/game-creation-1/oreno-jump-5.txt
  • 最終更新: 15カ月前
  • by root