[GodotDL C# D2]從空格控制轉彎到撞牆檢測

meny發表於2024-06-23

書接上回:https://www.cnblogs.com/meny233/p/18250399
新增功能:
空格控制轉彎
匯出變數
撞牆檢測
音樂播放
前戲
image

點選檢視程式碼
using Godot;
using System;

public partial class Line : CharacterBody3D
{
	[Export]
	public float Speed = 10f;
	[Export]
	public bool turn = false;
	[Export]
	public bool alive = true;
	[Export]
	public bool start = false;
	[Export]
	public MeshInstance3D tail;
	[Export]
	public AudioStreamPlayer song;
	[Export]
	public AudioStreamPlayer die;

	public override void _PhysicsProcess(double delta)
	{
		Vector3 velocity = Velocity;
		if (alive)
		{
			if (!IsOnFloor())
			{
				velocity += GetGravity() * (float)delta;
			}
			if (Input.IsActionJustPressed("ui_accept"))
			{
				if (!start)
				{
					start = true;
					song.Play();
				}
				turn = !turn;
			}
			if (start)
			{
				if (turn)
				{
					velocity.X = 0;
					velocity.Z = Speed;
				}
				else
				{
					velocity.Z = 0;
					velocity.X = Speed;
				}
			}
			if (IsOnWall())
			{
				alive = false;
				die.Play();
				song.Stop();
			}
		}
		Velocity = velocity;
		MoveAndSlide();
		MakeTail();
	}
	public void MakeTail()
	{
		//Soon
	}
}

參考
https://space.bilibili.com/508557497

點選檢視程式碼
extends CharacterBody3D

var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var lastonfloor:bool = true
var song_time:float = 0

@onready var last_linetail:MeshInstance3D = $MeshInstance3D2
@onready var fallpar:CPUParticles3D = $CPUParticles3D
@onready var body:MeshInstance3D = $MeshInstance3D
@onready var song:AudioStreamPlayer = $AudioStreamPlayer
@onready var playing_ui = $CanvasLayer/playing
@onready var end_ui = $CanvasLayer/end
@onready var start = $CanvasLayer/start
#@onready var start_ui = $start
signal go_dead
var turn:String = ''
var timeLine:Array
#@export_file('*.json') var chart_file:String

func _ready():
	body.scale = Lineinfo.scale
	last_linetail.scale = Lineinfo.scale
	playing_ui.visible = false
	end_ui.visible = false
	start.connect("startgame", Callable(self, "_start"))
	Lineinfo.connect('turn_main_line', Callable(self, 'turn_line'))
	Lineinfo.connect('jump_line', Callable(self, 'jump'))
	Lineinfo.connect("change_auto", Callable(self, "do_auto_play"))
	turn = Lineinfo.turn
	do_auto_play()
	Levelinfo.song_time = 0

func do_auto_play():
	if Lineinfo.auto_play:
		load_autoplay()
	else:
		timeLine = []
		
func load_autoplay():
	var chart := FileAccess.open(Levelinfo.chart_file, FileAccess.READ)
	if not chart:
		return
	
	var json := chart.get_as_text()
	var roadInfo:Dictionary = JSON.parse_string(json)
	timeLine = []
	while (roadInfo.note.size() > 1):
		var a_note:Array = roadInfo.note[0].beat
		var bpm:float = roadInfo.time[0].bpm
		timeLine.push_back((a_note[0]*60/bpm)+(60/bpm/4*(a_note[1]+1)))
		roadInfo.note.remove_at(0)
		
func jump():
	velocity.y += Lineinfo.jump_velocity
	
func _physics_process(delta):
	if Lineinfo.auto_play and timeLine.size() > 0:
		if Levelinfo.song_time >= timeLine[0]:
			turn_line()
			timeLine.remove_at(0)
	
	if not Lineinfo.auto_play:
		turn = Lineinfo.turn
		
	if Lineinfo.can_fall:
		if not is_on_floor():
			velocity.y -= gravity * delta
			lastonfloor = false
		else:
			if not lastonfloor:
				var fall:CPUParticles3D = fallpar.duplicate()
				add_child(fall)
				fall.top_level = true
				fall.position = global_position
				fall.emitting = true
				lastonfloor = true
				make_line()
			
	move_and_slide()
	
	if is_on_wall():
		go_die()
		
	var SPEED:float = Lineinfo.speed
	if Levelinfo.started and not Lineinfo.dead and Lineinfo.can_move:
		if turn == 'left':
			position.x += delta * -SPEED
			if is_on_floor() or not Lineinfo.can_fall:
				last_linetail.scale.x += delta *SPEED
				if last_linetail.top_level:
					last_linetail.position.x += delta * -SPEED/2
				else:
					last_linetail.position.x += delta * SPEED/2
		elif turn == 'up':
			position.z += delta * -SPEED
			if is_on_floor() or not Lineinfo.can_fall:
				last_linetail.scale.z += delta * SPEED
				if last_linetail.top_level:
					last_linetail.position.z += delta * -SPEED/2
				else:
					last_linetail.position.z += delta * SPEED/2
		elif turn == 'down':
			position.z += delta * SPEED
			if is_on_floor() or not Lineinfo.can_fall:
				last_linetail.scale.z += delta * SPEED
				if last_linetail.top_level:
					last_linetail.position.z += delta * SPEED/2
				else:
					last_linetail.position.z += delta * -SPEED/2
		elif turn == 'right':
			position.x += delta * SPEED
			if is_on_floor() or not Lineinfo.can_fall:
				last_linetail.scale.x += delta *SPEED
				if last_linetail.top_level:
					last_linetail.position.x += delta * SPEED/2
				else:
					last_linetail.position.x += delta * -SPEED/2
					
		Lineinfo.moving = true
	else:
		Lineinfo.moving = false
		
	if Input.is_action_just_pressed("play"):
		turn_line()
	
	if song.playing:
		song_time += delta
		Levelinfo.song_time = song_time
	
	Levelinfo.song_percent = int(song_time / (song.stream.get_length() - 40) *100)

func go_die():
	if not Lineinfo.dead:
		song.stop()
		$AudioStreamPlayer2.play()
		$CPUParticles3D2.emitting = true
		end_ui.visible = true
		playing_ui.visible = false
		Lineinfo.dead = true

func _input(event):
	if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT and (is_on_floor() or not Lineinfo.can_fall) and not Lineinfo.dead and Lineinfo.can_control:
		if Lineinfo.auto_play and Levelinfo.started:
			return
			
		turn_line()
		
func _start():
	start.visible = false

func turn_line():
	if not start.visible:
		if not Levelinfo.started:
			Levelinfo.started = true
			var offset:float = Levelinfo.offset
			if offset > 0:
				var tween = create_tween()
				tween.tween_interval(offset/1000)
				tween.tween_callback(playsong)
			elif offset <= 0:
				song.play()
				song.seek(-offset/1000)
			
			#song_time += offset/1000
			playing_ui.visible = true
			return
		
		if Lineinfo.next_turn != '':
			Lineinfo.turn = Lineinfo.next_turn
			Lineinfo.next_turn = ''
		else:
			if Lineinfo.auto_play:
				if turn == 'left':
					turn = 'up'
				elif turn == 'up':
					turn = 'left'
				elif turn == 'down':
					turn = 'right'
				elif turn == 'right':
					turn = 'down'
			else:	
				if Lineinfo.turn == 'left':
					Lineinfo.turn = 'up'
				elif Lineinfo.turn == 'up':
					Lineinfo.turn = 'left'
				elif Lineinfo.turn == 'down':
					Lineinfo.turn = 'right'
				elif Lineinfo.turn == 'right':
					Lineinfo.turn = 'down'
	
		make_line()
		
func playsong():
	song.play()

func make_line():
	last_linetail.top_level = true
	var linetail:MeshInstance3D = $MeshInstance3D2.duplicate()
	linetail.position = body.position
	linetail.scale = body.scale
	last_linetail = linetail
	add_child(linetail)

相關文章