using Godot; using System; using System.Collections.Generic; using System.Linq; using Models; // ReSharper disable CheckNamespace public partial class Student : CharacterBody2D { public float Speed { get; set; } = 8.0f; public const float JumpVelocity = -400.0f; [Export] public bool Use16x16Sprites { get; set; } = false; // --- MVP: Model Binding --- public StudentModel Model { get; private set; } public void BindData(StudentModel model) { Model = model; GD.Print($"Student bound to model: {Model.Name}"); } // -------------------------- public int NextType = -1; private Queue 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 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)) return; if (TargetDirection == Direction.Up) { } animationPlayer.Play("idle_front"); State = StateQueue.Dequeue(); GlobalPosition = targetSpecialPosition; } private void GettingUp(double delta) { duration += delta; if (!(duration > 0.3)) return; 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) return; 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"); // var bb = bt.Blackboard; // bb.BindVarToProperty("Stayed", this, "Speed"); // GD.Print(bb.GetVar("Stayed")); // GD.Print($"Speed: {Speed}"); animationPlayer = GetNode("AnimationPlayer"); animationPlayer.Play("idle_front"); var name_test = GetNode("StudentName"); // MVP: Initialize Model if null if (Model == null) { Model = new StudentModel(name_test.GenerateName()); GD.Print($"[Auto-Init] Student: {Model.Name}"); } else { GD.Print("生成的名字是: " + name_test.GenerateName()); // Keep original log for reference } } public void MoveFollowPath(List 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(); 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(); 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("parts/body").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.BODY, Use16x16Sprites)); GetNode("parts/hairstyle").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.HAIR, Use16x16Sprites)); GetNode("parts/outfit").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.OUTFIT, Use16x16Sprites)); GetNode("parts/eye").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.EYE, Use16x16Sprites)); GetNode("parts/accessory").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.ACCESSORY, Use16x16Sprites)); GetNode("parts/smartphone").Texture = ResourceLoader.Load(Res.GetRandom(Res.Type.PHONE, Use16x16Sprites)); } }