polymorph icon indicating copy to clipboard operation
polymorph copied to clipboard

Incorrect behavior when used with js backend

Open pietroppeter opened this issue 3 years ago • 2 comments

I have tried using polymorph with js backend and I am getting incorrect behavior.

The example I am using is taken from simple physics example (see here for a document showing this behavior). When the following code is compiled using nim js backend:

  • it starts with Pos (0, 0) instead of (1, 1) (and wrong velociy)
  • at each step neither move nor gravity are applied, only bounce is applied.
import polymorph

# Parse some types as components.
register defaultCompOpts:
  type
    Pos = object
      x, y: float
    Vel = object
      x, y: float
    Gravity = object
      strength: float
    Bounce = object   # A dataless 'tag' component.

makeSystem "move", [Pos, Vel]:
  # Calculate basic movement.
  all:
    echo "move"
    pos.x += vel.x
    pos.y += vel.y

makeSystem "gravity", [Vel, Gravity]:
  # Apply a gravity force to 'Vel'.
  all:
    vel.y -= gravity.strength

makeSystem "bounce", [Pos, Vel, Bounce]:
  all:
    # Correct 'Pos.y' to never goes below zero, enacting a simple bounce
    # to 'Vel.y' if this occurs.
    if pos.y <= 0.0:
      pos.y = 0.0
      vel.y = abs(vel.y) * 0.5

# Generate the framework and system procedures.
makeEcsCommit "run"

let
  ball = newEntityWith(
    Pos(x: 0.0, y: 0.0),
    Vel(x: 1.0, y: 1.0),
    Gravity(strength: 1.0),
    Bounce()
  ) 

for i in 0 ..< 4:
  run()
  echo ball

Here are the results in js console (truncated at the end):

Schermata 2022-11-13 alle 21 56 28

pietroppeter avatar Nov 13 '22 21:11 pietroppeter

It looks like this is caused by the += on the JavaScript platform.

A work around is to replace lines with += to dereference the index with access or just use =.

makeSystem "move", [Position, vel: Velocity]:
  all:
    position.access.y += vel.dy
    position.access.x += vel.dx

or

makeSystem "move", [Position, vel: Velocity]:
  all:
    position.y = position.y + vel.dy
    position.x = position.x + vel.dx

My guess is that += is making a copy and updating that rather than writing the value back to the components.

rlipsc avatar Nov 14 '22 20:11 rlipsc

So the situation is not to bad if we just have to avoid +=. Not sure if this is something that could be considered a bug for js backend but in order to report it on nim issue tracker it might be useful to have a more minimal reproducible example (possibly that does not involve polymorph).

I guess for the moment we could leave this open for others to be aware.

pietroppeter avatar Nov 14 '22 23:11 pietroppeter