Skip to content

Commit 60891d3

Browse files
committed
Use Multisynq
1 parent 550e2a7 commit 60891d3

File tree

11 files changed

+153
-171
lines changed

11 files changed

+153
-171
lines changed

README.md

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Croquet Multiblaster Tutorial 🚀
1+
# Multisynq Multiblaster Tutorial 🚀
22

33
![Screencapture](step9.gif)
44

5-
[🕹️ CLICK HERE TO PLAY 🕹️](https://croquet.github.io/multiblaster-tutorial/step9.html)_then scan the QR code or share the generated session URL to invite other players._
5+
[🕹️ CLICK HERE TO PLAY 🕹️](https://multisynq.github.io/multiblaster-tutorial/step9.html)_then scan the QR code or share the generated session URL to invite other players._
66

7-
Each HTML file in [this repository](https://github.com/croquet/multiblaster-tutorial/)
8-
contains an increasingly complete multiplayer game built using [Croquet](https://github.com/croquet/croquet).
7+
Each HTML file in [this repository](https://github.com/multisynq/multiblaster-tutorial/)
8+
contains an increasingly complete multiplayer game built using [Multisynq](https://multisynq.io).
99

1010
It's a 2D game, and its visuals are intentionally kept simple so that the code is more understandable.
1111

@@ -16,14 +16,14 @@ They can also shoot blasts which cause asteroids to break up and vanish.
1616
Successful blasts increase the player's score, while colliding with an asteroid
1717
causes a ship to be destroyed and lose all points.
1818

19-
**📖 Please use our [Documentation](https://multisynq.io/docs/croquet/) alongside this tutorial, and join our [Discord](https://multisynq.io/discord) for questions 🤔**
19+
**📖 Please use our [Documentation](https://multisynq.io/docs/client/) alongside this tutorial, and join our [Discord](https://multisynq.io/discord) for questions 🤔**
2020

21-
## Step 0: Asteroids floating without Croquet 🪨≠🪨
21+
## Step 0: Asteroids floating without Multisynq 🪨≠🪨
2222

23-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step0.html))
24-
([run it](https://croquet.github.io/multiblaster-tutorial/step0.html))
23+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step0.html))
24+
([run it](https://multisynq.github.io/multiblaster-tutorial/step0.html))
2525

26-
This is a non-Croquet app. It shows a few asteroids floating through space.
26+
This is a non-Multisynq app. It shows a few asteroids floating through space.
2727
If you run this in two windows, the asteroids will float differently.
2828

2929
Each asteroid has an `x` and `y` position as well as an `a` angle.
@@ -64,36 +64,36 @@ for (const asteroid of asteroids) {
6464

6565
This file has about 80 lines of code total.
6666

67-
## Step 1: Asteroids synchronized with Croquet 🪨≡🪨
67+
## Step 1: Asteroids synchronized with Multisynq 🪨≡🪨
6868

69-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step1.html))
70-
([run it](https://croquet.github.io/multiblaster-tutorial/step1.html))
69+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step1.html))
70+
([run it](https://multisynq.github.io/multiblaster-tutorial/step1.html))
7171

72-
This is the same app, but using a Croquet Model for the asteroids.
72+
This is the same app, but using a Multisynq Model for the asteroids.
7373

7474
A session name and password is automatically appended to the URL.
7575
If you open that session URL in another window or on another device,
7676
the asteroids will float exactly the same in both.
7777

7878
The app is devided into two parts: The "model" is the part that is synchronized
79-
by Croquet for all users. It is like a shared computer that all users directly
79+
by Multisynq for all users. It is like a shared computer that all users directly
8080
interact with. The other part is the "view", which displays the model to the user
8181
by drawing the asteroids on a canvas. These parts are subclassed from
82-
`Croquet.Model` and `Croquet.View`, respectively.
82+
`Multisynq.Model` and `Multisynq.View`, respectively.
8383

84-
The last few lines instruct Croquet to join a session for a particular model and view class
85-
via `Croquet.Session.join()`. The name and password for this session are taken from
84+
The last few lines instruct Multisynq to join a session for a particular model and view class
85+
via `Multisynq.Session.join()`. The name and password for this session are taken from
8686
the current URL, or generated automatically using `autoSession()` and `autoPassword`.
8787
It also needs an API key. You should fetch your own key from [multisynq.io/coder](https://multisynq.io/coder/).
8888

89-
This version has only 20 lines more than the non-Croquet one from step 0.
89+
This version has only 20 lines more than the non-Multisynq one from step 0.
9090

9191
Notice that the computation looks exactly the same.
9292
_No special data structures need to be used._
9393
All models are synchronized between machines without any special markup.
9494

9595
```js
96-
class Asteroid extends Croquet.Model {
96+
class Asteroid extends Multisynq.Model {
9797

9898
...
9999

@@ -115,12 +115,12 @@ this.future(50).move();
115115
```
116116
inside of the `move()` method. This causes `move()` to be called again 50 ms in the future,
117117
similarly to the `timeout()` call in step 0.
118-
_Future messages are how you define an object's behavior over time in Croquet._
118+
_Future messages are how you define an object's behavior over time in Multisynq._
119119

120-
Drawing happens exactly the same as in the non-Croquet case:
120+
Drawing happens exactly the same as in the non-Multisynq case:
121121

122122
```js
123-
class Display extends Croquet.View {
123+
class Display extends Multisynq.View {
124124

125125
...
126126

@@ -152,16 +152,16 @@ because that would break the synchronization. See the next step for how to inter
152152

153153
## Step 2: Spaceships controlled by players 🕹️➡🚀
154154

155-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step2.html))
156-
([run it](https://croquet.github.io/multiblaster-tutorial/step2.html))
155+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step2.html))
156+
([run it](https://multisynq.github.io/multiblaster-tutorial/step2.html))
157157

158158
This step adds interactive space ships.
159159

160160
For each player joining, another spaceship is created by subscribing to the session's
161161
`view-join` and `view-exit` events:
162162

163163
```js
164-
class Game extends Croquet.Model {
164+
class Game extends Multisynq.Model {
165165

166166
init() {
167167
...
@@ -187,7 +187,7 @@ Each ship subscribes to that player's input only, using the player's `viewId` as
187187
This is how the shared model can distinguish events sent from different user's views:
188188
189189
```js
190-
class Ship extends Croquet.Model {
190+
class Ship extends Multisynq.Model {
191191

192192
init({ viewId }) {
193193
...
@@ -249,9 +249,9 @@ document.onkeyup = (e) => {
249249
};
250250
```
251251
252-
In Croquet, publish and subscribe are used mainly to communicate events from the user's view to the shared model,
252+
In Multisynq, publish and subscribe are used mainly to communicate events from the user's view to the shared model,
253253
typically derived from user input. Unlike in other pub/sub systems you may be familiar with,
254-
Croquet's pub/sub is not used to synchronize changed values or to communicate between different devices.
254+
Multisynq's pub/sub is not used to synchronize changed values or to communicate between different devices.
255255
All communication is only between the local view and the shared model.
256256
257257
Before joining the session, `makeWidgetDock()` enables a QR code widget in the lower left corner.
@@ -260,8 +260,8 @@ this code with a mobile device.
260260
261261
## Step 3: Firing a blaster 🕹️➡•••
262262
263-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step3.html))
264-
([run it](https://croquet.github.io/multiblaster-tutorial/step3.html))
263+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step3.html))
264+
([run it](https://multisynq.github.io/multiblaster-tutorial/step3.html))
265265
266266
When pressing the space bar, a `"fire-blaster"` event is published.
267267
The ship subscribes to that event and creates a new blast that
@@ -301,8 +301,8 @@ move() {
301301
302302
## Step 4: Break up asteroids when hit by blasts 🪨➡💥
303303
304-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step4.html))
305-
([run it](https://croquet.github.io/multiblaster-tutorial/step4.html))
304+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step4.html))
305+
([run it](https://multisynq.github.io/multiblaster-tutorial/step4.html))
306306
307307
In this step we add collision detection between the blasts and the asteroids.
308308
When hit, Asteroids split into two smaller chunks, or are destroyed completely.
@@ -360,8 +360,8 @@ And there is no network congestion even if hundreds of blasts are moving because
360360
361361
## Step 5: Turn ship into debris after colliding with asteroids 🚀➡💥
362362
363-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step5.html))
364-
([run it](https://croquet.github.io/multiblaster-tutorial/step5.html))
363+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step5.html))
364+
([run it](https://multisynq.github.io/multiblaster-tutorial/step5.html))
365365
366366
Now we add collision between ships and asteroids, and turn both into debris which is floating for a while.
367367
@@ -411,8 +411,8 @@ if (!wasHit) {
411411
412412
## Step 6: Score points when hitting an asteroid with a blast 💥➡🏆
413413
414-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step6.html))
415-
([run it](https://croquet.github.io/multiblaster-tutorial/step6.html))
414+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step6.html))
415+
([run it](https://multisynq.github.io/multiblaster-tutorial/step6.html))
416416
417417
Add scoring for ships hitting an asteroid.
418418
When a blast is fired, we store a reference to the ship in the blast.
@@ -449,8 +449,8 @@ update() {
449449
450450
## Step 7: View-side animation smoothing 🤩
451451
452-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step7.html))
453-
([run it](https://croquet.github.io/multiblaster-tutorial/step7.html))
452+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step7.html))
453+
([run it](https://multisynq.github.io/multiblaster-tutorial/step7.html))
454454
455455
Now we add render smoothing for 60 fps animation.
456456
The models move at 20 fps (because of the 50 ms future send
@@ -467,7 +467,7 @@ this.smoothing = new WeakMap();
467467
468468
It maps from the model objects (asteroids, ships, blasts) to plain JS objects
469469
like `{x, y, a}` that are then used for rendering. Alternatively, we could create
470-
individual View classes for each Model class by subclassing `Croquet.View`,
470+
individual View classes for each Model class by subclassing `Multisynq.View`,
471471
but for this simple game that seems unnecessary. With the `WeakMap` approach
472472
we avoid having to track creation and destruction of model objects.
473473
@@ -511,20 +511,20 @@ in animation quality.
511511
512512
## Step 8: Persistent table of highscores 🥇🥈🥉
513513
514-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step8.html))
515-
([run it](https://croquet.github.io/multiblaster-tutorial/step8.html))
514+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step8.html))
515+
([run it](https://multisynq.github.io/multiblaster-tutorial/step8.html))
516516
517-
Now we add a persistent highscore. Croquet automatically snapshots the model data and
517+
Now we add a persistent highscore. Multisynq automatically snapshots the model data and
518518
keeps that session state even when everyone leaves the session. When you resume it later by joining the session, everything will continue just as before. That means a highscore table in the model would appear to be "persistent".
519519
520520
However, whenever we change the model code, a new session is created, even it has the
521-
same name (internally, Croquet takes a hash of the registered model class source code).
521+
same name (internally, Multisynq takes a hash of the registered model class source code).
522522
The old session state becomes inaccessible, because for one we cannot know if the
523523
new code will work with the old state, but more importantly, every client in the session
524524
needs to execute exactly the same code to ensure determinism. Otherwise, different clients
525525
would compute different states, and the session would diverge.
526526
527-
To keep important data from a previous session of the same name, we need to use Croquet's
527+
To keep important data from a previous session of the same name, we need to use Multisynq's
528528
explicit persistence. An app can call `persistSession()` with some JSON data to store
529529
that persistent state. When a new session is started (no snapshot exists) but there is
530530
some persisted data from the previous session of the same name, this will be passed
@@ -536,16 +536,16 @@ so players only have to type it once.
536536
537537
```js
538538
initials.onchange = () => {
539-
localStorage.setItem("io.croquet.multiblaster.initials", initials.value);
539+
localStorage.setItem("io.multisynq.multiblaster.initials", initials.value);
540540
this.publish(this.viewId, "set-initials", initials.value);
541541
}
542542
```
543543
544544
On startup we check `localStorage` to automatically re-use the stored initials.
545545
546546
```js
547-
if (localStorage.getItem("io.croquet.multiblaster.initials")) {
548-
initials.value = localStorage.getItem("io.croquet.multiblaster.initials");
547+
if (localStorage.getItem("io.multisynq.multiblaster.initials")) {
548+
initials.value = localStorage.getItem("io.multisynq.multiblaster.initials");
549549
this.publish(this.viewId, "set-initials", initials.value);
550550
}
551551
```
@@ -604,16 +604,16 @@ setHighscore(initials, score) {
604604
In a more complex application, you should design the JSON persistence
605605
format carefully, e.g. by including a version number so that future code
606606
versions can correctly interpret the data written by an older version.
607-
Croquet makes no assumptions about this, it only stores and retrieves
607+
Multisynq makes no assumptions about this, it only stores and retrieves
608608
that data.
609609
610610
From this point on, even when you change the model code, the highscores
611611
will always be there.
612612
613613
## Step 9: Support for mobile etc. 📱
614614
615-
([full source code](https://github.com/croquet/multiblaster-tutorial/blob/main/step9.html))
616-
([run it](https://croquet.github.io/multiblaster-tutorial/step9.html))
615+
([full source code](https://github.com/multisynq/multiblaster-tutorial/blob/main/step9.html))
616+
([run it](https://multisynq.github.io/multiblaster-tutorial/step9.html))
617617
618618
This is the finished tutorial game. It has some more features, like
619619
* support for mobile devices via touch input
@@ -624,7 +624,7 @@ This is the finished tutorial game. It has some more features, like
624624
* etc.
625625
626626
We're not going to go into much detail here because all of these are independent
627-
of Croquet, it's more about playability and web UX.
627+
of Multisynq, it's more about playability and web UX.
628628
629629
One cute thing is the "wrapped rendering". If an object is very close to the edge
630630
of the screen, its other "half" should be visible on the other side to maintain
@@ -655,12 +655,12 @@ drawWrapped(x, y, size, draw) {
655655
## Advanced Game 🚀💋
656656
657657
There's an even more polished game with some gimmicks at
658-
[github.com/croquet/multiblaster](https://github.com/croquet/multiblaster/).
658+
[github.com/multisynq/multiblaster](https://github.com/multisynq/multiblaster/).
659659
660660
One of its gimmicks is that if the initials contain an emoji, it will be used for shooting. The trickiest part of that is properly parsing out the emoji, which can be composed of many code points 😉
661661
662662
You can play it online at [apps.multisynq.io/multiblaster](https://apps.multisynq.io/multiblaster/).
663663
664664
## Further Information 👀
665665
666-
Please use our [Documentation](https://multisynq.io/docs/croquet/) alongside this tutorial, and join our [Discord](https://multisynq.io/discord) for questions!
666+
Please use our [Documentation](https://multisynq.io/docs/client/) alongside this tutorial, and join our [Discord](https://multisynq.io/discord) for questions!

step0.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<head>
33
<meta charset="utf-8">
44
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
5-
<title>Croquet Multiblaster</title>
5+
<title>Multiblaster</title>
66
<style>
77
html, body {
88
margin: 0;

step1.html

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<head>
33
<meta charset="utf-8">
44
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
5-
<title>Croquet Multiblaster</title>
5+
<title>Multiblaster</title>
66
<style>
77
html, body {
88
margin: 0;
@@ -16,13 +16,13 @@
1616
max-height: 100%;
1717
}
1818
</style>
19-
<script src="https://unpkg.com/@croquet/[email protected]"></script>
19+
<script src="https://cdn.jsdelivr.net/npm/@multisynq/client@1/bundled/multisynq-client.min.js"></script>
2020
</head>
2121
<body>
2222
<canvas id="canvas" width="1000" height="1000"></canvas>
2323
<script>
2424

25-
class Game extends Croquet.Model {
25+
class Game extends Multisynq.Model {
2626
init() {
2727
this.asteroids = new Set();
2828
this.asteroids.add(Asteroid.create());
@@ -32,7 +32,7 @@
3232
}
3333
Game.register("Game");
3434

35-
class Asteroid extends Croquet.Model {
35+
class Asteroid extends Multisynq.Model {
3636
init() {
3737
this.size = 40;
3838
this.x = Math.random() * 1000;
@@ -55,7 +55,7 @@
5555

5656
////////////////////////// VIEW //////////////////////////
5757

58-
class Display extends Croquet.View {
58+
class Display extends Multisynq.View {
5959
constructor(model) {
6060
super(model);
6161
this.model = model;
@@ -85,11 +85,9 @@
8585
}
8686

8787

88-
Croquet.Session.join({
89-
apiKey: '1_i65fcn11n7lhrb5n890hs3dhj11hfzfej57pvlrx', // get your own from croquet.io/keys
90-
appId: 'io.croquet.multiblaster-tutorial',
91-
name: Croquet.App.autoSession(),
92-
password: Croquet.App.autoPassword(),
88+
Multisynq.Session.join({
89+
apiKey: '234567_Paste_Your_Own_API_Key_Here_7654321', // get your own from multisynq.io/coder
90+
appId: 'io.multisynq.multiblaster-tutorial',
9391
model: Game,
9492
view: Display,
9593
});

0 commit comments

Comments
 (0)