Learn to create multi-user shared animations and interactions with bouncing balls simulation
This tutorial teaches you how to create multi-user shared animations and interactions using Multisynq. You’ll build a simulation with 25 bouncing balls that can be stopped and started by clicking them. This demonstrates how the Model computes simulations and how the View displays and interacts with them.
Click or scan the QR code above to launch a new CodePen instance of this session. Compare the two sessions - you’ll see that the animated simulations are identical. The balls all move and bounce exactly the same way.
Click any ball to stop/start it - changes sync to all users
The rounded rectangle bounces but ignores user actions
How to create a model that runs physics simulations
Building views that respond to user interactions
Properly communicating between Model and View
This application uses two Multisynq Model subclasses: MyModel
and BallModel
. Both classes must be registered with Multisynq for proper synchronization.
The app uses Multisynq.Constants
to ensure all users share the same configuration values:
Models must not use global variables, but global constants are fine. Multisynq.Constants
is recursively frozen once a session starts to prevent accidental modification.
MyModel
is the root model passed to Multisynq.Session.join()
. It creates and stores the BallModel
objects in the MyModel.children
array.
Each BallModel
represents a shaped, colored, bouncing ball. The model stores only the data needed for synchronization:
'circle'
or 'roundRect'
)Each BallModel
subscribes to the 'touch-me'
event using its own ID as scope. This ensures that only the specific ball responds to touch events intended for it.
After initialization, each BallModel
schedules its first step()
method invocation. This creates a continuous simulation loop:
25 balls ticking at 30Hz generates 750 messages per second, but future messages are very efficient with minimal overhead.
The moveBounce()
method updates ball position and handles wall collisions. When a ball hits a wall, it gets a new random speed vector.
This uses Multisynq’s replicated random number generator. Every session instance computes the same sequence of random numbers, ensuring identical bouncing behavior across all users.
The View comprises two classes: MyView
and BallView
.
MyView
is called when a session instance starts, receiving the MyModel
object as an argument. It builds the visual representation and container for all balls.
The MyView
accesses the model’s children collection and creates a BallView
for each BallModel
.
It’s fine for views to read from models directly, but views MUST NOT modify models in any way.
MyView
listens for browser “resize” events and adjusts the view scale accordingly. This ensures all users see the same scene regardless of their window size.
When a session shuts down, the root view cleans up all child views and resources.
Each BallView
tracks its associated BallModel
and handles visual representation and user interaction.
The BallView
subscribes to 'pos-changed'
events from its specific model. The "oncePerFrame"
handling ensures efficient rendering even with multiple position updates per frame.
The BallView
sets up touch/click handlers that publish 'touch-me'
events. The corresponding BallModel
subscribes to these events and toggles ball motion on and off.
Model-View Separation
Deterministic Simulation
Efficient Event Handling
Interactive Synchronization
Now that you understand basic animation and interaction patterns, you can explore:
Learn to handle user input and message synchronization
Create smoother animations with interpolation techniques
Store shared configuration in Multisynq.Constants
Use object IDs to scope events to specific instances
Use "oncePerFrame"
handling for frequent updates
Implement proper cleanup in detach()
methods
This tutorial demonstrates the power of Multisynq’s deterministic synchronization for creating engaging multi-user interactive experiences. The same patterns can be applied to games, simulations, and collaborative tools.