Robloxで二段ジャンプする

# 概要
- アクションゲームでよくある二段ジャンプ
- 公式ページから画像拝借
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206887/55d0ab41-d5e9-9d24-7390-bca3c191d4ce.png)


# ファイル構成
- StarterPlayerフォルダの中の、StarterPlayerScriptsフォルダの中に、「LocalScript」を追加します。いつも使っているScriptとは違うので要注意。
- 名前はDoubleJumpとかにしておきましょう
- LocalScriptとScriptの違いについてはいずれ説明します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206887/c7dec183-8960-6fc6-5bb3-689abd455b28.png)


# プログラミング
``` DoubleJump.lua
-- 「XXボタンを押したとき」というプログラミングを使いたいときにこれが必要
local UserInputService = game:GetService("UserInputService")

-- Workspaceの隣にあるPlayersフォルダのPropertyに「LocalPlayer」というパラメタがある
-- ここにはプレイしているユーザ本人の名前が入っている
local localPlayer = game.Players.LocalPlayer

-- あとでつかう変数を準備
local character
local humanoid 
local canDoubleJump = false
local hasDoubleJumped = false
local oldPower

-- ジャンプのタイミングとか強さを調整するための変数
local TIME_BETWEEN_JUMPS = 0.2
local DOUBLE_JUMP_POWER_MULTIPLIER = 2

-- ダブルジャンプするための関数 
-- スペースキーをおしたときに起動する
function onJumpRequest()
	-- 以下の場合は何もしない
	-- 1.キャラが存在しない
	-- 2.humanoidがない
	-- 3.キャラがWorｋｓpace上にいない
	-- 4.すでに死んでいる場合
	if not character or not humanoid or not character:IsDescendantOf(workspace) or
	 humanoid:GetState() == Enum.HumanoidStateType.Dead then
		return
	end
	
	-- 上の４通りのどれにも一致しない、かつ
	-- ダブルジャンプできる場合は、ダブルジャンプする
	-- つまり、ジャンプ後に落下してる、かつ二段ジャンプ中ではないとき
	if canDoubleJump and not hasDoubleJumped then
		-- 変数で、「二段ジャンプ中」の状態にする
		hasDoubleJumped = true
		-- ジャンプ力を、二倍にする
		humanoid.JumpPower = oldPower * DOUBLE_JUMP_POWER_MULTIPLIER
		-- humanoidが持つ状態を「ジャンプ中」にする
		-- これが実際にキャラクターがジャンプするということになる
		humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
	end
end
 
-- キャラクターがゲームに入ってきたときに起動する
local function characterAdded(newCharacter)
	-- 入ってきたキャラを変数に保存しておく
	character = newCharacter
	-- 入ってきたキャラのHumanoidを変数に保存しておく
	-- Humanoidを探すのにやや時間がかかるので、「みつかるまで待つ」というプログラミング
	humanoid = newCharacter:WaitForChild("Humanoid")
	
	-- まず変数を初期化
	hasDoubleJumped = false
	canDoubleJump = false
	
	-- いまのジャンプ力を保存しておく
	oldPower = humanoid.JumpPower
	
	-- キャラの状態が変更されたときに起動する
	-- キャラの状態が変更されると毎回これが起動される
	-- Scratchでいうと「ずっと」で囲まれているのと同じ
	humanoid.StateChanged:connect(function(old, new)
		-- oldには変更前の状態が入ってる
		-- newには変更後の状態が入ってる
		
		-- もし変更後が地面の上に立ってる状態なら
		-- 「２段ジャンプはできない　（１回目のジャンプはできる）」
		-- 「二段ジャンプ中ではない」
		-- 「ジャンプ力は通常にする」
		if new == Enum.HumanoidStateType.Landed then
			canDoubleJump = false
			hasDoubleJumped = false
			humanoid.JumpPower = oldPower
			
		-- もし変更後が落下中なら
		-- 「0.2秒まってから」
		-- 「ダブルジャンプ可能」にする
		elseif new == Enum.HumanoidStateType.Freefall then
			wait(TIME_BETWEEN_JUMPS)
			canDoubleJump = true
		end
	end)
end
 
-- たまにプレイヤーがスポーンしおわってからこのスクリプトが読み込まれる場合がある
-- そうなると、下にある「localPlayer.CharacterAdded:connect(characterAdded)」が反応しない
-- その場合を考えて、すでにPlayersの中のLocalPlayer内に名前が入ってるなら、characterAdded関数を起動するようにする
if localPlayer.Character then
	characterAdded(localPlayer.Character)
end
 
-- プレイヤーがスポーンしたタイミングでcharacterAdded関数を起動
localPlayer.CharacterAdded:connect(characterAdded)
-- プレイヤーがスペースキーをおしてジャンプする際に、onJumpRequest関数を起動
UserInputService.JumpRequest:connect(onJumpRequest)


```

# チャレンジ課題
- humanoid:ChangeState(Enum.HumanoidStateType.Jumping)を理解するために、「何もしなくても勝手にジャンプしつづける」を作ってみましょう。
- 他の状態にも切り替えてみましょう。
    - 参考：https://developer.roblox.com/en-us/api-reference/enum/HumanoidStateType