create-bloop 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/hello/package.json +2 -2
- package/templates/hello/src/draw.ts +2 -2
- package/templates/mario/package.json +2 -2
- package/templates/mario/src/game.ts +2 -3
- package/templates/mario/src/main.ts +27 -42
- package/templates/mario/src/systems/inputs.ts +9 -9
- package/templates/mario/src/systems/matchmaking.ts +24 -0
- package/templates/mario/src/tape-load.ts +2 -0
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ export function draw(g: typeof game, toodle: Toodle) {
|
|
|
6
6
|
toodle.startFrame();
|
|
7
7
|
toodle.draw(
|
|
8
8
|
toodle.shapes.Circle({
|
|
9
|
-
|
|
9
|
+
radius: 50,
|
|
10
10
|
scale: bag.scale,
|
|
11
11
|
position: { x: bag.x, y: bag.y },
|
|
12
12
|
color: Colors.web.hotPink,
|
|
@@ -14,7 +14,7 @@ export function draw(g: typeof game, toodle: Toodle) {
|
|
|
14
14
|
);
|
|
15
15
|
toodle.draw(
|
|
16
16
|
toodle.shapes.Rect({
|
|
17
|
-
|
|
17
|
+
size: { width: 10, height: 10 },
|
|
18
18
|
position: toodle.convertSpace(
|
|
19
19
|
{ x: bag.mouse.x, y: bag.mouse.y },
|
|
20
20
|
{ from: "screen", to: "world" },
|
|
@@ -5,6 +5,7 @@ import { FLIPBOOKS } from "./sprites";
|
|
|
5
5
|
import { AnimationSystem } from "./systems/animation";
|
|
6
6
|
import { CollisionSystem } from "./systems/collision";
|
|
7
7
|
import { InputsSystem } from "./systems/inputs";
|
|
8
|
+
import { MatchmakingSystem } from "./systems/matchmaking";
|
|
8
9
|
import { PhaseSystem } from "./systems/phase";
|
|
9
10
|
import { PhysicsSystem } from "./systems/physics";
|
|
10
11
|
|
|
@@ -113,12 +114,10 @@ game.system(
|
|
|
113
114
|
}),
|
|
114
115
|
);
|
|
115
116
|
|
|
117
|
+
game.system("matchmaking", MatchmakingSystem);
|
|
116
118
|
game.system("inputs", InputsSystem);
|
|
117
|
-
|
|
118
119
|
game.system("physics", PhysicsSystem);
|
|
119
|
-
|
|
120
120
|
game.system("collision", CollisionSystem);
|
|
121
|
-
|
|
122
121
|
game.system("animation", AnimationSystem);
|
|
123
122
|
|
|
124
123
|
// Debug hitbox toggle (H key)
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import "./style.css";
|
|
2
2
|
import { Toodle } from "@bloopjs/toodle";
|
|
3
|
-
import {
|
|
3
|
+
import { start } from "@bloopjs/web";
|
|
4
4
|
import { createChromaticAberrationEffect } from "./chromatic-aberration";
|
|
5
5
|
import { createDrawState, draw as drawFn } from "./draw";
|
|
6
6
|
import { game } from "./game";
|
|
7
7
|
|
|
8
8
|
let draw = drawFn;
|
|
9
9
|
|
|
10
|
+
// boot up the game
|
|
10
11
|
const app = await start({
|
|
11
12
|
game,
|
|
12
13
|
startRecording: false,
|
|
@@ -15,6 +16,17 @@ const app = await start({
|
|
|
15
16
|
},
|
|
16
17
|
});
|
|
17
18
|
|
|
19
|
+
// HMR support
|
|
20
|
+
if (import.meta.hot) {
|
|
21
|
+
import.meta.hot.accept("./game", async (newModule) => {
|
|
22
|
+
await app.acceptHmr(newModule?.game);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
import.meta.hot.accept("./draw", async (newModule) => {
|
|
26
|
+
draw = newModule?.draw;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
const canvas = app.canvas;
|
|
19
31
|
if (!canvas) throw new Error("No canvas element found");
|
|
20
32
|
|
|
@@ -56,7 +68,20 @@ requestAnimationFrame(function frame() {
|
|
|
56
68
|
requestAnimationFrame(frame);
|
|
57
69
|
});
|
|
58
70
|
|
|
59
|
-
|
|
71
|
+
game.system("recording-watcher", {
|
|
72
|
+
netcode({ event, time }) {
|
|
73
|
+
console.log("[netcode]", event.type, event);
|
|
74
|
+
if (event.type === "session:start") {
|
|
75
|
+
console.log(
|
|
76
|
+
"[netcode]",
|
|
77
|
+
"session started, recording at frame",
|
|
78
|
+
time.frame,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
app.sim.record(100_000);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
60
85
|
|
|
61
86
|
// Debug: Press R to start recording mid-game
|
|
62
87
|
window.addEventListener("keydown", (e) => {
|
|
@@ -77,43 +102,3 @@ if (toodle.backend.type === "webgpu") {
|
|
|
77
102
|
}
|
|
78
103
|
});
|
|
79
104
|
}
|
|
80
|
-
|
|
81
|
-
game.system("title-input", {
|
|
82
|
-
update({ bag, inputs }) {
|
|
83
|
-
if (bag.phase !== "title") return;
|
|
84
|
-
|
|
85
|
-
if ((inputs.keys.enter.down || inputs.mouse.left.down) && !networkJoined) {
|
|
86
|
-
// Online multiplayer - wait for connection
|
|
87
|
-
bag.mode = "online";
|
|
88
|
-
bag.phase = "waiting";
|
|
89
|
-
networkJoined = true;
|
|
90
|
-
|
|
91
|
-
// Phase transitions are handled by the session-watcher system
|
|
92
|
-
joinRollbackRoom("mario-demo", app, {
|
|
93
|
-
onSessionStart() {
|
|
94
|
-
bag.phase = "playing";
|
|
95
|
-
|
|
96
|
-
app.sim.record(100_000);
|
|
97
|
-
console.log(
|
|
98
|
-
"Network session started, recording at frame",
|
|
99
|
-
app.sim.time.frame,
|
|
100
|
-
);
|
|
101
|
-
},
|
|
102
|
-
onSessionEnd() {
|
|
103
|
-
networkJoined = false;
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// HMR support
|
|
111
|
-
if (import.meta.hot) {
|
|
112
|
-
import.meta.hot.accept("./game", async (newModule) => {
|
|
113
|
-
await app.acceptHmr(newModule?.game);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
import.meta.hot.accept("./draw", async (newModule) => {
|
|
117
|
-
draw = newModule?.draw;
|
|
118
|
-
});
|
|
119
|
-
}
|
|
@@ -9,18 +9,18 @@ export const InputsSystem = PhaseSystem("playing", {
|
|
|
9
9
|
|
|
10
10
|
// P1 Horizontal movement
|
|
11
11
|
p1.vx = 0;
|
|
12
|
-
if (players
|
|
12
|
+
if (players.get(0).keys.a.held) {
|
|
13
13
|
p1.x -= cfg.MOVE_SPEED;
|
|
14
14
|
p1.vx = -cfg.MOVE_SPEED;
|
|
15
15
|
p1.facingDir = -1;
|
|
16
16
|
}
|
|
17
|
-
if (players
|
|
17
|
+
if (players.get(0).keys.d.held) {
|
|
18
18
|
p1.x += cfg.MOVE_SPEED;
|
|
19
19
|
p1.vx = cfg.MOVE_SPEED;
|
|
20
20
|
p1.facingDir = 1;
|
|
21
21
|
}
|
|
22
22
|
// P1 Jump
|
|
23
|
-
const wantsJump = players
|
|
23
|
+
const wantsJump = players.get(0).keys.w.down || players.get(0).mouse.left.down;
|
|
24
24
|
if (wantsJump && p1.grounded) {
|
|
25
25
|
p1.vy = cfg.JUMP_VELOCITY;
|
|
26
26
|
p1.grounded = false;
|
|
@@ -28,36 +28,36 @@ export const InputsSystem = PhaseSystem("playing", {
|
|
|
28
28
|
|
|
29
29
|
// P2 Horizontal movement
|
|
30
30
|
p2.vx = 0;
|
|
31
|
-
if (players
|
|
31
|
+
if (players.get(1).keys.a.held) {
|
|
32
32
|
p2.x -= cfg.MOVE_SPEED;
|
|
33
33
|
p2.vx = -cfg.MOVE_SPEED;
|
|
34
34
|
p2.facingDir = -1;
|
|
35
35
|
}
|
|
36
|
-
if (players
|
|
36
|
+
if (players.get(1).keys.d.held) {
|
|
37
37
|
p2.x += cfg.MOVE_SPEED;
|
|
38
38
|
p2.vx = cfg.MOVE_SPEED;
|
|
39
39
|
p2.facingDir = 1;
|
|
40
40
|
}
|
|
41
41
|
// P2 Jump
|
|
42
|
-
if ((players
|
|
42
|
+
if ((players.get(1).keys.w.down || players.get(1).mouse.left.down) && p2.grounded) {
|
|
43
43
|
p2.vy = cfg.JUMP_VELOCITY;
|
|
44
44
|
p2.grounded = false;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
if (!net.isInSession) {
|
|
48
48
|
// locally, control second player with ijkl
|
|
49
|
-
if (players
|
|
49
|
+
if (players.get(0).keys.j.held) {
|
|
50
50
|
p2.x -= cfg.MOVE_SPEED;
|
|
51
51
|
p2.vx = -cfg.MOVE_SPEED;
|
|
52
52
|
p2.facingDir = -1;
|
|
53
53
|
}
|
|
54
|
-
if (players
|
|
54
|
+
if (players.get(0).keys.l.held) {
|
|
55
55
|
p2.x += cfg.MOVE_SPEED;
|
|
56
56
|
p2.vx = cfg.MOVE_SPEED;
|
|
57
57
|
p2.facingDir = 1;
|
|
58
58
|
}
|
|
59
59
|
// Jump
|
|
60
|
-
if (players
|
|
60
|
+
if (players.get(0).keys.i.down && p2.grounded) {
|
|
61
61
|
p2.vy = cfg.JUMP_VELOCITY;
|
|
62
62
|
p2.grounded = false;
|
|
63
63
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PhaseSystem } from "./phase";
|
|
2
|
+
|
|
3
|
+
export const MatchmakingSystem = PhaseSystem("title", {
|
|
4
|
+
update({ bag, inputs, net }) {
|
|
5
|
+
if (net.isInSession) return;
|
|
6
|
+
if (inputs.keys.enter.down || inputs.mouse.left.down) {
|
|
7
|
+
bag.mode = "online";
|
|
8
|
+
bag.phase = "waiting";
|
|
9
|
+
net.wantsRoomCode = "mario-demo";
|
|
10
|
+
console.log("[netcode] setting wantsRoomCode");
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
netcode({ event, bag }) {
|
|
15
|
+
switch (event.type) {
|
|
16
|
+
case "session:start":
|
|
17
|
+
bag.phase = "playing";
|
|
18
|
+
break;
|
|
19
|
+
case "session:end":
|
|
20
|
+
bag.phase = "title";
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -75,6 +75,8 @@ async function loadTape(bytes: Uint8Array, fileName: string) {
|
|
|
75
75
|
marioWalk: spriteUrl("MarioWalk"),
|
|
76
76
|
marioJump: spriteUrl("MarioJump"),
|
|
77
77
|
marioSkid: spriteUrl("MarioSkid"),
|
|
78
|
+
brick: spriteUrl("Brick"),
|
|
79
|
+
ground: spriteUrl("Ground"),
|
|
78
80
|
},
|
|
79
81
|
autoLoad: true,
|
|
80
82
|
});
|