pragmagic/godot-nim

Godot debug hangs

WinstonHartnett opened this issue · 2 comments

I am new to Nim and Godot, so please bear with me. Also, note that this code comes from Heartbeast's [GDScript] Godot tutorial.

I was trying to get an FSM from Synthesis working to run a player's animation state machine, although I am running into a problem: the Godot debug hangs on the splashscreen and eats up an increasing amount of memory. The debugger shows no information about the debug process and there are neither errors nor print outputs while it runs. When the self.processAnimation... line is commented out, the program runs perfectly (with no player animations).

Is there a better way to do this? Is this a problem with godot-nim?

Player Nodes

Player
-> Sprite
-> CollisionShape2D
-> AnimationPlayer
-> AnimationTree

player.nim

import godot
import godotapi / [kinematic_body_2d,
                  input,
                  scene_tree,
                  animation_node_state_machine_playback]
import util
import synthesis

const
  MAX_SPEED = 150
  ACCELERATION = 500
  FRICTION = 750
  VECTOR_ZERO = vec2()

type
  # States and Events
  AnimationState = enum
    IDLEING
    MOVING
  AnimationEvent = enum
    STOP
    MOVE

gdobj Player of KinematicBody2D:  # Linter shows error here although compilation succeeds.
  var
    velocity = vec2()

    # Player Animation
    animationTree: AnimationTree
    animationState: AnimationNodeStateMachinePlayback
    animationPlayer: AnimationPlayer

    processAnimation: proc(x: Vector2, y: bool)

  method ready*() =
    # Animation Setup
    self.animationPlayer = (self.getNodeOrNull("AnimationPlayer")) as AnimationPlayer

    self.animationTree = (self.getNodeOrNull("AnimationTree")) as AnimationTree
    self.animationTree.setImpl("active", true.toVariant)

    self.animationState = asObject[AnimationNodeStateMachinePlayback](self.animationTree.getImpl("parameters/playback"))

    # Animation State Machine
    declareAutomaton(animationSM, AnimationState, AnimationEvent)

    setInitialState(animationSM, IDLEING)
    setTerminalState(animationSM, Exit)

    # Event Triggers
    implEvent(animationSM, MOVE):
      direction != VECTOR_ZERO
    implEvent(animationSM, STOP):
      direction == VECTOR_ZERO

    # State Relationships (Transitions)
    # None of the print statements show up in Output
    behavior(animationSM):
      ini: IDLEING
      fin: MOVING
      event: MOVE
      transition:
        self.animationTree.setImpl("parameters/Idle/blend_position", direction.toVariant)
        self.animationTree.setImpl("parameters/Run/blend_position", direction.toVariant)
        self.animationState.travel("Run")
        print("IDLE -> MOVE")
    behavior(animationSM):
      steady: IDLEING
      transition:
        self.animationState.travel("Idle")
        print("Idleing")
    behavior(animationSM):
      ini: MOVING
      fin: IDLEING
      event: STOP
      transition:
        self.animationState.travel("Idle")
    behavior(animationSM):
      steady: MOVING
      transition:
        self.animationTree.setImpl("parameters/Idle/blend_position", direction.toVariant)
        self.animationTree.setImpl("parameters/Run/blend_position", direction.toVariant)
        print("MOVING STEADY")

    # This is probably where the problems come from...
    # The `synthesize` macro spits out a proc that runs the FSM, which can't be
    # used unless it's assigned to a Player-level closure. Unless there's a
    # better way?
    synthesize(animationSM):
      proc processAnimationImpl(direction: Vector2, animationFinished: bool)

    self.processAnimation = processAnimationImpl

  method physicsProcess*(delta: float64) =
    print("Got here")  # Doesn't print

    # Movement
    var inputVector = vec2()

    inputVector.x = getActionStrength("ui_right") - getActionStrength("ui_left")
    inputVector.y = getActionStrength("ui_down") - getActionStrength("ui_up")
    inputVector.normalize

    if inputVector != VECTOR_ZERO:
      self.velocity.moveToward(inputVector * MAX_SPEED, ACCELERATION * delta)
    else:
      self.velocity.moveToward(VECTOR_ZERO, FRICTION * delta)

    self.velocity = self.moveAndSlide(self.velocity)

    # Run the state machine
    self.processAnimation(inputVector, false)  # Linter notes: `physicsProcess` is not GC-safe as it performs an indirect call here

I'm not sure what synthesize actually generates, but the description sounds like processAnimation just hangs forever in there, i.e. it doesn't give the control back, which is not suitable for a game application.

I'm not sure what synthesize actually generates, but the description sounds like processAnimation just hangs forever in there, i.e. it doesn't give the control back, which is not suitable for a game application.

You are entirely correct. I didn't understand how the synthesize macro actually worked. Thanks!