littlejsengine 1.14.19 → 1.14.28
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 +217 -38
- package/dist/littlejs.esm.js +879 -324
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +861 -324
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +799 -325
- package/examples/box2d/gameObjects.js +6 -10
- package/examples/box2d/scenes.js +2 -2
- package/examples/breakout/gameObjects.js +1 -1
- package/examples/electron/game.js +1 -41
- package/examples/electron/index.html +2 -2
- package/examples/htmlMenu/game.js +1 -1
- package/examples/index.html +19 -10
- package/examples/module/game.js +5 -7
- package/examples/particles/index.html +6 -9
- package/examples/platformer/gameCharacter.js +4 -3
- package/examples/platformer/gameEffects.js +7 -2
- package/examples/platformer/gameObjects.js +6 -11
- package/examples/shorts/animation.js +2 -2
- package/examples/shorts/base.html +4 -1
- package/examples/shorts/box2d.js +2 -2
- package/examples/shorts/box2dCar.js +18 -7
- package/examples/shorts/box2dPool.js +108 -0
- package/examples/shorts/cameraDrag.js +22 -0
- package/examples/shorts/debugDraw.js +37 -0
- package/examples/shorts/flappyGame.js +1 -0
- package/examples/shorts/fps.js +90 -0
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/hillGlideGame.js +1 -3
- 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/postProcess.js +1 -1
- package/examples/shorts/sequencer.js +3 -3
- package/examples/shorts/slidingPuzzle.js +1 -1
- package/examples/shorts/spaceGame.js +1 -3
- package/examples/shorts/spriteAtlas.js +6 -8
- package/examples/shorts/starfield.js +1 -1
- package/examples/shorts/tileRaycast.js +39 -0
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +1 -4
- package/examples/shorts/timers.js +1 -2
- package/examples/shorts/topDown.js +0 -2
- package/examples/starter/game.js +5 -7
- package/examples/starter/index.html +2 -2
- package/examples/typescript/game.js +3 -2
- package/examples/typescript/game.ts +5 -7
- package/examples/uiSystem/game.js +2 -2
- package/package.json +1 -1
- package/plugins/box2d.js +170 -50
- package/plugins/pluginExport.js +2 -0
- package/plugins/uiSystem.js +55 -27
- package/src/engine.js +19 -16
- package/src/engineAudio.js +27 -15
- package/src/engineDebug.js +64 -0
- package/src/engineDraw.js +88 -32
- package/src/engineExport.js +16 -0
- package/src/engineInput.js +35 -25
- package/src/engineMedals.js +2 -2
- package/src/engineObject.js +55 -10
- package/src/engineParticles.js +36 -20
- package/src/engineRelease.js +2 -1
- package/src/engineSettings.js +20 -1
- package/src/engineTileLayer.js +64 -59
- package/src/engineUtilities.js +213 -59
- package/src/engineWebGL.js +13 -8
- package/examples/shorts/raycasting.js +0 -79
|
@@ -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
|
|
|
@@ -16,13 +16,6 @@ setTileFixBleedScale(.5);
|
|
|
16
16
|
// sound effects
|
|
17
17
|
const sound_click = new Sound([1,.5]);
|
|
18
18
|
|
|
19
|
-
// medals
|
|
20
|
-
const medal_example = new Medal(0, 'Example Medal', 'Welcome to LittleJS!');
|
|
21
|
-
medalsInit('Hello World');
|
|
22
|
-
|
|
23
|
-
// game variables
|
|
24
|
-
let particleEmitter;
|
|
25
|
-
|
|
26
19
|
///////////////////////////////////////////////////////////////////////////////
|
|
27
20
|
function gameInit()
|
|
28
21
|
{
|
|
@@ -58,23 +51,6 @@ function gameInit()
|
|
|
58
51
|
// setup camera
|
|
59
52
|
setCameraPos(vec2(16,8));
|
|
60
53
|
setCameraScale(32);
|
|
61
|
-
|
|
62
|
-
// enable gravity
|
|
63
|
-
setGravity(vec2(0,-.01));
|
|
64
|
-
|
|
65
|
-
// create particle emitter
|
|
66
|
-
particleEmitter = new ParticleEmitter(
|
|
67
|
-
vec2(16,9), 0, // emitPos, emitAngle
|
|
68
|
-
0, 0, 500, PI, // emitSize, emitTime, rate, cone
|
|
69
|
-
tile(0, 16), // tileIndex, tileSize
|
|
70
|
-
hsl(1,1,1), hsl(0,0,0), // colorStartA, colorStartB
|
|
71
|
-
hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
|
|
72
|
-
1, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
73
|
-
.99, 1, 1, PI, // damping, angleDamping, gravityScale, cone
|
|
74
|
-
.05, .5, true, true // fadeRate, randomness, collide, additive
|
|
75
|
-
);
|
|
76
|
-
particleEmitter.restitution = .3; // bounce when it collides
|
|
77
|
-
particleEmitter.trailScale = 2; // stretch as it moves
|
|
78
54
|
}
|
|
79
55
|
|
|
80
56
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -84,15 +60,6 @@ function gameUpdate()
|
|
|
84
60
|
{
|
|
85
61
|
// play sound when mouse is pressed
|
|
86
62
|
sound_click.play(mousePos);
|
|
87
|
-
|
|
88
|
-
// change particle color and set to fade out
|
|
89
|
-
particleEmitter.colorStartA = randColor();
|
|
90
|
-
particleEmitter.colorStartB = randColor();
|
|
91
|
-
particleEmitter.colorEndA = particleEmitter.colorStartA.scale(1,0);
|
|
92
|
-
particleEmitter.colorEndB = particleEmitter.colorStartB.scale(1,0);
|
|
93
|
-
|
|
94
|
-
// unlock medals
|
|
95
|
-
medal_example.unlock();
|
|
96
63
|
}
|
|
97
64
|
|
|
98
65
|
if (mouseWheel)
|
|
@@ -101,13 +68,6 @@ function gameUpdate()
|
|
|
101
68
|
cameraScale -= sign(mouseWheel)*cameraScale/5;
|
|
102
69
|
cameraScale = clamp(cameraScale, 10, 300);
|
|
103
70
|
}
|
|
104
|
-
|
|
105
|
-
// move particles to mouse location if on screen
|
|
106
|
-
if (mousePosScreen.x)
|
|
107
|
-
{
|
|
108
|
-
particleEmitter.pos = mousePos;
|
|
109
|
-
particleEmitter.velocity = mouseDelta.scale(.3*timeDelta);
|
|
110
|
-
}
|
|
111
71
|
}
|
|
112
72
|
|
|
113
73
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -130,7 +90,7 @@ function gameRender()
|
|
|
130
90
|
function gameRenderPost()
|
|
131
91
|
{
|
|
132
92
|
// draw to overlay canvas for hud rendering
|
|
133
|
-
drawTextScreen('LittleJS Demo',
|
|
93
|
+
drawTextScreen('LittleJS Electron Demo',
|
|
134
94
|
vec2(mainCanvasSize.x/2, 70), 80, // position, size
|
|
135
95
|
hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
|
|
136
96
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</head><body>
|
|
8
8
|
|
|
9
9
|
<!-- LittleJS Engine -->
|
|
10
|
-
<script src=../../dist/littlejs.js?
|
|
10
|
+
<script src=../../dist/littlejs.js?1.15.0></script>
|
|
11
11
|
|
|
12
12
|
<!-- Add your game scripts here -->
|
|
13
|
-
<script src=game.js?
|
|
13
|
+
<script src=game.js?1.15.0></script>
|
|
@@ -64,7 +64,7 @@ function gameRender()
|
|
|
64
64
|
for (let i=0; i<1e3; ++i)
|
|
65
65
|
{
|
|
66
66
|
const time = LJS.time;
|
|
67
|
-
const pos = vec2(30*
|
|
67
|
+
const pos = vec2(30*LJS.sin(i+time/9),20*LJS.sin(i*i+time/9));
|
|
68
68
|
LJS.drawTile(pos, vec2(2), tile(3,128), hsl(i/9,1,.4), time+i, !(i%2), hsl(i/9,1,.1,0));
|
|
69
69
|
}
|
|
70
70
|
}
|
package/examples/index.html
CHANGED
|
@@ -84,29 +84,34 @@ 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
|
-
new ExampleInfo('Shapes', 'shapes.js', 'Draw geometric shapes and primitives', false, 'circle,
|
|
93
|
-
new ExampleInfo('Colors', 'colors.js', 'Color manipulation and HSL', false, 'hue, saturation, blending,
|
|
94
|
-
new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield', false, 'space, movement, depth, rectangles'),
|
|
92
|
+
new ExampleInfo('Shapes', 'shapes.js', 'Draw geometric shapes and primitives', false, 'circle, ellipse, rectangle, polygon, lines'),
|
|
93
|
+
new ExampleInfo('Colors', 'colors.js', 'Color manipulation and HSL', false, 'hue, saturation, blending, 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
102
|
new ExampleInfo('Font Image', 'systemFont.js', 'Bitmap font system with built-in system font', false, 'text, characters'),
|
|
103
|
+
new ExampleInfo('Medals', 'medals.js', 'Achievement system', false, 'unlock, progress, newgrounds'),
|
|
104
|
+
new ExampleInfo('Tile Raycast', 'tileRaycast.js', 'Example of the tile layer raycast collision', false, 'level, map, grid'),
|
|
105
|
+
new ExampleInfo('Camera Mouse Drag', 'cameraDrag.js', 'Example of how to control camera with mose', false, 'ui, input, control'),
|
|
106
|
+
new ExampleInfo('Debug Drawing', 'debugDraw.js', 'Debug drawing system', false, 'debug, circle, line, rectangle'),
|
|
107
|
+
new ExampleInfo('--- ADVANCED ---'),
|
|
108
|
+
new ExampleInfo('Clock', 'clock.js', 'Animated analog clock', false, 'time, rotation, lines, rectangle'),
|
|
109
|
+
new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield', false, 'space, movement, depth, rectangle'),
|
|
103
110
|
new ExampleInfo('Parallax', 'parallax.js', 'Parallax scrolling mountains', false, 'generative, canvas, background'),
|
|
104
111
|
new ExampleInfo('Maze Generator', 'maze.js', 'Procedural maze generation', false, 'generative, level, tiles, map, grid'),
|
|
105
|
-
new ExampleInfo('Medals', 'medals.js', 'Achievement system', false, 'unlock, progress, newgrounds'),
|
|
106
|
-
new ExampleInfo('Clock', 'clock.js', 'Animated analog clock', false, 'time, rotation, lines, rectangles'),
|
|
107
112
|
new ExampleInfo('Piano', 'piano.js', 'Interactive piano keyboard', false, 'music, sound, audio, notes, ui, instrument'),
|
|
108
113
|
new ExampleInfo('Step Sequencer', 'sequencer.js', 'Simple music loop creation tool', false, 'music, sound, audio, notes, ui, instrument'),
|
|
109
|
-
new ExampleInfo('Music Player', 'musicPlayer.js', '
|
|
114
|
+
new ExampleInfo('Music Player', 'musicPlayer.js', 'Music player with audio seeking and drag and drop', false, 'sound, loading, audio, ui'),
|
|
110
115
|
new ExampleInfo('WebGL Shader', 'shader.js', 'Full canvas webgl shader', false, 'webgl, visual, effect'),
|
|
111
116
|
new ExampleInfo('--- MINI GAMES ---'),
|
|
112
117
|
new ExampleInfo('Pong Game', 'pongGame.js', 'Classic paddle ball bouncing', false, 'objects, collision'),
|
|
@@ -118,10 +123,11 @@ const exampleList =
|
|
|
118
123
|
new ExampleInfo('Hill Glide Game', 'hillGlideGame.js', 'Tiny wings style sliding game', false, 'objects, physics, speed'),
|
|
119
124
|
new ExampleInfo('Sliding Puzzle', 'slidingPuzzle.js', '15 tile sliding puzzle', false, 'objects, numbers, ui'),
|
|
120
125
|
new ExampleInfo('Space Game', 'spaceGame.js', 'Spaceship shooter with parallax', false, 'objects, weapons, stars, camera, rotation'),
|
|
121
|
-
new ExampleInfo('
|
|
126
|
+
new ExampleInfo('3D FPS Game', 'fps.js', 'Pseudo 3D raycasting demo', false, '3D, FPS, maze, camera'),
|
|
122
127
|
new ExampleInfo('--- PLUGINS ---'),
|
|
123
128
|
new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin', false, 'objects, mouse'),
|
|
124
129
|
new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics', false, 'objects, vehicle, suspension, wheels'),
|
|
130
|
+
new ExampleInfo('Box2d Pool', 'box2dPool.js', 'Billiard table pool game with physics', false, 'objects, game'),
|
|
125
131
|
new ExampleInfo('Post Processing', 'postProcess.js', 'Shader effects and filters', false, 'webgl, visual, effect'),
|
|
126
132
|
new ExampleInfo('UI System Plugin', 'uiSystem.js', 'Buttons, sliders, and checkboxes', false, 'objects, widgets, interactive'),
|
|
127
133
|
new ExampleInfo('Nine Slice', 'nineSlice.js', 'Scalable UI panels', false, 'three slice, stretch, corners, text, tiles'),
|
|
@@ -551,7 +557,10 @@ function setCode(code, filename)
|
|
|
551
557
|
{
|
|
552
558
|
// setup frame controls
|
|
553
559
|
setFrameControlsEnabled();
|
|
554
|
-
iframeContent.
|
|
560
|
+
if (iframeContent.glCanEnable())
|
|
561
|
+
iframeContent.setGLEnable(checkboxWebGL.checked);
|
|
562
|
+
else
|
|
563
|
+
checkboxWebGL.disabled = true;
|
|
555
564
|
checkboxWebGL.onchange = ()=> iframeContent.setGLEnable(checkboxWebGL.checked);
|
|
556
565
|
})
|
|
557
566
|
}
|
package/examples/module/game.js
CHANGED
|
@@ -69,16 +69,17 @@ function gameInit()
|
|
|
69
69
|
// create particle emitter
|
|
70
70
|
particleEmitter = new LJS.ParticleEmitter(
|
|
71
71
|
vec2(16,9), 0, // emitPos, emitAngle
|
|
72
|
-
|
|
72
|
+
0, 0, 500, 3.14, // emitSize, emitTime, rate, cone
|
|
73
73
|
tile(0, 16), // tileIndex, tileSize
|
|
74
74
|
hsl(1,1,1), hsl(0,0,0), // colorStartA, colorStartB
|
|
75
75
|
hsl(0,0,0,0), hsl(0,0,0,0), // colorEndA, colorEndB
|
|
76
|
-
1, .2, .2, .1, .05,
|
|
77
|
-
.99, 1, 1,
|
|
78
|
-
.05, .5, true, true
|
|
76
|
+
1, .2, .2, .1, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
|
|
77
|
+
.99, 1, 1, 3.14, // damping, angleDamping, gravityScale, cone
|
|
78
|
+
.05, .5, true, true // fadeRate, randomness, collide, additive
|
|
79
79
|
);
|
|
80
80
|
particleEmitter.restitution = .3; // bounce when it collides
|
|
81
81
|
particleEmitter.trailScale = 2; // stretch as it moves
|
|
82
|
+
particleEmitter.velocityInheritance = .3; // inherit emitter velocity
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -101,10 +102,7 @@ function gameUpdate()
|
|
|
101
102
|
|
|
102
103
|
// move particles to mouse location if on screen
|
|
103
104
|
if (LJS.mousePosScreen.x)
|
|
104
|
-
{
|
|
105
105
|
particleEmitter.pos = LJS.mousePos;
|
|
106
|
-
particleEmitter.velocity = LJS.mouseDelta.scale(.3*LJS.timeDelta);
|
|
107
|
-
}
|
|
108
106
|
}
|
|
109
107
|
|
|
110
108
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -298,12 +298,10 @@ function getCode()
|
|
|
298
298
|
{
|
|
299
299
|
const expand = inputExpand.checked;
|
|
300
300
|
let code = '';
|
|
301
|
-
|
|
302
|
-
//
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
return Math.round((this + Number.EPSILON) * d) / d;
|
|
306
|
-
}
|
|
301
|
+
|
|
302
|
+
// limit float precision to prevent long strings
|
|
303
|
+
const trimFloat = (n, decimals=3)=>
|
|
304
|
+
Number(Number(n).toFixed(decimals));
|
|
307
305
|
|
|
308
306
|
code = 'new ParticleEmitter(';
|
|
309
307
|
if (expand)
|
|
@@ -325,13 +323,12 @@ function getCode()
|
|
|
325
323
|
else if (type == 'color')
|
|
326
324
|
{
|
|
327
325
|
const c = particleSystem[name];
|
|
328
|
-
|
|
329
|
-
value = `new Color(${c.r.round(p)}, ${c.g.round(p)}, ${c.b.round(p)}, ${c.a.round(p)})`;
|
|
326
|
+
value = `new Color(${trimFloat(c.r)}, ${trimFloat(c.g)}, ${trimFloat(c.b)}, ${trimFloat(c.a)})`;
|
|
330
327
|
}
|
|
331
328
|
else if (type == 'checkbox')
|
|
332
329
|
value = particleSystem[name] ? 1 : 0;
|
|
333
330
|
else
|
|
334
|
-
value = particleSystem[name]
|
|
331
|
+
value = trimFloat(particleSystem[name]);
|
|
335
332
|
if (expand)
|
|
336
333
|
code += ' ';
|
|
337
334
|
code += value;
|
|
@@ -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;
|
|
@@ -238,7 +239,7 @@ export class Character extends GameObjects.GameObject
|
|
|
238
239
|
if (!this.isDead())
|
|
239
240
|
{
|
|
240
241
|
// bounce pos with walk cycle
|
|
241
|
-
bodyPos = bodyPos.add(vec2(0,.05*
|
|
242
|
+
bodyPos = bodyPos.add(vec2(0,.05*LJS.sin(this.walkCyclePercent*LJS.PI)));
|
|
242
243
|
|
|
243
244
|
// make bottom flush
|
|
244
245
|
bodyPos = bodyPos.add(vec2(0,(this.drawSize.y-this.size.y)/2));
|
|
@@ -15,6 +15,9 @@ import * as LJS from '../../dist/littlejs.esm.js';
|
|
|
15
15
|
import * as GameLevel from './gameLevel.js';
|
|
16
16
|
const {vec2, hsl, rgb} = LJS;
|
|
17
17
|
|
|
18
|
+
// use low graphics mode on mobile devices
|
|
19
|
+
const lowGraphicsMode = LJS.isTouchDevice;
|
|
20
|
+
|
|
18
21
|
///////////////////////////////////////////////////////////////////////////////
|
|
19
22
|
// sound effects
|
|
20
23
|
|
|
@@ -33,7 +36,9 @@ export const sound_score = new LJS.Sound([,,783,,.03,.02,1,2,,,940,.03,,,
|
|
|
33
36
|
|
|
34
37
|
export const persistentParticleDestroyCallback = (particle)=>
|
|
35
38
|
{
|
|
36
|
-
|
|
39
|
+
if (lowGraphicsMode) return;
|
|
40
|
+
|
|
41
|
+
// draw particle to tile layer on death
|
|
37
42
|
LJS.ASSERT(!particle.tileInfo, 'quick draw to tile layer uses canvas 2d so must be untextured');
|
|
38
43
|
if (particle.groundObject)
|
|
39
44
|
{
|
|
@@ -193,7 +198,7 @@ export class Sky extends LJS.EngineObject
|
|
|
193
198
|
// draw stars
|
|
194
199
|
LJS.setBlendMode(true);
|
|
195
200
|
const random = new LJS.RandomGenerator(this.seed);
|
|
196
|
-
for (let i=1e3; i--;)
|
|
201
|
+
for (let i= lowGraphicsMode ? 500 : 1e3; i--;)
|
|
197
202
|
{
|
|
198
203
|
const size = random.float(.5,2)**2;
|
|
199
204
|
const speed = random.float() < .9 ? random.float(5) : random.float(9,99);
|
|
@@ -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()
|
|
@@ -106,7 +105,7 @@ export class Coin extends LJS.EngineObject
|
|
|
106
105
|
|
|
107
106
|
// make it appear to spin
|
|
108
107
|
const t = LJS.time+this.pos.x/4+this.pos.y/4;
|
|
109
|
-
const spinSize = vec2(.5+.5*
|
|
108
|
+
const spinSize = vec2(.5+.5*LJS.sin(t*2*LJS.PI), 1);
|
|
110
109
|
if (spinSize.x > .1)
|
|
111
110
|
LJS.drawTile(this.pos, spinSize, this.tileInfo, this.color);
|
|
112
111
|
}
|
|
@@ -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
|
|
|
@@ -174,7 +173,7 @@ export class Enemy extends GameObject
|
|
|
174
173
|
{
|
|
175
174
|
// bounce by changing size
|
|
176
175
|
const bounceTime = this.bounceTime*6;
|
|
177
|
-
this.drawSize = vec2(1-.1*
|
|
176
|
+
this.drawSize = vec2(1-.1*LJS.sin(bounceTime), 1+.1*LJS.sin(bounceTime));
|
|
178
177
|
|
|
179
178
|
// make bottom flush
|
|
180
179
|
let bodyPos = this.pos;
|
|
@@ -221,7 +220,7 @@ export class Grenade extends GameObject
|
|
|
221
220
|
|
|
222
221
|
// draw additive flash exploding
|
|
223
222
|
LJS.setBlendMode(true);
|
|
224
|
-
const flash =
|
|
223
|
+
const flash = LJS.cos(this.getAliveTime()*2*LJS.PI);
|
|
225
224
|
LJS.drawTile(this.pos, vec2(2), Game.spriteAtlas.circle, hsl(0,1,.5,.2-.2*flash));
|
|
226
225
|
LJS.setBlendMode(false);
|
|
227
226
|
}
|
|
@@ -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(
|
|
@@ -4,13 +4,13 @@ function gameRender()
|
|
|
4
4
|
{
|
|
5
5
|
{
|
|
6
6
|
// animate by changing frames
|
|
7
|
-
const pos = vec2(-5, 2*abs(
|
|
7
|
+
const pos = vec2(-5, 2*abs(sin(time*2*PI)));
|
|
8
8
|
const frame = (time*4)%2|0;
|
|
9
9
|
drawTile(pos, vec2(7), tile(3).frame(frame), RED);
|
|
10
10
|
}
|
|
11
11
|
{
|
|
12
12
|
// animate with stretch and squash
|
|
13
|
-
const s =
|
|
13
|
+
const s = sin(time*9)*.5;
|
|
14
14
|
const size = vec2(7-s,7+s);
|
|
15
15
|
const pos = vec2(5,size.y-7);
|
|
16
16
|
drawTile(pos, size, tile(5), GREEN);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html><meta charset=utf-8><body>
|
|
2
|
-
<script src=../../dist/littlejs.js?
|
|
2
|
+
<script src=../../dist/littlejs.js?1.15.0></script>
|
|
3
3
|
<script src=../../dist/box2d.wasm.js></script>
|
|
4
4
|
|
|
5
5
|
<!-- LittleJS Engine Source
|
|
@@ -44,4 +44,7 @@ function gameUpdatePost() {}
|
|
|
44
44
|
function gameRender() {}
|
|
45
45
|
function gameRenderPost() {}
|
|
46
46
|
|
|
47
|
+
// check if WebGL can be enabled
|
|
48
|
+
function glCanEnable() { return glCanBeEnabled; }
|
|
49
|
+
|
|
47
50
|
</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
|
}
|