243 lines
7.0 KiB
C#
243 lines
7.0 KiB
C#
using Godot;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
public partial class Student : CharacterBody2D
|
|
{
|
|
public float Speed { get; set; } = 8.0f;
|
|
public const float JumpVelocity = -400.0f;
|
|
|
|
public int NextType = -1;
|
|
|
|
private Queue<Vector2I> PathToGo = new();
|
|
private AnimationPlayer animationPlayer;
|
|
public enum CharacterState { Idle, Walking, Sitting, SittingDown, StandingUp }
|
|
public CharacterState State { get; set; } = CharacterState.Idle;
|
|
public enum Direction { Up, Down, Left, Right }
|
|
public Direction TargetDirection { get; set; } = Direction.Up;
|
|
|
|
public Queue<CharacterState> StateQueue { get; set; } = new();
|
|
|
|
private Vector2I targetSpecialPosition;
|
|
private Vector2I lastWalkablePosition;
|
|
private double duration = 0;
|
|
|
|
|
|
private void SitDown(double delta) {
|
|
duration += delta;
|
|
if (duration > 0.3) {
|
|
if (TargetDirection == Direction.Up) {
|
|
|
|
}
|
|
animationPlayer.Play("idle_front");
|
|
State = StateQueue.Dequeue();
|
|
GlobalPosition = targetSpecialPosition;
|
|
}
|
|
}
|
|
|
|
private void GettingUp(double delta) {
|
|
duration += delta;
|
|
if (duration > 0.3) {
|
|
State = StateQueue.Dequeue();
|
|
GlobalPosition = lastWalkablePosition;
|
|
}
|
|
}
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
if (StateQueue.Count > 0) {
|
|
// GD.Print($"{State} -> {StateQueue.Peek()}");
|
|
if (StateQueue.Peek() == CharacterState.Sitting && State == CharacterState.SittingDown) {
|
|
SitDown(delta);
|
|
return; // do not handle potentially conflicting command
|
|
}
|
|
|
|
if (StateQueue.Peek() == CharacterState.StandingUp && State == CharacterState.Sitting) {
|
|
duration = 0;
|
|
State = StateQueue.Dequeue();
|
|
return;
|
|
}
|
|
|
|
if (StateQueue.Peek() == CharacterState.Walking && State == CharacterState.StandingUp) {
|
|
GettingUp(delta);
|
|
return;
|
|
}
|
|
} else {
|
|
// GD.Print($"{State} -> Empty");
|
|
}
|
|
|
|
if (PathToGo.Count == 0)
|
|
{
|
|
if (State == CharacterState.Walking) {
|
|
if (StateQueue.Count > 0) {
|
|
if (StateQueue.Peek() == CharacterState.SittingDown) {
|
|
duration = 0;
|
|
}
|
|
State = StateQueue.Dequeue();
|
|
}
|
|
if (State == CharacterState.Idle) {
|
|
animationPlayer.Play("idle_front");
|
|
}
|
|
}
|
|
return;// No path to follow.
|
|
}
|
|
|
|
if (State != CharacterState.Walking) return;
|
|
|
|
Vector2 velocity = new();
|
|
var nextPoint = PathToGo.Peek();
|
|
if ((int)GlobalPosition.X == nextPoint.X && (int)GlobalPosition.Y == nextPoint.Y)
|
|
{
|
|
PathToGo.Dequeue();
|
|
return;
|
|
}
|
|
|
|
if ((int)GlobalPosition.X == nextPoint.X)
|
|
{
|
|
// Move Y
|
|
// velocity.Y = Math.Max(Speed, Math.Abs(nextPoint.Y - GlobalPosition.Y));
|
|
velocity.Y = Speed;
|
|
if (GlobalPosition.Y > nextPoint.Y)
|
|
{
|
|
animationPlayer.Play("walk_up");
|
|
velocity.Y = -velocity.Y;
|
|
} else {
|
|
animationPlayer.Play("walk_down");
|
|
}
|
|
}
|
|
else if ((int)GlobalPosition.Y == nextPoint.Y)
|
|
{
|
|
// move X
|
|
// velocity.X = Math.Max(Speed, Math.Abs(nextPoint.X - GlobalPosition.X));
|
|
velocity.X = Speed;
|
|
if (GlobalPosition.X > nextPoint.X)
|
|
{
|
|
|
|
animationPlayer.Play("walk_left");
|
|
velocity.X = -velocity.X;
|
|
} else {
|
|
animationPlayer.Play("walk_right");
|
|
}
|
|
}
|
|
GlobalPosition = GlobalPosition with
|
|
{
|
|
X = GlobalPosition.X + velocity.X,
|
|
Y = GlobalPosition.Y + velocity.Y
|
|
};
|
|
|
|
// GD.Print($"{GlobalPosition} -> {nextPoint}");
|
|
|
|
// Velocity = velocity;
|
|
// MoveAndSlide();
|
|
}
|
|
|
|
public override void _Ready()
|
|
{
|
|
base._Ready();
|
|
// var bt = GetNode<BTPlayer>("BTPlayer");
|
|
// var bb = bt.Blackboard;
|
|
// bb.BindVarToProperty("Stayed", this, "Speed");
|
|
// GD.Print(bb.GetVar("Stayed"));
|
|
// GD.Print($"Speed: {Speed}");
|
|
animationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
|
|
animationPlayer.Play("idle_front");
|
|
var name_test = GetNode<StudentName>("StudentName");
|
|
GD.Print("生成的名字是: " + name_test.GenerateName());
|
|
}
|
|
|
|
public void MoveFollowPath(List<Vector2I> path)
|
|
{
|
|
foreach (var p in path)
|
|
{
|
|
PathToGo.Enqueue(new Vector2I(p.X * 48 + 24, p.Y * 48 + 24));
|
|
}
|
|
}
|
|
|
|
public Guid CubeId;
|
|
|
|
public void GoTo() {
|
|
if (State == CharacterState.SittingDown || State == CharacterState.StandingUp || State == CharacterState.Walking)
|
|
{
|
|
return;
|
|
}
|
|
var lab = GetParentOrNull<Lab>();
|
|
if (lab == null)
|
|
{
|
|
return;
|
|
}
|
|
Vector2I vec = Vector2I.Zero;
|
|
while ((lab.GetMapNodeTypeOfPosition(vec) & Lab.MapNodeType.Walkable) == 0) {
|
|
vec.X = GD.RandRange(0, Lab.MAP_WIDTH);
|
|
vec.Y = GD.RandRange(0, Lab.MAP_HEIGHT);
|
|
}
|
|
var pos = GlobalPosition;
|
|
if (State == CharacterState.Sitting) {
|
|
StateQueue.Enqueue(CharacterState.StandingUp);
|
|
StateQueue.Enqueue(CharacterState.Walking);
|
|
pos = lastWalkablePosition;
|
|
} else if (State == CharacterState.Idle) {
|
|
State = CharacterState.Walking;
|
|
}
|
|
StateQueue.Enqueue(CharacterState.Idle);
|
|
MoveFollowPath(lab.GetShortestPath(lab.Point2Coord(pos), vec));
|
|
randomChangeBody();
|
|
}
|
|
|
|
public void GoToSeat() {
|
|
if (State == CharacterState.SittingDown || State == CharacterState.StandingUp || State == CharacterState.Walking)
|
|
{
|
|
return;
|
|
}
|
|
var lab = GetParentOrNull<Lab>();
|
|
if (lab == null)
|
|
{
|
|
return;
|
|
}
|
|
var i = GD.RandRange(0,1);
|
|
var target = lab.GetFurSpecialPosition(CubeId, i);
|
|
if (i == 1) {
|
|
// Seat up
|
|
TargetDirection = Direction.Up;
|
|
targetSpecialPosition = new Vector2I(target.X * 48 + 24, target.Y * 48 + 12);
|
|
} else {
|
|
TargetDirection = Direction.Down;
|
|
targetSpecialPosition = new Vector2I(target.X * 48 + 24, target.Y * 48 + 18);
|
|
}
|
|
var pos = GlobalPosition;
|
|
if (State == CharacterState.Sitting) {
|
|
StateQueue.Enqueue(CharacterState.StandingUp);
|
|
StateQueue.Enqueue(CharacterState.Walking);
|
|
pos = lastWalkablePosition;
|
|
} else if (State == CharacterState.Idle) {
|
|
State = CharacterState.Walking;
|
|
}
|
|
StateQueue.Enqueue(CharacterState.SittingDown);
|
|
StateQueue.Enqueue(CharacterState.Sitting);
|
|
var path = lab.GetShortestPath(lab.Point2Coord(pos), target);
|
|
lastWalkablePosition = new Vector2I(path.Last().X * 48 + 24, path.Last().Y * 48 + 24);
|
|
// if (lastWalkablePosition.X < targetSpecialPosition.X) {
|
|
// TargetDirection = Direction.Right;
|
|
// } else if (lastWalkablePosition.X > targetSpecialPosition.X) {
|
|
// TargetDirection = Direction.Left;
|
|
// } else {
|
|
// if (lastWalkablePosition.Y < targetSpecialPosition.Y) {
|
|
// TargetDirection = Direction.Up;
|
|
// } else if (lastWalkablePosition.Y > targetSpecialPosition.Y) {
|
|
// TargetDirection = Direction.Down;
|
|
// }
|
|
// }
|
|
MoveFollowPath(path);
|
|
randomChangeBody();
|
|
}
|
|
|
|
private void randomChangeBody()
|
|
{
|
|
GetNode<Sprite2D>("parts/body").Texture = (Texture2D)ResourceLoader.Load(Res.GetRandom(Res.Type.BODY));
|
|
GetNode<Sprite2D>("parts/hairstyle").Texture = (Texture2D)ResourceLoader.Load(Res.GetRandom(Res.Type.HAIR));
|
|
GetNode<Sprite2D>("parts/outfit").Texture = (Texture2D)ResourceLoader.Load(Res.GetRandom(Res.Type.OUTFIT));
|
|
GetNode<Sprite2D>("parts/eye").Texture = (Texture2D)ResourceLoader.Load(Res.GetRandom(Res.Type.EYE));
|
|
GetNode<Sprite2D>("parts/accessory").Texture = (Texture2D)ResourceLoader.Load(Res.GetRandom(Res.Type.ACCESSORY));
|
|
GetNode<Sprite2D>("parts/smartphone").Texture = (Texture2D)ResourceLoader.Load(Res.GetRandom(Res.Type.PHONE));
|
|
}
|
|
}
|