extends Node2D

# 生成するシーン
var obj_floor = preload("res://Floor.tscn") # 床オブジェクト
var obj_spike = preload("res://Spike.tscn") # スパイクオブジェクト

const TIMER_SHAKE = 0.5 # 0.5秒の間揺らす

# 状態
enum eState {
	MAIN, # メイン.
	GAMEOVER, # ゲームオーバー.
}

# カメラの座標関連
const CAMERA_POS_Y = 320 # カメラの位置(Y).
const CAMERA_OFS_X = 400 # プレイヤーからのオフセット
const FLOOR_INTERVAL = 64 # 足場は 64px 単位で登場する.
const SCREEN_W = 1024 # 画面の幅.

onready var _player = $Player # プレイヤー.
onready var _camera = $Camera2D # カメラ.
onready var _field_mgr = $FieldMgr # フィールド管理.
onready var _labelSpeed = $CanvasLayer/LabelSpeed
onready var _labelGameover = $CanvasLayer/LabelGameover

var _prev_x:float = 0 # 前回の座標(X)
var _prev_y:float = 320 # 前回の座標(Y)
var _cnt_create:int = 0 # 足場を生成した回数.
var _timer:float = 0 # 経過時間.
var _state = eState.MAIN # 状態.
var _tShake: float = 0 # 画面揺らすタイマー.

func _ready() -> void:
	# プレイヤーの初期位置を設定しておく.
	_prev_x = _player.position.x

func _process(delta: float) -> void:
	match _state:
		eState.MAIN:
			_update_main(delta)
		eState.GAMEOVER:
			_update_gameover(delta)

# 更新 > メイン.
func _update_main(delta:float) -> void:
	if is_instance_valid(_player) == false:
		# プレイヤーが消滅したらゲームオーバー.
		_tShake = TIMER_SHAKE # 揺れ開始.
		_state = eState.GAMEOVER
		return
	
	if _player.position.y > 640:
		# 落下死.
		_player.queue_free()
		return
		
	# カメラをプレイヤーに追従させる.
	_camera.position.x = _player.position.x + CAMERA_OFS_X
	
	# 足場の生成チェック.
	_check_floor()
	
	# 時間経過に合わせてプレイヤーの速度を変更する
	_timer += delta
	_player.set_speed(200 + _timer * 30)	
	
	# 現在のスピードを表示.
	_labelSpeed.text = "SPEED: %d"%_player.get_speed()
	
	# 画面外に出た足場を消す.
	for child in _field_mgr.get_children():
		if child.position.x < _player.position.x - 100:
			child.queue_free()
			
# 更新 > ゲームオーバー.
func _update_gameover(delta: float) -> void:
	# "GAME OVER" を表示
	_labelGameover.visible = true
	
	# 画面揺らす
	_camera.offset = Vector2.ZERO
	_tShake -= delta
	if _tShake > 0:
		var rate = _tShake / TIMER_SHAKE
		var vx = 64 * rate
		var vy = 16 * rate
		_camera.offset.x = rand_range(-vx, vx)
		_camera.offset.y = rand_range(-vy, vy)
		# 画面揺れ中はリスタートできなくする.
		return
	
	if Input.is_action_just_pressed("ui_accept"):
		# Spaceキーでリスタート
		get_tree().change_scene("res://Main.tscn")

# 足場の出現チェック.
func _check_floor() -> void:
	# FLOOR_INTERVALの単位になるようにする.
	var prev = floor(_prev_x / FLOOR_INTERVAL) * FLOOR_INTERVAL # 前回.
	var now = floor(_player.position.x / FLOOR_INTERVAL) * FLOOR_INTERVAL # 現在値.

	if prev != now:
		# 出現タイミングになった.
		_cnt_create += 1 # 生成カウンタをアップする.
		
		if _cnt_create%9 == 8:
			# 出現座標(Y)を更新する.
			var y = _prev_y + (randi()%8 - 4) * 32
			if y < 200:
				y = 200 # 200よりも上にならないようにする
			if y > 540:
				y = 540 # 540よりも下にならないようにする
			_prev_y = y
		if _cnt_create%9 < 6:
			# (0〜5)なら床出現.
			_create_floor(now, _prev_y)
		# -----------------------------------
		# ※ここを追加
		if _cnt_create%19 == 0:
			# スパイク出現.
			_create_spike(now, _prev_y)
		# -----------------------------------		
	
	# 今回のプレイヤー位置を保存しておく.
	_prev_x = _player.position.x
	
# 足場を生成する.
func _create_floor(px:float, py:float) -> void:
	var obj = obj_floor.instance()
	obj.position.x = px + SCREEN_W
	obj.position.y = py
	_field_mgr.add_child(obj)

# スパイク生成.
func _create_spike(px: float, py: float) -> void:
	var obj = obj_spike.instance()
	obj.position.x = px + SCREEN_W
	obj.position.y = py - 64 - 32 * (randi()%4) # ランダムで床の上に生成する
	_field_mgr.add_child(obj)
