Something went wrong. Try again.
A card game engine for Magic: The Gathering inspired by Card Forge
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208using Godot;using Godot.Collections;using System;using System.Data;using System.Linq;
[GlobalClass]public partial class CardStateMachine : Node{ private State currentState; private CardUI cardUI; private const float DRAG_MINIMUM_THRESHOLD = 0.05f; private bool minimumDragTimeElsapsed = false; private bool played;
[Signal] public delegate void TransitionRequestedEventHandler(State from, State to);
public void Init(CardUI cardUI) { // construct card states currentState = State.Base; this.cardUI = cardUI; this.Enter(); }
public async void Enter(State state = State.None) { switch (state) { case State.None: this.Enter(currentState); break; case State.Base: if (!cardUI.IsNodeReady()) { await ToSignal(cardUI, Node.SignalName.Ready); }
cardUI.EmitSignal(CardUI.SignalName.ReparentRequested, cardUI); cardUI.color.Color = Color.Color8(0, 128, 0); cardUI.state.Text = "BASE"; cardUI.PivotOffset = Vector2.Zero; if (cardUI.tapped) { cardUI.RotationDegrees = 90.0f; cardUI.Position = new Vector2(cardUI.Position.X + 200.0f, cardUI.Position.Y); } else { cardUI.RotationDegrees = 0.0f; }
break; case State.Clicked: cardUI.color.Color = Color.Color8(255, 165, 0); cardUI.state.Text = "CLICKED"; cardUI.dropDetector.Monitoring = true; break; case State.Dragging: Node uiLayer = GetTree().GetFirstNodeInGroup("ui_layer");
if (IsInstanceIdValid(uiLayer.GetInstanceId())) { cardUI.Reparent(uiLayer); }
cardUI.color.Color = Color.Color8(0, 0, 128); cardUI.state.Text = "DRAGGING"; minimumDragTimeElsapsed = false; SceneTreeTimer thresholdTimer = GetTree().CreateTimer(DRAG_MINIMUM_THRESHOLD, false); thresholdTimer.Connect(SceneTreeTimer.SignalName.Timeout, Callable.From(() => minimumDragTimeElsapsed = true)); break; case State.Released: cardUI.color.Color = Color.Color8(148, 0, 211); cardUI.state.Text = "RELEASED"; played = false;
if (cardUI.targetedZone == CardZone.ZoneType.Battlefield) { played = true; cardUI.EmitSignal(CardUI.SignalName.ReparentRequested, cardUI); Node topLayer = GetTree().GetFirstNodeInGroup("top_layer");
if (topLayer is Main mainNode) { ManaGroveState gameState = mainNode.GetNode<ManaGroveState>("ManaGroveState"); gameState.EmitSignal(ManaGroveState.SignalName.MoveCard, [cardUI, (int)cardUI.targetedZone]); } } else { this.EmitSignal(CardStateMachine.SignalName.TransitionRequested, [(int)State.Released, (int)State.Base]); }
break; } }
public void Exit(State state = State.None) { switch (state) { case State.None: this.Exit(currentState); break; } }
public void OnInput(InputEvent @event) { switch (currentState) { case State.Clicked: if (cardUI.currentZone == CardZone.ZoneType.Battlefield) { if (cardUI.tapped) { cardUI.Position = new Vector2(cardUI.Position.X - 200.0f, cardUI.Position.Y); }
cardUI.tapped = !cardUI.tapped; this.EmitSignal(CardStateMachine.SignalName.TransitionRequested, [(int)State.Clicked, (int)State.Base]); } else { if (@event.IsClass("InputEventMouseMotion")) { this.EmitSignal(CardStateMachine.SignalName.TransitionRequested, [(int)State.Clicked, (int)State.Dragging]); } }
break; case State.Dragging: bool mouseMotion = @event.IsClass("InputEventMouseMotion"); bool confirm = @event.IsActionReleased("left_mouse"); bool canBePlayed = cardUI.CanBePlayed(cardUI.targetedZone);
if (mouseMotion) { cardUI.GlobalPosition = cardUI.GetGlobalMousePosition() - cardUI.PivotOffset; }
if (minimumDragTimeElsapsed && confirm && canBePlayed) { GetViewport().SetInputAsHandled(); this.EmitSignal(CardStateMachine.SignalName.TransitionRequested, [(int)State.Dragging, (int)State.Released]); } else if (minimumDragTimeElsapsed && confirm && !canBePlayed) { cardUI.targetedZone = CardZone.ZoneType.None; this.EmitSignal(CardStateMachine.SignalName.TransitionRequested, [(int)State.Dragging, (int)State.Base]); }
break; case State.Released: this.EmitSignal(CardStateMachine.SignalName.TransitionRequested, [(int)State.Released, (int)State.Base]); break; } }
public void OnGuiInput(InputEvent @event) { switch (currentState) { case State.Base: if (@event.IsActionPressed("left_mouse")) { cardUI.PivotOffset = cardUI.GetGlobalMousePosition() - cardUI.GlobalPosition; this.EmitSignal(CardStateMachine.SignalName.TransitionRequested, [(int)State.Base, (int)State.Clicked]); }
break; } }
public void OnMouseEntered() { }
public void OnMouseExited() { }
public void OnTransitionRequested(State from, State to) { if (from != currentState) { return; }
Exit(from); Enter(to); currentState = to; }}
public enum State{ None = -1, Base = 0, Clicked, Dragging, Released}