littlejsengine 1.14.19 → 1.14.23
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 +118 -18
- package/dist/littlejs.esm.js +506 -199
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +493 -199
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +468 -200
- 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 +12 -6
- package/examples/module/game.js +5 -7
- package/examples/particles/index.html +6 -9
- package/examples/platformer/gameCharacter.js +1 -1
- package/examples/platformer/gameEffects.js +7 -2
- package/examples/platformer/gameObjects.js +3 -3
- package/examples/shorts/animation.js +2 -2
- package/examples/shorts/base.html +4 -1
- package/examples/shorts/cameraDrag.js +22 -0
- package/examples/shorts/debugDraw.js +38 -0
- package/examples/shorts/fps.js +90 -0
- package/examples/shorts/helloWorld.js +1 -1
- package/examples/shorts/hillGlideGame.js +1 -1
- package/examples/shorts/landerGame.js +1 -1
- package/examples/shorts/postProcess.js +1 -1
- package/examples/shorts/sequencer.js +3 -3
- package/examples/shorts/spaceGame.js +1 -1
- package/examples/shorts/spriteAtlas.js +6 -6
- 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 -1
- 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/src/engine.js +3 -3
- package/src/engineAudio.js +13 -13
- package/src/engineDebug.js +27 -0
- package/src/engineDraw.js +68 -20
- package/src/engineExport.js +13 -0
- package/src/engineInput.js +14 -16
- package/src/engineObject.js +31 -6
- package/src/engineParticles.js +36 -15
- package/src/engineRelease.js +2 -1
- package/src/engineSettings.js +20 -1
- package/src/engineTileLayer.js +62 -59
- package/src/engineUtilities.js +206 -58
- package/src/engineWebGL.js +13 -8
- package/examples/shorts/raycasting.js +0 -79
|
@@ -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.14.24></script>
|
|
11
11
|
|
|
12
12
|
<!-- Add your game scripts here -->
|
|
13
|
-
<script src=game.js?
|
|
13
|
+
<script src=game.js?1.14.24></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
|
@@ -89,9 +89,9 @@ const exampleList =
|
|
|
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,
|
|
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'),
|
|
94
|
+
new ExampleInfo('Starfield', 'starfield.js', 'Animated parallax starfield', false, 'space, movement, depth, rectangle'),
|
|
95
95
|
new ExampleInfo('Sprite Atlas', 'spriteAtlas.js', 'Sprite atlas and tile rendering', false, 'sheet, frames, tiles'),
|
|
96
96
|
new ExampleInfo('Blending', 'blending.js', 'Additive blending and transparency', false, 'alpha, color, tiles, smooth'),
|
|
97
97
|
new ExampleInfo('Tile Layer', 'tileLayer.js', 'Tile layer rendering system', false, 'level, map, grid, particles'),
|
|
@@ -103,7 +103,10 @@ const exampleList =
|
|
|
103
103
|
new ExampleInfo('Parallax', 'parallax.js', 'Parallax scrolling mountains', false, 'generative, canvas, background'),
|
|
104
104
|
new ExampleInfo('Maze Generator', 'maze.js', 'Procedural maze generation', false, 'generative, level, tiles, map, grid'),
|
|
105
105
|
new ExampleInfo('Medals', 'medals.js', 'Achievement system', false, 'unlock, progress, newgrounds'),
|
|
106
|
-
new ExampleInfo('
|
|
106
|
+
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
|
+
new ExampleInfo('Camera Mouse Drag', 'cameraDrag.js', 'Example of how to control camera with mose', false, 'ui, input, control'),
|
|
109
|
+
new ExampleInfo('Clock', 'clock.js', 'Animated analog clock', false, 'time, rotation, lines, rectangle'),
|
|
107
110
|
new ExampleInfo('Piano', 'piano.js', 'Interactive piano keyboard', false, 'music, sound, audio, notes, ui, instrument'),
|
|
108
111
|
new ExampleInfo('Step Sequencer', 'sequencer.js', 'Simple music loop creation tool', false, 'music, sound, audio, notes, ui, instrument'),
|
|
109
112
|
new ExampleInfo('Music Player', 'musicPlayer.js', 'Advanced music player with audio seeking and drag and drop', false, 'music, sound, audio, streaming, volume, ui'),
|
|
@@ -118,7 +121,7 @@ const exampleList =
|
|
|
118
121
|
new ExampleInfo('Hill Glide Game', 'hillGlideGame.js', 'Tiny wings style sliding game', false, 'objects, physics, speed'),
|
|
119
122
|
new ExampleInfo('Sliding Puzzle', 'slidingPuzzle.js', '15 tile sliding puzzle', false, 'objects, numbers, ui'),
|
|
120
123
|
new ExampleInfo('Space Game', 'spaceGame.js', 'Spaceship shooter with parallax', false, 'objects, weapons, stars, camera, rotation'),
|
|
121
|
-
new ExampleInfo('
|
|
124
|
+
new ExampleInfo('3D FPS Game', 'fps.js', 'Pseudo 3D raycasting demo', false, '3D, FPS, maze, camera'),
|
|
122
125
|
new ExampleInfo('--- PLUGINS ---'),
|
|
123
126
|
new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin', false, 'objects, mouse'),
|
|
124
127
|
new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics', false, 'objects, vehicle, suspension, wheels'),
|
|
@@ -551,7 +554,10 @@ function setCode(code, filename)
|
|
|
551
554
|
{
|
|
552
555
|
// setup frame controls
|
|
553
556
|
setFrameControlsEnabled();
|
|
554
|
-
iframeContent.
|
|
557
|
+
if (iframeContent.glCanEnable())
|
|
558
|
+
iframeContent.setGLEnable(checkboxWebGL.checked);
|
|
559
|
+
else
|
|
560
|
+
checkboxWebGL.disabled = true;
|
|
555
561
|
checkboxWebGL.onchange = ()=> iframeContent.setGLEnable(checkboxWebGL.checked);
|
|
556
562
|
})
|
|
557
563
|
}
|
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;
|
|
@@ -238,7 +238,7 @@ export class Character extends GameObjects.GameObject
|
|
|
238
238
|
if (!this.isDead())
|
|
239
239
|
{
|
|
240
240
|
// bounce pos with walk cycle
|
|
241
|
-
bodyPos = bodyPos.add(vec2(0,.05*
|
|
241
|
+
bodyPos = bodyPos.add(vec2(0,.05*LJS.sin(this.walkCyclePercent*LJS.PI)));
|
|
242
242
|
|
|
243
243
|
// make bottom flush
|
|
244
244
|
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);
|
|
@@ -106,7 +106,7 @@ export class Coin extends LJS.EngineObject
|
|
|
106
106
|
|
|
107
107
|
// make it appear to spin
|
|
108
108
|
const t = LJS.time+this.pos.x/4+this.pos.y/4;
|
|
109
|
-
const spinSize = vec2(.5+.5*
|
|
109
|
+
const spinSize = vec2(.5+.5*LJS.sin(t*2*LJS.PI), 1);
|
|
110
110
|
if (spinSize.x > .1)
|
|
111
111
|
LJS.drawTile(this.pos, spinSize, this.tileInfo, this.color);
|
|
112
112
|
}
|
|
@@ -174,7 +174,7 @@ export class Enemy extends GameObject
|
|
|
174
174
|
{
|
|
175
175
|
// bounce by changing size
|
|
176
176
|
const bounceTime = this.bounceTime*6;
|
|
177
|
-
this.drawSize = vec2(1-.1*
|
|
177
|
+
this.drawSize = vec2(1-.1*LJS.sin(bounceTime), 1+.1*LJS.sin(bounceTime));
|
|
178
178
|
|
|
179
179
|
// make bottom flush
|
|
180
180
|
let bodyPos = this.pos;
|
|
@@ -221,7 +221,7 @@ export class Grenade extends GameObject
|
|
|
221
221
|
|
|
222
222
|
// draw additive flash exploding
|
|
223
223
|
LJS.setBlendMode(true);
|
|
224
|
-
const flash =
|
|
224
|
+
const flash = LJS.cos(this.getAliveTime()*2*LJS.PI);
|
|
225
225
|
LJS.drawTile(this.pos, vec2(2), Game.spriteAtlas.circle, hsl(0,1,.5,.2-.2*flash));
|
|
226
226
|
LJS.setBlendMode(false);
|
|
227
227
|
}
|
|
@@ -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.14.24></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>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function gameInit()
|
|
2
|
+
{
|
|
3
|
+
// create some objects
|
|
4
|
+
for (let i=500; i--;)
|
|
5
|
+
{
|
|
6
|
+
const pos = randInCircle(100);
|
|
7
|
+
const size = vec2(rand(2,9),rand(2,9));
|
|
8
|
+
const color = randColor();
|
|
9
|
+
const angle = rand(PI);
|
|
10
|
+
new EngineObject(pos, size, 0, angle, color);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function gameUpdate()
|
|
15
|
+
{
|
|
16
|
+
// drag camera with mouse
|
|
17
|
+
if (mouseIsDown(0))
|
|
18
|
+
cameraPos = cameraPos.subtract(mouseDelta);
|
|
19
|
+
|
|
20
|
+
// zoom camera with mouse wheel
|
|
21
|
+
cameraScale = clamp(cameraScale*(1-mouseWheel/5), 1, 1e3);
|
|
22
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
class BounceObject extends EngineObject
|
|
2
|
+
{
|
|
3
|
+
constructor(pos, size, tile)
|
|
4
|
+
{
|
|
5
|
+
super(pos, size, tile);
|
|
6
|
+
this.velocity = vec2(.1);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
update()
|
|
10
|
+
{
|
|
11
|
+
super.update();
|
|
12
|
+
|
|
13
|
+
// show debug info
|
|
14
|
+
debugText('Debug Text', this.pos.add(vec2(0,3)), 1, WHITE);
|
|
15
|
+
debugRect(this.pos, this.size, RED);
|
|
16
|
+
debugPoly(mousePos, [vec2(-2,-1), vec2(0,2), vec2(2,-1)], YELLOW);
|
|
17
|
+
debugLine(this.pos, mousePos, BLUE);
|
|
18
|
+
|
|
19
|
+
// bounce off screen edges
|
|
20
|
+
const cameraSize = getCameraSize();
|
|
21
|
+
if (abs(this.pos.x) > cameraSize.x/2)
|
|
22
|
+
{
|
|
23
|
+
debugCircle(this.pos, 3, GREEN, 1);
|
|
24
|
+
this.velocity.x = -this.velocity.x;
|
|
25
|
+
}
|
|
26
|
+
if (abs(this.pos.y) > cameraSize.y/2)
|
|
27
|
+
{
|
|
28
|
+
debugCircle(this.pos, 3, GREEN, 1);
|
|
29
|
+
this.velocity.y = -this.velocity.y;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function gameInit()
|
|
35
|
+
{
|
|
36
|
+
canvasClearColor = GRAY;
|
|
37
|
+
new BounceObject(vec2(), vec2(5), tile(3,128));
|
|
38
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
let playerPos = vec2(), playerAngle = 0;
|
|
2
|
+
setTileFixBleedScale(0);
|
|
3
|
+
|
|
4
|
+
// a simple function to create the level
|
|
5
|
+
const levelTest = (p)=> (floor(p.x)**3&floor(p.y)**2)%30>5;
|
|
6
|
+
|
|
7
|
+
function gameUpdate()
|
|
8
|
+
{
|
|
9
|
+
// update camera angle with mouse pointer lock
|
|
10
|
+
if (mouseWasPressed(0))
|
|
11
|
+
pointerLockRequest();
|
|
12
|
+
if (keyWasPressed('Escape'))
|
|
13
|
+
pointerLockExit()
|
|
14
|
+
if (pointerLockIsActive() || isTouchDevice)
|
|
15
|
+
playerAngle += mouseDelta.x * .003;
|
|
16
|
+
|
|
17
|
+
// update player movement, prevent walking through walls
|
|
18
|
+
const velocity = keyDirection().rotate(playerAngle).scale(.05);
|
|
19
|
+
const normal = vec2();
|
|
20
|
+
let newPos = playerPos.add(velocity);
|
|
21
|
+
if (lineTest(playerPos, newPos, levelTest, normal))
|
|
22
|
+
{
|
|
23
|
+
// adjust velocity to slide along wall
|
|
24
|
+
const d = velocity.dot(normal);
|
|
25
|
+
newPos = newPos.subtract(vec2(d*normal.x, d*normal.y));
|
|
26
|
+
if (!levelTest(newPos))
|
|
27
|
+
playerPos = newPos;
|
|
28
|
+
}
|
|
29
|
+
else
|
|
30
|
+
playerPos = newPos;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function gameRender()
|
|
34
|
+
{
|
|
35
|
+
{
|
|
36
|
+
// draw horizontal slizes to create floor and ceiling
|
|
37
|
+
const h = 9;
|
|
38
|
+
let pos = vec2(), size = vec2(39, .15), color = rgb();
|
|
39
|
+
for (let y=-h; y<h; y+=.1)
|
|
40
|
+
{
|
|
41
|
+
const p = 1.01 - abs(y/h)
|
|
42
|
+
color.setHSLA(.1, y>0?0:.5, .7-p*.7);
|
|
43
|
+
pos.y = y;
|
|
44
|
+
drawRect(pos, size, color);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
{
|
|
48
|
+
// draw vertical slices to create the walls
|
|
49
|
+
// create objects in advance for optimal performance
|
|
50
|
+
const w = 15;
|
|
51
|
+
const maxDistance = 50;
|
|
52
|
+
const pos = vec2(), endPos = vec2(), size = vec2(.15);
|
|
53
|
+
const tileInfo = new TileInfo(vec2(), vec2(0,16));
|
|
54
|
+
const normal = vec2(), light = vec2().setAngle(2);
|
|
55
|
+
const color = rgb();
|
|
56
|
+
for (pos.x=-w; pos.x<w; pos.x+=.1)
|
|
57
|
+
{
|
|
58
|
+
// cast ray for this slice
|
|
59
|
+
const angle = playerAngle + pos.x/w/2;
|
|
60
|
+
endPos.setAngle(angle, maxDistance);
|
|
61
|
+
endPos.x += playerPos.x;
|
|
62
|
+
endPos.y += playerPos.y;
|
|
63
|
+
const p = lineTest(playerPos, endPos, levelTest, normal);
|
|
64
|
+
if (!p) continue;
|
|
65
|
+
|
|
66
|
+
// get texture coordinate
|
|
67
|
+
const t = mod(p.x+p.y, 1);
|
|
68
|
+
tileInfo.pos.x = 161 + 14*t;
|
|
69
|
+
|
|
70
|
+
// apply fog and lighting
|
|
71
|
+
const d = p.distance(playerPos)/maxDistance;
|
|
72
|
+
const l = max(0, normal.dot(light));
|
|
73
|
+
size.y = .5/d;
|
|
74
|
+
color.setHSLA(.6, 1-d, .7-d+l*.3);
|
|
75
|
+
|
|
76
|
+
// draw the section the wall
|
|
77
|
+
drawTile(pos, size, tileInfo, color);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// draw instructions and pointer lock status
|
|
82
|
+
const instructions = pointerLockIsActive() ?
|
|
83
|
+
'Mouse Control Active - ESC To Exit' :
|
|
84
|
+
'Click To Enable Mouse Control';
|
|
85
|
+
const textPos = vec2(mainCanvasSize.x/2, 50);
|
|
86
|
+
const textSize = 30;
|
|
87
|
+
const textColor = pointerLockIsActive() ? GREEN : WHITE;
|
|
88
|
+
if (!isTouchDevice)
|
|
89
|
+
drawTextScreen(instructions, textPos, textSize, textColor);
|
|
90
|
+
}
|
|
@@ -14,7 +14,7 @@ class Player extends EngineObject
|
|
|
14
14
|
// space ship controls
|
|
15
15
|
const moveInput = keyDirection();
|
|
16
16
|
this.applyAngularAcceleration(moveInput.x * .002);
|
|
17
|
-
const accel =
|
|
17
|
+
const accel = this.getRight(moveInput.y*.002);
|
|
18
18
|
this.applyAcceleration(accel);
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -34,7 +34,7 @@ class UISequencerButton extends UIButton
|
|
|
34
34
|
this.hue = track*.15;
|
|
35
35
|
if (track >= pianoStart)
|
|
36
36
|
{
|
|
37
|
-
const octave =
|
|
37
|
+
const octave = floor((track-pianoStart) / scale.length);
|
|
38
38
|
const scaleNote = (track-pianoStart) % scale.length;
|
|
39
39
|
this.semitone = scale[scaleNote] + 12*octave;
|
|
40
40
|
this.sound = sound_piano;
|
|
@@ -93,7 +93,7 @@ function gameInit()
|
|
|
93
93
|
tempoSlider.onChange = ()=>
|
|
94
94
|
{
|
|
95
95
|
tempo = lerp(minTempo, maxTempo, tempoSlider.value);
|
|
96
|
-
tempo =
|
|
96
|
+
tempo = floor(tempo/10) * 10; // round to nearest 10th
|
|
97
97
|
tempoSlider.text = `${tempo} BPM`;
|
|
98
98
|
};
|
|
99
99
|
tempoSlider.onChange();
|
|
@@ -108,7 +108,7 @@ function gameUpdate()
|
|
|
108
108
|
const lastStepTime = stepTime;
|
|
109
109
|
const lastStep = currentStep;
|
|
110
110
|
stepTime += timeDelta*tempo/60;
|
|
111
|
-
currentStep =
|
|
111
|
+
currentStep = floor(stepTime) % stepCount;
|
|
112
112
|
if (currentStep == lastStep && lastStepTime)
|
|
113
113
|
return;
|
|
114
114
|
|
|
@@ -23,7 +23,7 @@ class Player extends EngineObject
|
|
|
23
23
|
// shoot bullet
|
|
24
24
|
const pos = this.pos.add(vec2(0,1).rotate(cameraAngle));
|
|
25
25
|
const bullet = new EngineObject(pos, vec2(.2,.5), 0, this.angle);
|
|
26
|
-
bullet.velocity =
|
|
26
|
+
bullet.velocity = this.getUp(.5);
|
|
27
27
|
bullet.velocity = bullet.velocity.add(this.velocity);
|
|
28
28
|
this.shootTimer.set(.1);
|
|
29
29
|
}
|
|
@@ -18,12 +18,12 @@ function gameInit()
|
|
|
18
18
|
function gameRender()
|
|
19
19
|
{
|
|
20
20
|
// draw a sprite from the atlas
|
|
21
|
-
let pos = vec2(
|
|
22
|
-
let angle = 0;
|
|
23
|
-
let size = vec2(9);
|
|
24
|
-
let mirror = 0;
|
|
25
|
-
let color = hsl(0,0,1);
|
|
26
|
-
let additive = hsl(0,0,0,0);
|
|
21
|
+
let pos = vec2(sin(time)*5,-3);// world position
|
|
22
|
+
let angle = 0; // world space angle
|
|
23
|
+
let size = vec2(9); // world space size
|
|
24
|
+
let mirror = 0; // should tile be mirrored?
|
|
25
|
+
let color = hsl(0,0,1); // color to multiply by
|
|
26
|
+
let additive = hsl(0,0,0,0); // color to add to
|
|
27
27
|
drawTile(pos, size, spriteAtlas.iconBig, color, angle, mirror, additive);
|
|
28
28
|
|
|
29
29
|
// draw more sprites from the atlas
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function gameInit()
|
|
2
|
+
{
|
|
3
|
+
// create tile layer
|
|
4
|
+
const pos = vec2();
|
|
5
|
+
const tileLayer = new TileCollisionLayer(pos, vec2(28,16), 0);
|
|
6
|
+
cameraPos = tileLayer.size.scale(.5); // setup camera
|
|
7
|
+
for (pos.x = tileLayer.size.x; pos.x--;)
|
|
8
|
+
for (pos.y = tileLayer.size.y; pos.y--;)
|
|
9
|
+
{
|
|
10
|
+
// create random solid tiles away from level center
|
|
11
|
+
if (rand() < .7 || cameraPos.distanceSquared(pos) < 9)
|
|
12
|
+
continue;
|
|
13
|
+
|
|
14
|
+
// set tile data
|
|
15
|
+
const data = new TileLayerData(1);
|
|
16
|
+
tileLayer.setData(pos, data);
|
|
17
|
+
tileLayer.setCollisionData(pos);
|
|
18
|
+
}
|
|
19
|
+
tileLayer.redraw();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function gameRenderPost()
|
|
23
|
+
{
|
|
24
|
+
// cast ray from camera center to mouse
|
|
25
|
+
drawLine(cameraPos, mousePos, .1, CYAN);
|
|
26
|
+
const normal = vec2();
|
|
27
|
+
const hit = tileCollisionRaycast(cameraPos, mousePos, 0, normal);
|
|
28
|
+
if (hit)
|
|
29
|
+
{
|
|
30
|
+
// draw hit tile
|
|
31
|
+
const tilePos = hit.floor().add(vec2(.5));
|
|
32
|
+
drawRect(tilePos, vec2(1), RED);
|
|
33
|
+
|
|
34
|
+
// draw hit point and normal
|
|
35
|
+
drawRect(hit, vec2(.2), GREEN);
|
|
36
|
+
drawLine(cameraPos, hit, .1, RED);
|
|
37
|
+
drawLine(hit, hit.add(normal), .1, YELLOW);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
Binary file
|
|
@@ -10,7 +10,7 @@ class GameObject extends EngineObject
|
|
|
10
10
|
{
|
|
11
11
|
// adjust draw postion to be at the bottom of the object
|
|
12
12
|
const drawSize = this.drawSize || this.size;
|
|
13
|
-
const offset =
|
|
13
|
+
const offset = this.getUp(drawSize.y/2);
|
|
14
14
|
const pos = this.pos.add(offset);
|
|
15
15
|
drawTile(pos, drawSize, this.tileInfo, this.color, this.angle);
|
|
16
16
|
}
|