書接上回:https://www.cnblogs.com/meny233/p/18250399
新增功能:
空格控制轉彎
匯出變數
撞牆檢測
音樂播放
前戲
點選檢視程式碼
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)