littlejsengine 1.12.4 → 1.12.6
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/box2d.wasm.js +630 -0
- package/dist/box2d.wasm.wasm +0 -0
- package/dist/littlejs.d.ts +52 -44
- package/dist/littlejs.esm.js +100 -97
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +98 -96
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +98 -96
- package/examples/box2d/game.js +36 -41
- package/examples/box2d/gameObjects.js +38 -35
- package/examples/box2d/index.html +1 -1
- package/examples/box2d/scenes.js +17 -13
- package/examples/box2d/tiles.png +0 -0
- package/examples/index.html +22 -14
- package/examples/platformer/game.js +6 -15
- package/examples/shorts/base.html +1 -0
- package/examples/shorts/box2d.js +46 -0
- package/examples/shorts/box2dCar.js +49 -0
- package/examples/shorts/postProcess.js +45 -0
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/uiSystem.js +39 -0
- package/examples/starter/game.js +2 -0
- package/examples/uiSystem/game.js +1 -1
- package/package.json +1 -1
- package/plugins/box2d.js +23 -29
- package/plugins/pluginExport.js +1 -1
- package/plugins/uiSystem.js +9 -3
- package/src/engine.js +10 -11
- package/src/engineAudio.js +24 -15
- package/src/engineBuild.js +12 -2
- package/src/engineExport.js +1 -0
- package/src/engineInput.js +3 -3
- package/src/engineUtilities.js +16 -0
- package/src/engineWebGL.js +13 -1
|
@@ -14,12 +14,16 @@ const {vec2, hsl} = LJS;
|
|
|
14
14
|
///////////////////////////////////////////////////////////////////////////////
|
|
15
15
|
// spawn object functions
|
|
16
16
|
|
|
17
|
+
const density = 1;
|
|
18
|
+
const friction = .5;
|
|
19
|
+
const restitution = .2;
|
|
20
|
+
|
|
17
21
|
export function spawnBox(pos, size=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, applyTexture=true, angle=0)
|
|
18
22
|
{
|
|
19
23
|
size = typeof size == 'number' ? vec2(size) : size; // square
|
|
20
24
|
const o = new LJS.Box2dObject(pos, size, applyTexture && Game.spriteAtlas.squareOutline, angle, color, type);
|
|
21
25
|
o.drawSize = size.scale(1.02); // slightly enlarge to cover gaps
|
|
22
|
-
o.addBox(size);
|
|
26
|
+
o.addBox(size, vec2(), 0, density, friction, restitution);
|
|
23
27
|
return o;
|
|
24
28
|
}
|
|
25
29
|
|
|
@@ -27,14 +31,14 @@ export function spawnCircle(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bod
|
|
|
27
31
|
{
|
|
28
32
|
const size = vec2(diameter);
|
|
29
33
|
const o = new LJS.Box2dObject(pos, size, applyTexture && Game.spriteAtlas.circleOutline, angle, color, type);
|
|
30
|
-
o.addCircle(diameter);
|
|
34
|
+
o.addCircle(diameter, vec2(), density, friction, restitution);
|
|
31
35
|
return o;
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
export function spawnRandomPoly(pos, diameter=1, color=LJS.WHITE, type=LJS.box2d.bodyTypeDynamic, angle=0)
|
|
35
39
|
{
|
|
36
40
|
const o = new LJS.Box2dObject(pos, vec2(), 0, angle, color, type);
|
|
37
|
-
o.addRandomPoly(diameter);
|
|
41
|
+
o.addRandomPoly(diameter, vec2(), 0, density, friction, restitution);
|
|
38
42
|
return o;
|
|
39
43
|
}
|
|
40
44
|
|
|
@@ -101,7 +105,7 @@ export class CarObject extends LJS.Box2dObject
|
|
|
101
105
|
{
|
|
102
106
|
constructor(pos)
|
|
103
107
|
{
|
|
104
|
-
super(pos, vec2(), 0, 0, LJS.
|
|
108
|
+
super(pos, vec2(), 0, 0, LJS.RED);
|
|
105
109
|
const carPoints = [
|
|
106
110
|
vec2(-1.5,-.5),
|
|
107
111
|
vec2(1.5, -.5),
|
|
@@ -112,50 +116,49 @@ export class CarObject extends LJS.Box2dObject
|
|
|
112
116
|
];
|
|
113
117
|
this.addPoly(carPoints);
|
|
114
118
|
|
|
119
|
+
// create wheels
|
|
120
|
+
const diameter = 1;
|
|
121
|
+
const density = 1;
|
|
122
|
+
const friction = 1;
|
|
123
|
+
const restitution = 0;
|
|
124
|
+
const damping = .7;
|
|
125
|
+
const frequency = 4;
|
|
126
|
+
const maxTorque = 35;
|
|
127
|
+
const sprite = Game.spriteAtlas.wheel;
|
|
128
|
+
this.wheels = [];
|
|
129
|
+
const makeWheel = (pos, isMotor) =>
|
|
115
130
|
{
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const damping = .7;
|
|
122
|
-
const frequencyHz = 4;
|
|
123
|
-
const maxTorque = 50;
|
|
124
|
-
const sprite = Game.spriteAtlas.wheel;
|
|
125
|
-
|
|
126
|
-
// create wheels
|
|
127
|
-
this.wheels = [];
|
|
128
|
-
const makeWheel = (pos, isMotor) =>
|
|
131
|
+
const wheel = new LJS.Box2dObject(pos, vec2(diameter), sprite);
|
|
132
|
+
const joint = new LJS.Box2dWheelJoint(this, wheel);
|
|
133
|
+
joint.setSpringDampingRatio(damping);
|
|
134
|
+
joint.setSpringFrequencyHz(frequency);
|
|
135
|
+
if (isMotor)
|
|
129
136
|
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this.
|
|
133
|
-
const joint = new LJS.Box2dWheelJoint(this, wheel);
|
|
134
|
-
joint.setSpringDampingRatio(damping);
|
|
135
|
-
joint.setSpringFrequencyHz(frequencyHz);
|
|
136
|
-
if (isMotor)
|
|
137
|
-
{
|
|
138
|
-
joint.setMaxMotorTorque(maxTorque);
|
|
139
|
-
joint.enableMotor(true);
|
|
140
|
-
this.wheelMotorJoint = joint;
|
|
141
|
-
}
|
|
137
|
+
joint.enableMotor();
|
|
138
|
+
joint.setMaxMotorTorque(maxTorque);
|
|
139
|
+
this.wheelMotorJoint = joint;
|
|
142
140
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
makeWheel(pos.add(vec2(-1, -.65)), true);
|
|
141
|
+
wheel.addCircle(diameter, vec2(), density, friction, restitution);
|
|
142
|
+
this.wheels.push(wheel);
|
|
146
143
|
}
|
|
144
|
+
|
|
145
|
+
makeWheel(pos.add(vec2( 1, -.6)));
|
|
146
|
+
makeWheel(pos.add(vec2(-1, -.65)), true);
|
|
147
147
|
}
|
|
148
|
-
|
|
148
|
+
update()
|
|
149
149
|
{
|
|
150
|
+
// car controls
|
|
150
151
|
const maxSpeed = 40;
|
|
151
152
|
const brakeAmount = .8;
|
|
153
|
+
const input = LJS.keyDirection().x;
|
|
152
154
|
let s = this.wheelMotorJoint.getMotorSpeed();
|
|
153
|
-
s = input ? LJS.clamp(s
|
|
155
|
+
s = input ? LJS.clamp(s - input, -maxSpeed, maxSpeed) : s * brakeAmount;
|
|
154
156
|
this.wheelMotorJoint.setMotorSpeed(s);
|
|
157
|
+
super.update();
|
|
155
158
|
}
|
|
156
159
|
destroy()
|
|
157
160
|
{
|
|
158
|
-
this.wheels.forEach(o=>o
|
|
161
|
+
this.wheels.forEach(o=>o.destroy());
|
|
159
162
|
super.destroy();
|
|
160
163
|
}
|
|
161
164
|
}
|
package/examples/box2d/scenes.js
CHANGED
|
@@ -23,11 +23,15 @@ import * as GameObjects from './gameObjects.js';
|
|
|
23
23
|
import * as Game from './game.js';
|
|
24
24
|
const {vec2} = LJS;
|
|
25
25
|
|
|
26
|
-
export
|
|
26
|
+
export let scene, sceneName;
|
|
27
|
+
|
|
28
|
+
export function loadScene(_scene)
|
|
27
29
|
{
|
|
30
|
+
scene = _scene;
|
|
31
|
+
|
|
28
32
|
if (scene == 0)
|
|
29
33
|
{
|
|
30
|
-
|
|
34
|
+
sceneName = 'Shapes';
|
|
31
35
|
GameObjects.spawnRandomEdges();
|
|
32
36
|
GameObjects.spawnBox(vec2(11,8), 4, LJS.randColor(), LJS.box2d.bodyTypeStatic, false);
|
|
33
37
|
GameObjects.spawnCircle(vec2(20,8), 4, LJS.randColor(), LJS.box2d.bodyTypeStatic, false);
|
|
@@ -37,14 +41,14 @@ export function loadScene(scene)
|
|
|
37
41
|
}
|
|
38
42
|
if (scene == 1)
|
|
39
43
|
{
|
|
40
|
-
|
|
44
|
+
sceneName = 'Pyramid';
|
|
41
45
|
GameObjects.spawnPyramid(vec2(20,0), 15);
|
|
42
46
|
GameObjects.spawnBox(vec2(10,2), 4, LJS.randColor());
|
|
43
47
|
GameObjects.spawnCircle(vec2(30,2), 4, LJS.randColor());
|
|
44
48
|
}
|
|
45
49
|
if (scene == 2)
|
|
46
50
|
{
|
|
47
|
-
|
|
51
|
+
sceneName = 'Dominoes';
|
|
48
52
|
GameObjects.spawnDominoes(vec2(11,11), 11);
|
|
49
53
|
GameObjects.spawnDominoes(vec2(2,0), 13, vec2(1,3));
|
|
50
54
|
GameObjects.spawnCircle(vec2(10,20), 2, LJS.randColor());
|
|
@@ -54,14 +58,14 @@ export function loadScene(scene)
|
|
|
54
58
|
}
|
|
55
59
|
if (scene == 3)
|
|
56
60
|
{
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
sceneName = 'Car';
|
|
62
|
+
new GameObjects.CarObject(vec2(10,2));
|
|
59
63
|
GameObjects.spawnBox(vec2(20,0), vec2(10,2), LJS.randColor(), LJS.box2d.bodyTypeStatic, false, -.2);
|
|
60
64
|
GameObjects.spawnPyramid(vec2(32,0), 6);
|
|
61
65
|
}
|
|
62
66
|
if (scene == 4)
|
|
63
67
|
{
|
|
64
|
-
|
|
68
|
+
sceneName = 'Rope';
|
|
65
69
|
const startPos = vec2(20, 14);
|
|
66
70
|
const angle = LJS.PI/2;
|
|
67
71
|
const color = LJS.randColor();
|
|
@@ -78,14 +82,14 @@ export function loadScene(scene)
|
|
|
78
82
|
}
|
|
79
83
|
if (scene == 5)
|
|
80
84
|
{
|
|
81
|
-
|
|
85
|
+
sceneName = 'Raycasts';
|
|
82
86
|
GameObjects.spawnRandomEdges();
|
|
83
87
|
for (let i=100;i--;)
|
|
84
88
|
GameObjects.spawnRandomObject(vec2(LJS.rand(1,39), LJS.rand(20)), 2, LJS.box2d.bodyTypeStatic, LJS.rand(LJS.PI*2));
|
|
85
89
|
}
|
|
86
90
|
if (scene == 6)
|
|
87
91
|
{
|
|
88
|
-
|
|
92
|
+
sceneName = 'Joints';
|
|
89
93
|
{
|
|
90
94
|
// prismatic joint
|
|
91
95
|
const o1 = GameObjects.spawnBox(vec2(20,8), vec2(3,2), LJS.randColor());
|
|
@@ -156,7 +160,7 @@ export function loadScene(scene)
|
|
|
156
160
|
}
|
|
157
161
|
if (scene == 7)
|
|
158
162
|
{
|
|
159
|
-
|
|
163
|
+
sceneName = 'Contacts';
|
|
160
164
|
new GameObjects.ContactTester(vec2(15,8), vec2(5), LJS.RED, LJS.RED);
|
|
161
165
|
new GameObjects.ContactTester(vec2(25,8), vec2(5), LJS.CYAN, LJS.CYAN, false, false);
|
|
162
166
|
for (let i=200;i--;)
|
|
@@ -164,19 +168,19 @@ export function loadScene(scene)
|
|
|
164
168
|
}
|
|
165
169
|
if (scene == 8)
|
|
166
170
|
{
|
|
167
|
-
|
|
171
|
+
sceneName = 'Mobile';
|
|
168
172
|
const pos = vec2(20, 16);
|
|
169
173
|
const mobile = new GameObjects.MobileObject(pos, 12, 2, 5);
|
|
170
174
|
new LJS.Box2dRevoluteJoint(Game.groundObject, mobile, pos);
|
|
171
175
|
}
|
|
172
176
|
if (scene == 9)
|
|
173
177
|
{
|
|
174
|
-
|
|
178
|
+
sceneName = 'Cloth'
|
|
175
179
|
new GameObjects.ClothObject(vec2(20, 9), vec2(15), vec2(24), LJS.randColor());
|
|
176
180
|
}
|
|
177
181
|
if (scene == 10)
|
|
178
182
|
{
|
|
179
|
-
|
|
183
|
+
sceneName = 'Softbodies';
|
|
180
184
|
for(let i=3;i--;)
|
|
181
185
|
new GameObjects.SoftBodyObject(vec2(20, 3+i*7), vec2(6-i), vec2(9-i), LJS.randColor());
|
|
182
186
|
}
|
package/examples/box2d/tiles.png
CHANGED
|
Binary file
|
package/examples/index.html
CHANGED
|
@@ -122,7 +122,7 @@ const exampleList =
|
|
|
122
122
|
new ExampleInfo('Hello World', 'helloWorld.js', 'Simplest example'),
|
|
123
123
|
new ExampleInfo('Shapes', 'shapes.js', 'How to draw geometric shapes'),
|
|
124
124
|
new ExampleInfo('Colors', 'colors.js', 'How to use the color object'),
|
|
125
|
-
new ExampleInfo('Blending', 'blending.js', '
|
|
125
|
+
new ExampleInfo('Blending', 'blending.js', 'How to use blending modes'),
|
|
126
126
|
new ExampleInfo('Timers', 'timers.js', 'How to use the timer object'),
|
|
127
127
|
new ExampleInfo('Texture', 'texture.js', 'How to display a full texture'),
|
|
128
128
|
new ExampleInfo('Particles', 'particles.js', 'How to use the particle system'),
|
|
@@ -130,12 +130,16 @@ const exampleList =
|
|
|
130
130
|
new ExampleInfo('System Font', 'systemFont.js', 'Demo of the included system font'),
|
|
131
131
|
new ExampleInfo('Sprite Atlas', 'spriteAtlas.js', 'How to set up a simple sprite atlas'),
|
|
132
132
|
new ExampleInfo('Animation', 'animation.js', 'How to animate sprites'),
|
|
133
|
-
new ExampleInfo('Clock', 'clock.js', '
|
|
133
|
+
new ExampleInfo('Clock', 'clock.js', 'Simple clock showing the time'),
|
|
134
134
|
new ExampleInfo('Tile Layer', 'tileLayer.js', 'How to use the tile layer object'),
|
|
135
|
-
new ExampleInfo('Platformer Game', 'platformer.js', '
|
|
136
|
-
new ExampleInfo('Top Down Game', 'topDown.js', '
|
|
135
|
+
new ExampleInfo('Platformer Game', 'platformer.js', 'Platformer jumping game'),
|
|
136
|
+
new ExampleInfo('Top Down Game', 'topDown.js', 'Rop down adventure game'),
|
|
137
137
|
new ExampleInfo('Tilted View', 'tiltedView.js', 'Pseudo 3D view with tilted camera'),
|
|
138
|
-
new ExampleInfo('Pong Game', 'pong.js', '
|
|
138
|
+
new ExampleInfo('Pong Game', 'pong.js', 'Simple pong game'),
|
|
139
|
+
new ExampleInfo('Box2d Demo', 'box2d.js', 'Demo of the Box2D physics plugin'),
|
|
140
|
+
new ExampleInfo('Box2d Car', 'box2dCar.js', 'Controllable vehicle using the Box2D physics plugin'),
|
|
141
|
+
new ExampleInfo('Post Processing', 'postProcess.js', 'Example of the post processing plugin'),
|
|
142
|
+
new ExampleInfo('UI System Plugin', 'uiSystem.js', 'Simple example of LittleJS UI plugin'),
|
|
139
143
|
|
|
140
144
|
new ExampleInfo('--- FULL EXAMPLES ---'),
|
|
141
145
|
new ExampleInfo('Starter', 'starter', 'Clean starter project', true),
|
|
@@ -205,7 +209,7 @@ function codeInput()
|
|
|
205
209
|
inputTimeout = setTimeout(() => setCode(textareaCode.value), 500);
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
function loadFile(filename, fullExample)
|
|
212
|
+
async function loadFile(filename, fullExample)
|
|
209
213
|
{
|
|
210
214
|
textareaCode.disabled = fullExample;
|
|
211
215
|
if (fullExample)
|
|
@@ -227,14 +231,18 @@ function loadFile(filename, fullExample)
|
|
|
227
231
|
return;
|
|
228
232
|
}
|
|
229
233
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
234
|
+
try
|
|
235
|
+
{
|
|
236
|
+
const response = await fetch(filename);
|
|
237
|
+
if (!response.ok)
|
|
238
|
+
throw new Error('Could not load file: ' + filename);
|
|
239
|
+
const text = await response.text();
|
|
240
|
+
setCode(textareaCode.value = text, fullExample);
|
|
241
|
+
}
|
|
242
|
+
catch (error)
|
|
243
|
+
{
|
|
244
|
+
setErrorMessage(error.message);
|
|
245
|
+
}
|
|
238
246
|
}
|
|
239
247
|
|
|
240
248
|
function setCode(code, largeExample)
|
|
@@ -16,14 +16,17 @@ import * as GamePlayer from './gamePlayer.js';
|
|
|
16
16
|
import * as GameLevel from './gameLevel.js';
|
|
17
17
|
const {vec2} = LJS;
|
|
18
18
|
|
|
19
|
-
//
|
|
20
|
-
LJS.
|
|
19
|
+
// load the game level data
|
|
20
|
+
export const gameLevelData = await LJS.fetchJSON('gameLevelData.json');
|
|
21
21
|
|
|
22
22
|
// globals
|
|
23
|
-
export let spriteAtlas, player, score, deaths
|
|
23
|
+
export let spriteAtlas, player, score, deaths;
|
|
24
24
|
export function addToScore(delta=1) { score += delta; }
|
|
25
25
|
export function addToDeaths() { ++deaths; }
|
|
26
26
|
|
|
27
|
+
// enable touch gamepad on touch devices
|
|
28
|
+
LJS.setTouchGamepadEnable(true);
|
|
29
|
+
|
|
27
30
|
///////////////////////////////////////////////////////////////////////////////
|
|
28
31
|
function loadLevel()
|
|
29
32
|
{
|
|
@@ -41,18 +44,6 @@ function loadLevel()
|
|
|
41
44
|
///////////////////////////////////////////////////////////////////////////////
|
|
42
45
|
async function gameInit()
|
|
43
46
|
{
|
|
44
|
-
try
|
|
45
|
-
{
|
|
46
|
-
// load level data from external JSON file
|
|
47
|
-
const response = await fetch('gameLevelData.json');
|
|
48
|
-
gameLevelData = await response.json();
|
|
49
|
-
console.log('Level data loaded successfully');
|
|
50
|
-
}
|
|
51
|
-
catch (error)
|
|
52
|
-
{
|
|
53
|
-
console.error('Failed to load level data!');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
47
|
// engine settings
|
|
57
48
|
LJS.setGravity(vec2(0,-.01));
|
|
58
49
|
LJS.setObjectDefaultDamping(.99);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
async function gameInit()
|
|
2
|
+
{
|
|
3
|
+
// setup box2d
|
|
4
|
+
await box2dInit();
|
|
5
|
+
mouseJoint = 0;
|
|
6
|
+
gravity.y = -50;
|
|
7
|
+
|
|
8
|
+
// create ground object
|
|
9
|
+
groundObject = new Box2dObject(vec2(-8), vec2(), 0, 0, GRAY, box2d.bodyTypeStatic);
|
|
10
|
+
groundObject.addBox(vec2(100,2));
|
|
11
|
+
|
|
12
|
+
// add some random objects
|
|
13
|
+
for(let i=50; i--;)
|
|
14
|
+
{
|
|
15
|
+
const o = new Box2dObject(randInCircle(5), vec2(), 0, 0, randColor());
|
|
16
|
+
randInt(2) ? o.addCircle(rand(1,2)) : o.addRandomPoly(rand(1,2));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function gameUpdate()
|
|
21
|
+
{
|
|
22
|
+
// mouse controls
|
|
23
|
+
if (mouseJoint)
|
|
24
|
+
{
|
|
25
|
+
// update mouse joint
|
|
26
|
+
mouseJoint.setTarget(mousePos);
|
|
27
|
+
if (mouseWasReleased(0))
|
|
28
|
+
{
|
|
29
|
+
// release object
|
|
30
|
+
mouseJoint = mouseJoint.destroy();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (mouseWasPressed(0))
|
|
34
|
+
{
|
|
35
|
+
// grab object
|
|
36
|
+
const object = box2d.pointCast(mousePos);
|
|
37
|
+
if (object)
|
|
38
|
+
mouseJoint = new Box2dTargetJoint(object, groundObject, mousePos);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function gameRenderPost()
|
|
43
|
+
{
|
|
44
|
+
// draw mouse joint
|
|
45
|
+
mouseJoint && drawLine(mousePos, mouseJoint.getAnchorB(), .2, RED);
|
|
46
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
async function gameInit()
|
|
2
|
+
{
|
|
3
|
+
// setup box2d and create the objects
|
|
4
|
+
await box2dInit();
|
|
5
|
+
gravity.y = -20;
|
|
6
|
+
groundObject = new Box2dObject(vec2(-8), vec2(), 0, 0, GRAY, box2d.bodyTypeStatic);
|
|
7
|
+
groundObject.addBox(vec2(100,6));
|
|
8
|
+
new CarObject(vec2(0,-2));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class CarObject extends Box2dObject
|
|
12
|
+
{
|
|
13
|
+
constructor(pos)
|
|
14
|
+
{
|
|
15
|
+
super(pos, vec2(), 0, 0, RED);
|
|
16
|
+
|
|
17
|
+
// create a car with wheels
|
|
18
|
+
this.addBox(vec2(7,2));
|
|
19
|
+
const frequency = 4, maxTorque = 250;
|
|
20
|
+
this.wheels = [];
|
|
21
|
+
for(let i=2; i--;)
|
|
22
|
+
{
|
|
23
|
+
const wheelPos = pos.add(vec2(i?2:-2, -1));
|
|
24
|
+
const wheel = new Box2dObject(wheelPos, vec2(2), tile(7));
|
|
25
|
+
const joint = new Box2dWheelJoint(this, wheel);
|
|
26
|
+
joint.setSpringFrequencyHz(frequency);
|
|
27
|
+
joint.setMaxMotorTorque(maxTorque);
|
|
28
|
+
joint.enableMotor(!i);
|
|
29
|
+
wheel.addCircle(2);
|
|
30
|
+
wheel.motorJoint = joint;
|
|
31
|
+
this.wheels[i] = wheel;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
update()
|
|
35
|
+
{
|
|
36
|
+
// car controls - use arrow keys or A/D to drive
|
|
37
|
+
const maxSpeed = 40, brakeAmount = .9;
|
|
38
|
+
const input = keyDirection().x;
|
|
39
|
+
let s = this.wheels[0].motorJoint.getMotorSpeed();
|
|
40
|
+
s = input ? clamp(s - input, -maxSpeed, maxSpeed) : s * brakeAmount;
|
|
41
|
+
this.wheels[0].motorJoint.setMotorSpeed(s);
|
|
42
|
+
super.update();
|
|
43
|
+
}
|
|
44
|
+
destroy()
|
|
45
|
+
{
|
|
46
|
+
this.wheels.forEach(o=>o.destroy());
|
|
47
|
+
super.destroy();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
function gameInit()
|
|
2
|
+
{
|
|
3
|
+
new PostProcessPlugin(tvShader);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function gameRender()
|
|
7
|
+
{
|
|
8
|
+
drawRect(vec2(), vec2(99), GRAY);
|
|
9
|
+
drawTile(vec2(), vec2(12), tile(3,128));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const tvShader = `
|
|
13
|
+
// Simple TV Shader Code
|
|
14
|
+
float hash(vec2 p)
|
|
15
|
+
{
|
|
16
|
+
p=fract(p*.3197);
|
|
17
|
+
return fract(1.+sin(51.*p.x+73.*p.y)*13753.3);
|
|
18
|
+
}
|
|
19
|
+
float noise(vec2 p)
|
|
20
|
+
{
|
|
21
|
+
vec2 i=floor(p),f=fract(p),u=f*f*(3.-2.*f);
|
|
22
|
+
return mix(mix(hash(i),hash(i+vec2(1,0)),u.x),mix(hash(i+vec2(0,1)),hash(i+1.),u.x),u.y);
|
|
23
|
+
}
|
|
24
|
+
void mainImage(out vec4 c, vec2 p)
|
|
25
|
+
{
|
|
26
|
+
// setup the shader
|
|
27
|
+
p /= iResolution.xy;
|
|
28
|
+
c = texture(iChannel0, p);
|
|
29
|
+
|
|
30
|
+
// static noise
|
|
31
|
+
const float staticAlpha = .1;
|
|
32
|
+
const float staticScale = .005;
|
|
33
|
+
c += staticAlpha * hash(floor(p/staticScale) + mod(iTime*500., 1e3));
|
|
34
|
+
|
|
35
|
+
// scan lines
|
|
36
|
+
const float scanlineScale = 2.;
|
|
37
|
+
const float scanlineAlpha = .3;
|
|
38
|
+
c *= 1. - scanlineAlpha*cos(p.y*2.*iResolution.y/scanlineScale);
|
|
39
|
+
|
|
40
|
+
// black vignette around edges
|
|
41
|
+
const float vignette = 2.;
|
|
42
|
+
const float vignettePow = 6.;
|
|
43
|
+
float dx = 2.*p.x-1., dy = 2.*p.y-1.;
|
|
44
|
+
c *= 1.-pow((dx*dx + dy*dy)/vignette, vignettePow);
|
|
45
|
+
}`;
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// globals objects
|
|
2
|
+
const sound_ui = new Sound([1,0]);
|
|
3
|
+
let uiMenu;
|
|
4
|
+
|
|
5
|
+
function gameInit()
|
|
6
|
+
{
|
|
7
|
+
// load ui system plugin
|
|
8
|
+
new UISystemPlugin;
|
|
9
|
+
|
|
10
|
+
// setup example menu
|
|
11
|
+
uiMenu = new UIObject(mainCanvasSize.scale(.5));
|
|
12
|
+
const uiBackground = new UIObject(vec2(), vec2(400));
|
|
13
|
+
uiMenu.addChild(uiBackground);
|
|
14
|
+
|
|
15
|
+
// example text
|
|
16
|
+
const textTitle = new UIText(vec2(0,-100), vec2(400, 60), 'LittleJS UI\nSystem Demo');
|
|
17
|
+
uiMenu.addChild(textTitle);
|
|
18
|
+
|
|
19
|
+
// example button
|
|
20
|
+
const button1 = new UIButton(vec2(70,40), vec2(100), 'Test');
|
|
21
|
+
button1.textHeight = 40;
|
|
22
|
+
uiMenu.addChild(button1);
|
|
23
|
+
button1.onPress = ()=> sound_ui.play();
|
|
24
|
+
|
|
25
|
+
// example checkbox
|
|
26
|
+
const checkbox = new UICheckbox(vec2(-70,40), vec2(50));
|
|
27
|
+
uiMenu.addChild(checkbox);
|
|
28
|
+
checkbox.onChange = ()=> sound_ui.play(0,1,checkbox.checked?4:1);
|
|
29
|
+
|
|
30
|
+
// exit button
|
|
31
|
+
const button2 = new UIButton(vec2(0,140), vec2(300, 50), 'Exit Menu');
|
|
32
|
+
button2.textHeight = 40;
|
|
33
|
+
uiMenu.addChild(button2);
|
|
34
|
+
button2.onPress = ()=>
|
|
35
|
+
{
|
|
36
|
+
uiMenu.visible = false;
|
|
37
|
+
sound_ui.play(0,1,2);
|
|
38
|
+
}
|
|
39
|
+
}
|
package/examples/starter/game.js
CHANGED
|
@@ -25,7 +25,7 @@ LJS.setCanvasPixelated(false);
|
|
|
25
25
|
function createUI()
|
|
26
26
|
{
|
|
27
27
|
// setup root to attach all ui elements to
|
|
28
|
-
uiRoot = new LJS.UIObject
|
|
28
|
+
uiRoot = new LJS.UIObject;
|
|
29
29
|
const uiInfo = new LJS.UIText(vec2(0,90), vec2(1e3, 70),
|
|
30
30
|
'LittleJS UI System Example\nM = Toggle menu');
|
|
31
31
|
uiInfo.textColor = LJS.WHITE;
|
package/package.json
CHANGED
package/plugins/box2d.js
CHANGED
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LittleJS Box2D Physics Plugin
|
|
3
3
|
* - Box2dObject extends EngineObject with Box2D physics
|
|
4
|
-
* - Call
|
|
4
|
+
* - Call box2dInit() before engineInit() to enable
|
|
5
5
|
* - You will also need to include box2d.wasm.js
|
|
6
|
-
* - Uses
|
|
6
|
+
* - Uses a super fast web assembly port of Box2D
|
|
7
7
|
* - More info: https://github.com/kripken/box2d.js
|
|
8
|
-
* - Fully wraps everything in Box2d
|
|
9
8
|
* - Functions to create polygon, circle, and edge shapes
|
|
10
|
-
* - Raycasting and querying
|
|
11
|
-
* - Joint creation
|
|
12
9
|
* - Contact begin and end callbacks
|
|
10
|
+
* - Wraps b2Vec2 type to/from Vector2
|
|
11
|
+
* - Raycasting and querying
|
|
12
|
+
* - Every type of joint
|
|
13
13
|
* - Debug physics drawing
|
|
14
|
+
* @namespace Box2D
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
'use strict';
|
|
17
18
|
|
|
18
19
|
/** Global Box2d Plugin object
|
|
19
|
-
* @type {Box2dPlugin}
|
|
20
|
+
* @type {Box2dPlugin}
|
|
21
|
+
* @memberof Box2D */
|
|
20
22
|
let box2d;
|
|
21
23
|
|
|
22
24
|
/** Enable Box2D debug drawing
|
|
23
25
|
* @type {boolean}
|
|
24
|
-
* @default
|
|
26
|
+
* @default
|
|
27
|
+
* @memberof Box2D */
|
|
25
28
|
let box2dDebug = false;
|
|
26
29
|
|
|
27
30
|
/** Enable Box2D debug drawing
|
|
28
|
-
* @param {boolean} enable
|
|
31
|
+
* @param {boolean} enable
|
|
32
|
+
* @memberof Box2D */
|
|
29
33
|
function box2dSetDebug(enable) { box2dDebug = enable; }
|
|
30
34
|
|
|
31
35
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -127,7 +131,7 @@ class Box2dObject extends EngineObject
|
|
|
127
131
|
* @param {number} [friction]
|
|
128
132
|
* @param {number} [restitution]
|
|
129
133
|
* @param {boolean} [isSensor] */
|
|
130
|
-
addShape(shape, density=1, friction
|
|
134
|
+
addShape(shape, density=1, friction=1, restitution=0, isSensor=false)
|
|
131
135
|
{
|
|
132
136
|
const fd = new box2d.instance.b2FixtureDef();
|
|
133
137
|
fd.set_shape(shape);
|
|
@@ -1766,28 +1770,18 @@ class Box2dPlugin
|
|
|
1766
1770
|
}
|
|
1767
1771
|
|
|
1768
1772
|
///////////////////////////////////////////////////////////////////////////////
|
|
1769
|
-
/** Box2d Init -
|
|
1770
|
-
* @
|
|
1771
|
-
* @
|
|
1772
|
-
|
|
1773
|
-
* @param {Function} gameRender - Called before objects are rendered, for drawing the background
|
|
1774
|
-
* @param {Function} gameRenderPost - Called after objects are rendered, useful for drawing UI
|
|
1775
|
-
* @param {Array<string>} [imageSources=[]] - List of images to load
|
|
1776
|
-
* @param {HTMLElement} [rootElement] - Root element to attach to, the document body by default */
|
|
1777
|
-
function box2dEngineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources, rootElement)
|
|
1773
|
+
/** Box2d Init - Call with await before starting LittleJS to init box2d
|
|
1774
|
+
* @return {Promise<Box2dPlugin>}
|
|
1775
|
+
* @memberof Box2D */
|
|
1776
|
+
async function box2dInit()
|
|
1778
1777
|
{
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
// start littlejs
|
|
1786
|
-
engineAddPlugin(box2dUpdate, box2dRender);
|
|
1787
|
-
engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, imageSources, rootElement);
|
|
1788
|
-
});
|
|
1778
|
+
// load box2d
|
|
1779
|
+
new Box2dPlugin(await Box2D());
|
|
1780
|
+
setupDebugDraw();
|
|
1781
|
+
engineAddPlugin(box2dUpdate, box2dRender);
|
|
1782
|
+
return box2d;
|
|
1789
1783
|
|
|
1790
|
-
//
|
|
1784
|
+
// add the box2d plugin to the engine
|
|
1791
1785
|
function box2dUpdate()
|
|
1792
1786
|
{
|
|
1793
1787
|
if (!paused)
|