Incorrect behavior when used with js backend
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):
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.
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.