littlejsengine 1.14.23 → 1.15.2
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/dist/littlejs.d.ts +184 -30
- package/dist/littlejs.esm.js +589 -147
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +583 -147
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +546 -147
- package/examples/box2d/gameObjects.js +6 -10
- package/examples/box2d/scenes.js +2 -2
- package/examples/breakout/gameObjects.js +1 -1
- package/examples/electron/index.html +2 -2
- package/examples/index.html +11 -7
- package/examples/platformer/gameCharacter.js +3 -2
- package/examples/platformer/gameObjects.js +3 -8
- package/examples/shorts/base.html +2 -2
- package/examples/shorts/box2d.js +2 -2
- package/examples/shorts/box2dCar.js +18 -7
- package/examples/shorts/box2dPool.js +108 -0
- package/examples/shorts/debugDraw.js +2 -3
- package/examples/shorts/flappyGame.js +1 -0
- package/examples/shorts/fps.js +1 -1
- package/examples/shorts/hillGlideGame.js +0 -2
- package/examples/shorts/input.js +59 -0
- package/examples/shorts/landerGame.js +1 -3
- package/examples/shorts/medals.js +15 -9
- package/examples/shorts/music.js +15 -17
- package/examples/shorts/musicPlayer.js +24 -24
- package/examples/shorts/platformer.js +0 -2
- package/examples/shorts/slidingPuzzle.js +1 -1
- package/examples/shorts/song.mp3 +0 -0
- package/examples/shorts/spaceGame.js +0 -2
- package/examples/shorts/spriteAtlas.js +0 -2
- package/examples/shorts/tiltedView.js +0 -3
- package/examples/shorts/timers.js +1 -2
- package/examples/shorts/topDown.js +0 -2
- package/examples/shorts/video.webm +0 -0
- package/examples/shorts/videoPlayer.js +33 -0
- package/examples/starter/index.html +3 -3
- package/package.json +1 -1
- package/plugins/box2d.js +170 -50
- package/plugins/pluginExport.js +3 -0
- package/plugins/uiSystem.js +229 -27
- package/src/engine.js +21 -18
- package/src/engineAudio.js +14 -2
- package/src/engineDebug.js +37 -0
- package/src/engineDraw.js +21 -13
- package/src/engineExport.js +3 -0
- package/src/engineInput.js +24 -12
- package/src/engineMedals.js +2 -2
- package/src/engineObject.js +24 -4
- package/src/engineParticles.js +4 -6
- package/src/engineTileLayer.js +2 -0
- package/src/engineUtilities.js +35 -13
|
@@ -38,7 +38,7 @@ export function spawnCircle(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bod
|
|
|
38
38
|
export function spawnRandomPoly(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, angle=0)
|
|
39
39
|
{
|
|
40
40
|
const o = new LJS.Box2dObject(pos, vec2(), 0, angle, color, type);
|
|
41
|
-
o.addRandomPoly(diameter,
|
|
41
|
+
o.addRandomPoly(diameter, density, friction, restitution);
|
|
42
42
|
return o;
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -77,7 +77,7 @@ export function spawnRandomEdges()
|
|
|
77
77
|
for (let i=40, y=0; i--;)
|
|
78
78
|
edgePoints.push(vec2(i, y=LJS.clamp(y+LJS.rand(-2,2),0,5)));
|
|
79
79
|
edgePoints.push(vec2(0,0));
|
|
80
|
-
const o = new LJS.
|
|
80
|
+
const o = new LJS.Box2dStaticObject;
|
|
81
81
|
o.addEdgeList(edgePoints);
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -147,8 +147,6 @@ export class CarObject extends LJS.Box2dObject
|
|
|
147
147
|
}
|
|
148
148
|
update()
|
|
149
149
|
{
|
|
150
|
-
super.update();
|
|
151
|
-
|
|
152
150
|
// car controls
|
|
153
151
|
const maxSpeed = 40;
|
|
154
152
|
const input = LJS.keyDirection().x;
|
|
@@ -166,11 +164,11 @@ export class CarObject extends LJS.Box2dObject
|
|
|
166
164
|
///////////////////////////////////////////////////////////////////////////////
|
|
167
165
|
|
|
168
166
|
// changes objects color when touched
|
|
169
|
-
export class ContactTester extends LJS.
|
|
167
|
+
export class ContactTester extends LJS.Box2dStaticObject
|
|
170
168
|
{
|
|
171
169
|
constructor(pos, size, color, contactColor, isCircle=true, isSensor=true)
|
|
172
170
|
{
|
|
173
|
-
super(pos, size, 0, 0, color
|
|
171
|
+
super(pos, size, 0, 0, color);
|
|
174
172
|
isCircle ? this.addCircle(size.x) : this.addBox(size);
|
|
175
173
|
this.setSensor(isSensor);
|
|
176
174
|
this.contactColor = contactColor;
|
|
@@ -325,11 +323,11 @@ export class SoftBodyObject extends LJS.Box2dObject
|
|
|
325
323
|
///////////////////////////////////////////////////////////////////////////////
|
|
326
324
|
|
|
327
325
|
// cloth sim using grid of rope joints
|
|
328
|
-
export class ClothObject extends LJS.
|
|
326
|
+
export class ClothObject extends LJS.Box2dStaticObject
|
|
329
327
|
{
|
|
330
328
|
constructor(pos, scale, sizeCount, color, maxJointStress=10)
|
|
331
329
|
{
|
|
332
|
-
super(pos, vec2(), 0, 0, color
|
|
330
|
+
super(pos, vec2(), 0, 0, color);
|
|
333
331
|
const nodeSize = sizeCount.subtract(vec2(1));
|
|
334
332
|
const spacing = scale.divide(nodeSize);
|
|
335
333
|
const objectDiameter = LJS.min(spacing.x, spacing.y);
|
|
@@ -393,8 +391,6 @@ export class ClothObject extends LJS.Box2dObject
|
|
|
393
391
|
}
|
|
394
392
|
update()
|
|
395
393
|
{
|
|
396
|
-
super.update();
|
|
397
|
-
|
|
398
394
|
for (let y=this.sizeCount.y; y--;)
|
|
399
395
|
for (let x=this.sizeCount.x; x--;)
|
|
400
396
|
{
|
package/examples/box2d/scenes.js
CHANGED
|
@@ -137,14 +137,14 @@ export function loadScene(_scene)
|
|
|
137
137
|
}
|
|
138
138
|
{
|
|
139
139
|
// distance joint
|
|
140
|
-
const o1 = new LJS.
|
|
140
|
+
const o1 = new LJS.Box2dStaticObject(vec2(30,11), vec2(4), Game.spriteAtlas.circleOutline, 0, LJS.randColor());
|
|
141
141
|
o1.renderOrder = -2;
|
|
142
142
|
const o2 = GameObjects.spawnCircle(vec2(30,8), 2, LJS.randColor());
|
|
143
143
|
new LJS.Box2dDistanceJoint(o1, o2);
|
|
144
144
|
}
|
|
145
145
|
{
|
|
146
146
|
// motor joint
|
|
147
|
-
const o = new LJS.
|
|
147
|
+
const o = new LJS.Box2dStaticObject(vec2(10,8), vec2(4), Game.spriteAtlas.circleOutline, 0, LJS.randColor());
|
|
148
148
|
o.renderOrder = -2;
|
|
149
149
|
new GameObjects.MotorJointObject(vec2(10,8), vec2(2), LJS.randColor(), o);
|
|
150
150
|
}
|
|
@@ -137,7 +137,7 @@ export class Ball extends PhysicsObject
|
|
|
137
137
|
this.velocity.y = LJS.max(-this.velocity.y, .2);
|
|
138
138
|
|
|
139
139
|
// speed up
|
|
140
|
-
const speed = LJS.min(1.04*this.
|
|
140
|
+
const speed = LJS.min(1.04*this.getSpeed(), .5);
|
|
141
141
|
this.velocity = this.velocity.normalize(speed);
|
|
142
142
|
sound_bounce.play(this.pos, 1, speed*2);
|
|
143
143
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</head><body>
|
|
8
8
|
|
|
9
9
|
<!-- LittleJS Engine -->
|
|
10
|
-
<script src=../../dist/littlejs.js?1.
|
|
10
|
+
<script src=../../dist/littlejs.js?1.15.2></script>
|
|
11
11
|
|
|
12
12
|
<!-- Add your game scripts here -->
|
|
13
|
-
<script src=game.js?1.
|
|
13
|
+
<script src=game.js?1.15.2></script>
|
package/examples/index.html
CHANGED
|
@@ -84,32 +84,35 @@ class ExampleInfo
|
|
|
84
84
|
|
|
85
85
|
const exampleList =
|
|
86
86
|
[
|
|
87
|
-
new ExampleInfo('---
|
|
87
|
+
new ExampleInfo('--- BASIC ---'),
|
|
88
88
|
new ExampleInfo('Hello World', 'helloWorld.js', 'Simple starter example', false, 'beginner, gradient, text, tiles'),
|
|
89
89
|
new ExampleInfo('Empty', 'empty.js', 'Empty example template', false, 'beginner, text'),
|
|
90
90
|
new ExampleInfo('Texture', 'texture.js', 'Texture display and manipulation', false, 'sprites, loading, tiles'),
|
|
91
91
|
new ExampleInfo('Animation', 'animation.js', 'Sprite animation system', false, 'frames, loop, tiles, sprites'),
|
|
92
92
|
new ExampleInfo('Shapes', 'shapes.js', 'Draw geometric shapes and primitives', false, 'circle, ellipse, rectangle, polygon, lines'),
|
|
93
93
|
new ExampleInfo('Colors', 'colors.js', 'Color manipulation and HSL', false, 'hue, saturation, blending, rectangle'),
|
|
94
|
-
new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield', false, 'space, movement, depth, rectangle'),
|
|
95
94
|
new ExampleInfo('Sprite Atlas', 'spriteAtlas.js', 'Sprite atlas and tile rendering', false, 'sheet, frames, tiles'),
|
|
96
95
|
new ExampleInfo('Blending', 'blending.js', 'Additive blending and transparency', false, 'alpha, color, tiles, smooth'),
|
|
97
96
|
new ExampleInfo('Tile Layer', 'tileLayer.js', 'Tile layer rendering system', false, 'level, map, grid, particles'),
|
|
98
97
|
new ExampleInfo('Particles', 'particles.js', 'Particle system', false, 'effects, emitter, physics, fire, smoke'),
|
|
98
|
+
new ExampleInfo('Input', 'input.js', 'Input system demo for keyboard, mouse, touch, and gamepad.', false, 'input, control'),
|
|
99
99
|
new ExampleInfo('Timers', 'timers.js', 'Timer objects and UI', false, 'delay, interval, slider'),
|
|
100
100
|
new ExampleInfo('Sound Effects', 'sound.js', 'ZzFX sound effect generator', false, 'audio, volume, ui'),
|
|
101
|
-
new ExampleInfo('Music', 'music.js', 'Basic
|
|
101
|
+
new ExampleInfo('Music', 'music.js', 'Basic load, play, pause, and stop', false, 'music, sound, audio, streaming, volume, ui'),
|
|
102
|
+
new ExampleInfo('Video', 'videoPlayer.js', 'Basic video play, pause, and stop', false, 'movie, sound, audio, streaming, volume, ui'),
|
|
102
103
|
new ExampleInfo('Font Image', 'systemFont.js', 'Bitmap font system with built-in system font', false, 'text, characters'),
|
|
103
|
-
new ExampleInfo('Parallax', 'parallax.js', 'Parallax scrolling mountains', false, 'generative, canvas, background'),
|
|
104
|
-
new ExampleInfo('Maze Generator', 'maze.js', 'Procedural maze generation', false, 'generative, level, tiles, map, grid'),
|
|
105
104
|
new ExampleInfo('Medals', 'medals.js', 'Achievement system', false, 'unlock, progress, newgrounds'),
|
|
106
105
|
new ExampleInfo('Tile Raycast', 'tileRaycast.js', 'Example of the tile layer raycast collision', false, 'level, map, grid'),
|
|
107
|
-
new ExampleInfo('Debug Drawing', 'debugDraw.js', 'Debug drawing system', false, 'debug, circle, line, rectangle'),
|
|
108
106
|
new ExampleInfo('Camera Mouse Drag', 'cameraDrag.js', 'Example of how to control camera with mose', false, 'ui, input, control'),
|
|
107
|
+
new ExampleInfo('Debug Drawing', 'debugDraw.js', 'Debug drawing system', false, 'debug, circle, line, rectangle'),
|
|
108
|
+
new ExampleInfo('--- ADVANCED ---'),
|
|
109
109
|
new ExampleInfo('Clock', 'clock.js', 'Animated analog clock', false, 'time, rotation, lines, rectangle'),
|
|
110
|
+
new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield', false, 'space, movement, depth, rectangle'),
|
|
111
|
+
new ExampleInfo('Parallax', 'parallax.js', 'Parallax scrolling mountains', false, 'generative, canvas, background'),
|
|
112
|
+
new ExampleInfo('Maze Generator', 'maze.js', 'Procedural maze generation', false, 'generative, level, tiles, map, grid'),
|
|
110
113
|
new ExampleInfo('Piano', 'piano.js', 'Interactive piano keyboard', false, 'music, sound, audio, notes, ui, instrument'),
|
|
111
114
|
new ExampleInfo('Step Sequencer', 'sequencer.js', 'Simple music loop creation tool', false, 'music, sound, audio, notes, ui, instrument'),
|
|
112
|
-
new ExampleInfo('Music Player', 'musicPlayer.js', '
|
|
115
|
+
new ExampleInfo('Music Player', 'musicPlayer.js', 'Music player with audio seeking and drag and drop', false, 'sound, loading, audio, ui'),
|
|
113
116
|
new ExampleInfo('WebGL Shader', 'shader.js', 'Full canvas webgl shader', false, 'webgl, visual, effect'),
|
|
114
117
|
new ExampleInfo('--- MINI GAMES ---'),
|
|
115
118
|
new ExampleInfo('Pong Game', 'pongGame.js', 'Classic paddle ball bouncing', false, 'objects, collision'),
|
|
@@ -125,6 +128,7 @@ const exampleList =
|
|
|
125
128
|
new ExampleInfo('--- PLUGINS ---'),
|
|
126
129
|
new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin', false, 'objects, mouse'),
|
|
127
130
|
new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics', false, 'objects, vehicle, suspension, wheels'),
|
|
131
|
+
new ExampleInfo('Box2d Pool', 'box2dPool.js', 'Billiard table pool game with physics', false, 'objects, game'),
|
|
128
132
|
new ExampleInfo('Post Processing', 'postProcess.js', 'Shader effects and filters', false, 'webgl, visual, effect'),
|
|
129
133
|
new ExampleInfo('UI System Plugin', 'uiSystem.js', 'Buttons, sliders, and checkboxes', false, 'objects, widgets, interactive'),
|
|
130
134
|
new ExampleInfo('Nine Slice', 'nineSlice.js', 'Scalable UI panels', false, 'three slice, stretch, corners, text, tiles'),
|
|
@@ -34,6 +34,7 @@ export class Character extends GameObjects.GameObject
|
|
|
34
34
|
this.deadTimer = new Timer;
|
|
35
35
|
this.grenadeThrowTimer = new Timer;
|
|
36
36
|
this.drawSize = vec2(1);
|
|
37
|
+
this.moveInput = vec2();
|
|
37
38
|
this.color = hsl(LJS.rand(),1,.7);
|
|
38
39
|
this.renderOrder = 10;
|
|
39
40
|
this.walkCyclePercent = 0;
|
|
@@ -195,11 +196,11 @@ export class Character extends GameObjects.GameObject
|
|
|
195
196
|
// track last pos for ladder collision code
|
|
196
197
|
this.lastPos = this.pos.copy();
|
|
197
198
|
|
|
198
|
-
// call parent
|
|
199
|
+
// call parent
|
|
199
200
|
super.update();
|
|
200
201
|
|
|
201
202
|
// update walk cycle
|
|
202
|
-
const speed = this.
|
|
203
|
+
const speed = this.getSpeed();
|
|
203
204
|
if (this.climbingLadder || this.groundTimer.active() && !this.dodgeTimer.active())
|
|
204
205
|
{
|
|
205
206
|
this.walkCyclePercent += speed * .5;
|
|
@@ -26,8 +26,6 @@ export class GameObject extends LJS.EngineObject
|
|
|
26
26
|
|
|
27
27
|
update()
|
|
28
28
|
{
|
|
29
|
-
super.update();
|
|
30
|
-
|
|
31
29
|
// flash white when damaged
|
|
32
30
|
let brightness = 0;
|
|
33
31
|
if (!this.isDead() && this.damageTimer.isSet())
|
|
@@ -97,6 +95,7 @@ export class Coin extends LJS.EngineObject
|
|
|
97
95
|
{
|
|
98
96
|
super(pos, vec2(1), Game.spriteAtlas.coin);
|
|
99
97
|
this.color = hsl(.15,1,.5);
|
|
98
|
+
this.mass = 0;
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
render()
|
|
@@ -155,7 +154,7 @@ export class Enemy extends GameObject
|
|
|
155
154
|
this.velocity = vec2(LJS.rand(.1,-.1), LJS.rand(.4,.2));
|
|
156
155
|
|
|
157
156
|
// damage player if touching
|
|
158
|
-
if (
|
|
157
|
+
if (this.isOverlappingObject(Game.player))
|
|
159
158
|
Game.player.damage(1, this);
|
|
160
159
|
}
|
|
161
160
|
|
|
@@ -261,8 +260,6 @@ export class Weapon extends LJS.EngineObject
|
|
|
261
260
|
|
|
262
261
|
update()
|
|
263
262
|
{
|
|
264
|
-
super.update();
|
|
265
|
-
|
|
266
263
|
// update recoil
|
|
267
264
|
if (this.recoilTimer.active())
|
|
268
265
|
this.localAngle = LJS.lerp(this.localAngle, 0, this.recoilTimer.getPercent());
|
|
@@ -318,11 +315,9 @@ export class Bullet extends LJS.EngineObject
|
|
|
318
315
|
if (o.isGameObject)
|
|
319
316
|
this.collideWithObject(o)
|
|
320
317
|
});
|
|
321
|
-
|
|
322
|
-
super.update();
|
|
323
318
|
|
|
324
319
|
this.angle = this.velocity.angle();
|
|
325
|
-
this.range -= this.
|
|
320
|
+
this.range -= this.getSpeed();
|
|
326
321
|
if (this.range < 0)
|
|
327
322
|
{
|
|
328
323
|
new LJS.ParticleEmitter(
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<!DOCTYPE html><meta charset=utf-8><body>
|
|
2
|
-
<script src=../../dist/littlejs.js?1.
|
|
2
|
+
<script src=../../dist/littlejs.js?1.15.2></script>
|
|
3
3
|
<script src=../../dist/box2d.wasm.js></script>
|
|
4
4
|
|
|
5
5
|
<!-- LittleJS Engine Source
|
|
6
|
+
<script src=../../src/engine.js></script>
|
|
6
7
|
<script src=../../src/engineDebug.js></script>
|
|
7
8
|
<script src=../../src/engineUtilities.js></script>
|
|
8
9
|
<script src=../../src/engineSettings.js></script>
|
|
@@ -14,7 +15,6 @@
|
|
|
14
15
|
<script src=../../src/engineParticles.js></script>
|
|
15
16
|
<script src=../../src/engineMedals.js></script>
|
|
16
17
|
<script src=../../src/engineWebGL.js></script>
|
|
17
|
-
<script src=../../src/engine.js></script>
|
|
18
18
|
<script src=../../plugins/box2d.js></script>
|
|
19
19
|
<script src=../../plugins/box2d.wasm.js></script>
|
|
20
20
|
<script src=../../plugins/drawUtilities.js></script>
|
package/examples/shorts/box2d.js
CHANGED
|
@@ -7,8 +7,8 @@ async function gameInit()
|
|
|
7
7
|
canvasClearColor = hsl(0,0,.9);
|
|
8
8
|
|
|
9
9
|
// create ground object
|
|
10
|
-
groundObject = new
|
|
11
|
-
|
|
10
|
+
groundObject = new Box2dStaticObject(vec2(-8));
|
|
11
|
+
groundObject.color = GRAY;
|
|
12
12
|
groundObject.addBox(vec2(100,2));
|
|
13
13
|
|
|
14
14
|
// add some random objects
|
|
@@ -3,9 +3,19 @@ async function gameInit()
|
|
|
3
3
|
// setup box2d and create the objects
|
|
4
4
|
await box2dInit();
|
|
5
5
|
gravity.y = -20;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
|
|
7
|
+
// create edge list for ground
|
|
8
|
+
const edgePoints = [];
|
|
9
|
+
for (let i=0, y=0, s=0; i<1e3; ++i)
|
|
10
|
+
{
|
|
11
|
+
y = clamp(y+rand(-1,1),0,5);
|
|
12
|
+
edgePoints.push(vec2(i*5-15, y-8));
|
|
13
|
+
}
|
|
14
|
+
const ground = new Box2dStaticObject;
|
|
15
|
+
ground.lineWidth = 1;
|
|
16
|
+
ground.addEdgeList(edgePoints);
|
|
17
|
+
|
|
18
|
+
// make a car
|
|
9
19
|
new CarObject(vec2(0,-2));
|
|
10
20
|
canvasClearColor = hsl(0,0,.9);
|
|
11
21
|
}
|
|
@@ -14,9 +24,10 @@ class CarObject extends Box2dObject
|
|
|
14
24
|
{
|
|
15
25
|
constructor(pos)
|
|
16
26
|
{
|
|
17
|
-
super(pos
|
|
27
|
+
super(pos);
|
|
18
28
|
|
|
19
29
|
// create car with wheels
|
|
30
|
+
this.color = RED;
|
|
20
31
|
this.addBox(vec2(7,2));
|
|
21
32
|
const frequency = 4, maxTorque = 250;
|
|
22
33
|
this.wheels = [];
|
|
@@ -28,15 +39,14 @@ class CarObject extends Box2dObject
|
|
|
28
39
|
joint.setSpringFrequencyHz(frequency);
|
|
29
40
|
joint.setMaxMotorTorque(maxTorque);
|
|
30
41
|
joint.enableMotor(!i);
|
|
31
|
-
|
|
42
|
+
const friction = 1;
|
|
43
|
+
wheel.addCircle(2, vec2(), 1, friction);
|
|
32
44
|
wheel.motorJoint = joint;
|
|
33
45
|
this.wheels[i] = wheel;
|
|
34
46
|
}
|
|
35
47
|
}
|
|
36
48
|
update()
|
|
37
49
|
{
|
|
38
|
-
super.update();
|
|
39
|
-
|
|
40
50
|
// car controls - use mouse, arrow keys, or A/D to drive
|
|
41
51
|
const maxSpeed = 40;
|
|
42
52
|
const input = mouseIsDown(0) ? 1 :
|
|
@@ -44,5 +54,6 @@ class CarObject extends Box2dObject
|
|
|
44
54
|
let s = this.wheels[0].motorJoint.getMotorSpeed();
|
|
45
55
|
s = input ? clamp(s - input, -maxSpeed, maxSpeed) : 0;
|
|
46
56
|
this.wheels[0].motorJoint.setMotorSpeed(s);
|
|
57
|
+
cameraPos.x = this.pos.x;
|
|
47
58
|
}
|
|
48
59
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const hitSound = new Sound([,,2e3,,,.01]);
|
|
2
|
+
const maxHitDistance = 6;
|
|
3
|
+
|
|
4
|
+
class Ball extends Box2dObject
|
|
5
|
+
{
|
|
6
|
+
constructor(position, number=0)
|
|
7
|
+
{
|
|
8
|
+
const color = hsl(number/9, 1, number? .5 : 1);
|
|
9
|
+
super(position, vec2(), 0, 0, color);
|
|
10
|
+
this.number = number;
|
|
11
|
+
|
|
12
|
+
// setup pool ball physics
|
|
13
|
+
const friction = 0, restitution = .95;
|
|
14
|
+
this.addCircle(1, vec2(), 1, friction, restitution);
|
|
15
|
+
this.setLinearDamping(.4);
|
|
16
|
+
this.setBullet(true);
|
|
17
|
+
this.setFixedRotation(true);
|
|
18
|
+
}
|
|
19
|
+
beginContact()
|
|
20
|
+
{
|
|
21
|
+
const volume = clamp(this.getSpeed()/20);
|
|
22
|
+
hitSound.play(this.pos, clamp(this.getSpeed()/20));
|
|
23
|
+
}
|
|
24
|
+
canHit() { return this == cueBall && this.getSpeed() < 1; }
|
|
25
|
+
getHitOffset()
|
|
26
|
+
{
|
|
27
|
+
// hit from cue ball to mouse position
|
|
28
|
+
const deltaPos = mousePos.subtract(this.pos);
|
|
29
|
+
const length = min(deltaPos.length(), maxHitDistance);
|
|
30
|
+
return deltaPos.normalize(length);
|
|
31
|
+
}
|
|
32
|
+
update()
|
|
33
|
+
{
|
|
34
|
+
if (this.canHit() && mouseWasPressed(0))
|
|
35
|
+
{
|
|
36
|
+
// hit the cue ball
|
|
37
|
+
const accel = this.getHitOffset().scale(8);
|
|
38
|
+
this.applyAcceleration(accel);
|
|
39
|
+
hitSound.play(cueBall.pos);
|
|
40
|
+
}
|
|
41
|
+
if (this.pocketed)
|
|
42
|
+
this.destroy();
|
|
43
|
+
}
|
|
44
|
+
render()
|
|
45
|
+
{
|
|
46
|
+
super.render();
|
|
47
|
+
|
|
48
|
+
// draw white circle and ball number
|
|
49
|
+
drawCircle(this.pos, .6, WHITE);
|
|
50
|
+
const textPos = this.pos.add(vec2(0,-.06));
|
|
51
|
+
if (this.number)
|
|
52
|
+
drawTextOverlay(this.number, textPos, .5, BLACK);
|
|
53
|
+
if (this.canHit())
|
|
54
|
+
{
|
|
55
|
+
// draw the aim line
|
|
56
|
+
const offset = this.getHitOffset();
|
|
57
|
+
const endPos = this.pos.add(offset);
|
|
58
|
+
const width = offset.length()/maxHitDistance;
|
|
59
|
+
drawLine(this.pos, endPos, width, hsl(0,1,.5,.5),
|
|
60
|
+
vec2(), 0, false, false, overlayContext);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
class Pocket extends Box2dStaticObject
|
|
66
|
+
{
|
|
67
|
+
constructor(pos, size)
|
|
68
|
+
{
|
|
69
|
+
super(pos, size, 0, 0, BLACK);
|
|
70
|
+
|
|
71
|
+
// create a sensor circle for pocket
|
|
72
|
+
this.addCircle(size.x);
|
|
73
|
+
this.setSensor(true);
|
|
74
|
+
}
|
|
75
|
+
render()
|
|
76
|
+
{
|
|
77
|
+
// add ball size to pocket size for drawing
|
|
78
|
+
drawCircle(this.pos, this.size.x + 1, BLACK);
|
|
79
|
+
}
|
|
80
|
+
beginContact(other) { other.pocketed = 1; }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function gameInit()
|
|
84
|
+
{
|
|
85
|
+
// setup box2d
|
|
86
|
+
await box2dInit();
|
|
87
|
+
canvasClearColor = hsl(.4,.5,.5);
|
|
88
|
+
|
|
89
|
+
// create table walls
|
|
90
|
+
const groundObject = new Box2dStaticObject;
|
|
91
|
+
groundObject.color = hsl(.1,1,.2);
|
|
92
|
+
groundObject.addBox(vec2(100,3), vec2( 0, 8.5));
|
|
93
|
+
groundObject.addBox(vec2(100,3), vec2( 0,-8.5));
|
|
94
|
+
groundObject.addBox(vec2(3,100), vec2( 15,0));
|
|
95
|
+
groundObject.addBox(vec2(3,100), vec2(-15,0));
|
|
96
|
+
|
|
97
|
+
// create pockets
|
|
98
|
+
for (let j=0; j<2; ++j)
|
|
99
|
+
for (let i=0; i<3; ++i)
|
|
100
|
+
new Pocket(vec2(i-1, j-.5).scale(13), vec2(.5));
|
|
101
|
+
|
|
102
|
+
// create balls
|
|
103
|
+
let number = 1;
|
|
104
|
+
for (let i=5; i--;)
|
|
105
|
+
for (let j=i+1; j--;)
|
|
106
|
+
new Ball(vec2(6+i*.9, j-i/2), number++);
|
|
107
|
+
cueBall = new Ball(vec2(-6, 0));
|
|
108
|
+
}
|
|
@@ -8,12 +8,11 @@ class BounceObject extends EngineObject
|
|
|
8
8
|
|
|
9
9
|
update()
|
|
10
10
|
{
|
|
11
|
-
super.update();
|
|
12
|
-
|
|
13
11
|
// show debug info
|
|
14
12
|
debugText('Debug Text', this.pos.add(vec2(0,3)), 1, WHITE);
|
|
15
13
|
debugRect(this.pos, this.size, RED);
|
|
16
|
-
|
|
14
|
+
const trianglePoints = [vec2(-2,-1), vec2(0,2), vec2(2,-1)];
|
|
15
|
+
debugPoly(mousePos, trianglePoints, YELLOW);
|
|
17
16
|
debugLine(this.pos, mousePos, BLUE);
|
|
18
17
|
|
|
19
18
|
// bounce off screen edges
|
package/examples/shorts/fps.js
CHANGED
|
@@ -12,7 +12,7 @@ function gameUpdate()
|
|
|
12
12
|
if (keyWasPressed('Escape'))
|
|
13
13
|
pointerLockExit()
|
|
14
14
|
if (pointerLockIsActive() || isTouchDevice)
|
|
15
|
-
playerAngle += mouseDelta.x * .
|
|
15
|
+
playerAngle += mouseDelta.x * .03;
|
|
16
16
|
|
|
17
17
|
// update player movement, prevent walking through walls
|
|
18
18
|
const velocity = keyDirection().rotate(playerAngle).scale(.05);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
function gameUpdate()
|
|
2
|
+
{
|
|
3
|
+
if (isUsingGamepad)
|
|
4
|
+
{
|
|
5
|
+
debugText('Gamepad Mode', vec2(0,4));
|
|
6
|
+
|
|
7
|
+
// analog sticks
|
|
8
|
+
for (let i=2; i--;)
|
|
9
|
+
{
|
|
10
|
+
const stick = gamepadStick(i);
|
|
11
|
+
const pos = vec2(i?2:-2, 1);
|
|
12
|
+
debugCircle(pos, 2, WHITE);
|
|
13
|
+
debugLine(pos, pos.add(stick), GREEN);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// buttons
|
|
17
|
+
for (let i=16; i--;)
|
|
18
|
+
{
|
|
19
|
+
const pos = vec2(-1.5 + i%4, -2 - (i/4|0));
|
|
20
|
+
if (gamepadIsDown(i))
|
|
21
|
+
debugCircle(pos, 1, RED, 0, 1);
|
|
22
|
+
debugCircle(pos, 1, WHITE);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else if (isTouchDevice)
|
|
26
|
+
{
|
|
27
|
+
debugText('Touch Mode', vec2(0,4));
|
|
28
|
+
|
|
29
|
+
// touch input routed to mouse
|
|
30
|
+
if (mouseIsDown(0))
|
|
31
|
+
debugCircle(mousePos, 4, RED, 0, 1);
|
|
32
|
+
debugCircle(mousePos, 4, WHITE);
|
|
33
|
+
}
|
|
34
|
+
else
|
|
35
|
+
{
|
|
36
|
+
debugText('Mouse and Keyboard Mode', vec2(0,4));
|
|
37
|
+
|
|
38
|
+
// keyboard key (space bar)
|
|
39
|
+
debugRect(vec2(), vec2(2), WHITE);
|
|
40
|
+
if (keyIsDown('Space'))
|
|
41
|
+
debugRect(vec2(), vec2(2), RED, 0, 0, 1);
|
|
42
|
+
|
|
43
|
+
// keyboard direction (arrow keys or WASD)
|
|
44
|
+
const inputDirection = keyDirection();
|
|
45
|
+
debugLine(vec2(), inputDirection, GREEN);
|
|
46
|
+
|
|
47
|
+
// mouse pos
|
|
48
|
+
debugPoint(mousePos, mouseIsDown(0) ? RED : YELLOW);
|
|
49
|
+
|
|
50
|
+
// mouse buttons
|
|
51
|
+
for (let i=3; i--;)
|
|
52
|
+
{
|
|
53
|
+
const pos = vec2(-1 + i, -3);
|
|
54
|
+
if (mouseIsDown(i))
|
|
55
|
+
debugCircle(pos, 1, RED, 0, 1);
|
|
56
|
+
debugCircle(pos, 1, WHITE);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -9,12 +9,10 @@ class Player extends EngineObject
|
|
|
9
9
|
|
|
10
10
|
update()
|
|
11
11
|
{
|
|
12
|
-
super.update();
|
|
13
|
-
|
|
14
12
|
// space ship controls
|
|
15
13
|
const moveInput = keyDirection();
|
|
16
14
|
this.applyAngularAcceleration(moveInput.x * .002);
|
|
17
|
-
const accel = this.
|
|
15
|
+
const accel = this.getUp(moveInput.y*.002);
|
|
18
16
|
this.applyAcceleration(accel);
|
|
19
17
|
}
|
|
20
18
|
|
|
@@ -4,19 +4,25 @@ const medal_leftClick = new Medal(1, 'Lefty', 'Left clicked!', '🐁');
|
|
|
4
4
|
const medal_rightClick = new Medal(2, 'Righty', 'Right clicked!', '🐭');
|
|
5
5
|
const medal_spacePressed = new Medal(3, 'Space', 'Pressed spacebar!', '🚀');
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
function gameInit()
|
|
8
|
+
{
|
|
9
|
+
// setup medals
|
|
10
|
+
const saveName = 'Medals Example';
|
|
11
|
+
medalsInit(saveName);
|
|
12
|
+
|
|
13
|
+
// clear unlocked medals for testing
|
|
14
|
+
medalsForEach(medal=> medal.unlocked = false);
|
|
10
15
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
medal_openedExample.unlock();
|
|
16
|
+
// unlock the example medal
|
|
17
|
+
medal_openedExample.unlock();
|
|
14
18
|
|
|
15
|
-
// set background color
|
|
16
|
-
canvasClearColor = hsl(.5,.3,.2);
|
|
19
|
+
// set background color
|
|
20
|
+
canvasClearColor = hsl(.5,.3,.2);
|
|
21
|
+
}
|
|
17
22
|
|
|
18
23
|
function gameUpdate()
|
|
19
24
|
{
|
|
25
|
+
// unlock example medals based on input
|
|
20
26
|
if (mouseWasPressed(0))
|
|
21
27
|
medal_leftClick.unlock();
|
|
22
28
|
if (mouseWasPressed(2))
|
|
@@ -25,7 +31,7 @@ function gameUpdate()
|
|
|
25
31
|
medal_spacePressed.unlock();
|
|
26
32
|
}
|
|
27
33
|
|
|
28
|
-
function
|
|
34
|
+
function gameRenderPost()
|
|
29
35
|
{
|
|
30
36
|
const size = 80;
|
|
31
37
|
let pos = mainCanvasSize.scale(.5).subtract(vec2(0,40));
|
package/examples/shorts/music.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
let
|
|
3
|
-
let musicVolume = 1;
|
|
4
|
-
let music;
|
|
1
|
+
const musicSound = new SoundWave('song.mp3');
|
|
2
|
+
let musicVolume = 1, musicInstance;
|
|
5
3
|
|
|
6
4
|
function gameInit()
|
|
7
5
|
{
|
|
@@ -13,7 +11,8 @@ function gameInit()
|
|
|
13
11
|
canvasClearColor = hsl(.9,.3,.2);
|
|
14
12
|
|
|
15
13
|
// setup music player UI
|
|
16
|
-
|
|
14
|
+
const center = mainCanvasSize.scale(.5);
|
|
15
|
+
musicPlayer = new UIObject(center, vec2(500, 220));
|
|
17
16
|
|
|
18
17
|
// infomation text
|
|
19
18
|
infoText = new UIText(vec2(0, -70), vec2(400, 50));
|
|
@@ -26,8 +25,7 @@ function gameInit()
|
|
|
26
25
|
volumeSlider.onChange = () =>
|
|
27
26
|
{
|
|
28
27
|
musicVolume = volumeSlider.value;
|
|
29
|
-
|
|
30
|
-
music.setVolume(musicVolume);
|
|
28
|
+
musicInstance?.setVolume(musicVolume);
|
|
31
29
|
};
|
|
32
30
|
|
|
33
31
|
// play button
|
|
@@ -39,17 +37,17 @@ function gameInit()
|
|
|
39
37
|
return;
|
|
40
38
|
|
|
41
39
|
// handle play/pause toggle
|
|
42
|
-
if (!
|
|
43
|
-
|
|
44
|
-
else if (
|
|
45
|
-
|
|
40
|
+
if (!musicInstance)
|
|
41
|
+
musicInstance = musicSound.playMusic(musicVolume);
|
|
42
|
+
else if (musicInstance.isPaused())
|
|
43
|
+
musicInstance.resume();
|
|
46
44
|
else
|
|
47
|
-
|
|
45
|
+
musicInstance.pause();
|
|
48
46
|
};
|
|
49
47
|
|
|
50
48
|
// stop button
|
|
51
49
|
stopButton = new UIButton(vec2(90, 50), vec2(140, 50), 'Stop');
|
|
52
|
-
stopButton.onClick = ()=>
|
|
50
|
+
stopButton.onClick = ()=> musicInstance?.stop();
|
|
53
51
|
musicPlayer.addChild(stopButton);
|
|
54
52
|
}
|
|
55
53
|
|
|
@@ -69,10 +67,10 @@ function gameUpdate()
|
|
|
69
67
|
else
|
|
70
68
|
{
|
|
71
69
|
// update ui text
|
|
72
|
-
const isPlaying =
|
|
70
|
+
const isPlaying = musicInstance?.isPlaying();
|
|
73
71
|
playButton.text = isPlaying ? 'Pause' : 'Play';
|
|
74
|
-
const current =
|
|
75
|
-
const duration = musicSound.getDuration();
|
|
76
|
-
infoText.text =
|
|
72
|
+
const current = formatTime(musicInstance?.getCurrentTime());
|
|
73
|
+
const duration = formatTime(musicSound.getDuration());
|
|
74
|
+
infoText.text = current + ' / ' + duration;
|
|
77
75
|
}
|
|
78
76
|
}
|