littlejsengine 1.12.6 → 1.13.1
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 +387 -177
- package/dist/littlejs.esm.js +5934 -5294
- package/dist/littlejs.esm.min.js +4 -1
- package/dist/littlejs.js +5887 -5263
- package/dist/littlejs.min.js +4 -1
- package/dist/littlejs.release.js +5426 -4829
- package/examples/box2d/game.js +1 -1
- package/examples/box2d/gameObjects.js +7 -6
- package/examples/box2d/index.html +1 -1
- package/examples/box2d/scenes.js +7 -7
- package/examples/breakout/game.js +1 -1
- package/examples/breakout/gameObjects.js +2 -2
- package/examples/breakout/index.html +1 -1
- package/examples/breakoutTutorial/README.md +2 -2
- package/examples/breakoutTutorial/game.js +1 -1
- package/examples/breakoutTutorial/index.html +1 -1
- package/examples/empty/index.html +1 -1
- package/examples/htmlMenu/index.html +1 -1
- package/examples/index.html +396 -153
- package/examples/module/game.js +1 -1
- package/examples/module/index.html +1 -1
- package/examples/platformer/game.js +4 -4
- package/examples/platformer/gameCharacter.js +6 -6
- package/examples/platformer/gameEffects.js +74 -57
- package/examples/platformer/gameLevel.js +61 -70
- package/examples/platformer/gameObjects.js +4 -4
- package/examples/platformer/index.html +1 -1
- package/examples/puzzle/index.html +1 -1
- package/examples/shorts/base.html +23 -3
- package/examples/shorts/box2dCar.js +8 -12
- package/examples/shorts/flappyGame.js +52 -0
- package/examples/shorts/helloWorld.js +6 -3
- package/examples/shorts/hillGlideGame.js +56 -0
- package/examples/shorts/landerGame.js +32 -0
- package/examples/shorts/maze.js +47 -0
- package/examples/shorts/medals.js +42 -0
- package/examples/shorts/nineSlice.js +21 -0
- package/examples/shorts/piano.js +52 -0
- package/examples/shorts/platformer.js +24 -20
- package/examples/shorts/{pong.js → pongGame.js} +1 -1
- package/examples/shorts/raycasting.js +71 -0
- package/examples/shorts/slidingPuzzle.js +42 -0
- package/examples/shorts/spaceGame.js +56 -0
- package/examples/shorts/starfield.js +17 -0
- package/examples/shorts/tileLayer.js +3 -5
- package/examples/shorts/tiles.png +0 -0
- package/examples/shorts/tiltedView.js +8 -7
- package/examples/shorts/topDown.js +18 -26
- package/examples/shorts/uiSystem.js +4 -7
- package/examples/starter/build.bat +6 -1
- package/examples/starter/game.js +2 -2
- package/examples/starter/index.html +23 -13
- package/examples/stress/index.html +2 -3
- package/examples/style.css +136 -0
- package/examples/typescript/build.js +1 -2
- package/examples/typescript/game.js +2 -2
- package/examples/typescript/game.ts +1 -1
- package/examples/typescript/index.html +1 -1
- package/examples/uiSystem/game.js +8 -24
- package/examples/uiSystem/index.html +1 -1
- package/package.json +1 -1
- package/plugins/box2d.js +8 -8
- package/plugins/drawUtilities.js +126 -0
- package/plugins/newgrounds.js +1 -1
- package/plugins/pluginExport.js +7 -1
- package/plugins/postProcess.js +2 -2
- package/plugins/uiSystem.js +153 -65
- package/plugins/zzfxm.js +1 -1
- package/reference.md +10 -10
- package/src/engine.js +50 -29
- package/src/engineAudio.js +14 -5
- package/src/engineBuild.bat +6 -1
- package/src/engineBuild.js +20 -5
- package/src/engineDebug.js +53 -26
- package/src/engineDraw.js +108 -57
- package/src/engineExport.js +21 -9
- package/src/engineInput.js +109 -37
- package/src/engineObject.js +68 -67
- package/src/engineParticles.js +26 -9
- package/src/engineSettings.js +15 -16
- package/src/engineTileLayer.js +312 -153
- package/src/engineUtilities.js +182 -130
- package/src/engineWebGL.js +47 -36
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
function gameRender()
|
|
2
2
|
{
|
|
3
|
-
// draw
|
|
4
|
-
|
|
3
|
+
// draw background rect
|
|
4
|
+
drawRect(cameraPos, vec2(30), hsl(0,0,.2));
|
|
5
|
+
|
|
6
|
+
// draw text to the overlay canvas
|
|
7
|
+
drawTextOverlay('Hello World', vec2(0,3), 3);
|
|
5
8
|
|
|
6
9
|
// draw a tile
|
|
7
|
-
drawTile(vec2(
|
|
10
|
+
drawTile(vec2(Math.sin(time)*3,-2), vec2(7), tile(3,128));
|
|
8
11
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
class Player extends EngineObject
|
|
2
|
+
{
|
|
3
|
+
constructor(pos)
|
|
4
|
+
{
|
|
5
|
+
super(pos, vec2(2), tile(9), 0, CYAN);
|
|
6
|
+
this.damping = 1; // disable damping
|
|
7
|
+
this.clampSpeed = false; // disable speed clamping
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
update()
|
|
11
|
+
{
|
|
12
|
+
super.update();
|
|
13
|
+
|
|
14
|
+
const h = getGroundHeight(this.pos.x);
|
|
15
|
+
if (this.pos.y < h + this.size.y/2)
|
|
16
|
+
{
|
|
17
|
+
// clamp to ground and reflect velocity
|
|
18
|
+
this.pos.y = h + this.size.y/2;
|
|
19
|
+
const n = vec2((h-getGroundHeight(this.pos.x+.1))/.1, 1).normalize();
|
|
20
|
+
this.velocity = this.velocity.reflect(n,0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// apply movement controls
|
|
24
|
+
if (mouseIsDown(0) || keyIsDown('Space'))
|
|
25
|
+
this.applyAcceleration(vec2(0,-.05));
|
|
26
|
+
this.velocity.x = max(this.velocity.x,.4);
|
|
27
|
+
this.angle = this.velocity.angle() - PI/2;
|
|
28
|
+
|
|
29
|
+
// move camera with player
|
|
30
|
+
cameraPos = vec2(this.pos.x+9,5);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getGroundHeight(x)
|
|
35
|
+
{
|
|
36
|
+
return Math.sin(x/4)*2 + Math.sin(x/17);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function gameInit()
|
|
40
|
+
{
|
|
41
|
+
gravity.y = -.01;
|
|
42
|
+
new Player(vec2(0,5));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function gameRender()
|
|
46
|
+
{
|
|
47
|
+
const h = 100, w = 20;
|
|
48
|
+
const pos = vec2(), size = vec2(.2,h), color = WHITE;
|
|
49
|
+
for (let x=cameraPos.x-w; x<cameraPos.x+w; x+=.1)
|
|
50
|
+
{
|
|
51
|
+
pos.x = x;
|
|
52
|
+
pos.y = getGroundHeight(x)-h/2;
|
|
53
|
+
color.setHSLA(.2+.2*wave(.2,1,x), .5, .5);
|
|
54
|
+
drawRect(pos, size, color);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class Player extends EngineObject
|
|
2
|
+
{
|
|
3
|
+
constructor(pos)
|
|
4
|
+
{
|
|
5
|
+
super(pos, vec2(1,2), tile(8), 0, RED);
|
|
6
|
+
this.setCollision(); // make object collide
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
update()
|
|
10
|
+
{
|
|
11
|
+
super.update();
|
|
12
|
+
|
|
13
|
+
// apply movement controls
|
|
14
|
+
this.applyAcceleration(keyDirection().scale(.002));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function gameInit()
|
|
19
|
+
{
|
|
20
|
+
// setup level
|
|
21
|
+
gravity.y = -.001;
|
|
22
|
+
new Player(vec2(0,4));
|
|
23
|
+
|
|
24
|
+
// create ground
|
|
25
|
+
for (let i=0, y=0; i<20; ++i)
|
|
26
|
+
{
|
|
27
|
+
y = (y + rand(1,-1)*4) * .5;
|
|
28
|
+
const o = new EngineObject(vec2(i*2-20, y-54), vec2(2, 99), 0, 0, hsl(0,0,.5+i%.29));
|
|
29
|
+
o.setCollision(); // make object collide
|
|
30
|
+
o.mass = 0; // make object have static physics
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
function generateMaze(size)
|
|
2
|
+
{
|
|
3
|
+
const maze = [], w = size.x, h = size.y;
|
|
4
|
+
maze[1 + w] = 1; // start point
|
|
5
|
+
for(let k=w*h*9|0; k--;)
|
|
6
|
+
{
|
|
7
|
+
// get a random position on odd coordinates
|
|
8
|
+
const jx = randInt(w/2-(w%2?0:2)|0)*2 + 1;
|
|
9
|
+
const jy = randInt(h/2-(h%2?1:2)|0)*2 + 1;
|
|
10
|
+
const j = jx + jy*w;
|
|
11
|
+
|
|
12
|
+
// get a random direction
|
|
13
|
+
const d = randSign() * (randBool() ? 1 : w);
|
|
14
|
+
|
|
15
|
+
// check if we are not the same line or column
|
|
16
|
+
if (j%w != (j+d*2)%w && (j/w|0) != ((j+d*2)/w|0))
|
|
17
|
+
continue;
|
|
18
|
+
|
|
19
|
+
// check if pos is open and the next 2 cells are closed
|
|
20
|
+
if (maze[j] && !maze[j+d] && !maze[j+d*2])
|
|
21
|
+
maze[j+d] = maze[j+d*2] = 1;
|
|
22
|
+
}
|
|
23
|
+
return maze;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function gameInit()
|
|
27
|
+
{
|
|
28
|
+
// generate maze data
|
|
29
|
+
const mazeSize = vec2(27,15);
|
|
30
|
+
const maze = generateMaze(mazeSize);
|
|
31
|
+
|
|
32
|
+
// create tile layer
|
|
33
|
+
const pos = vec2();
|
|
34
|
+
const tileLayer = new TileCollisionLayer(pos, mazeSize);
|
|
35
|
+
for (pos.x = tileLayer.size.x; pos.x--;)
|
|
36
|
+
for (pos.y = tileLayer.size.y; pos.y--;)
|
|
37
|
+
{
|
|
38
|
+
// check if tile should be solid
|
|
39
|
+
if (maze[pos.x + pos.y*mazeSize.x])
|
|
40
|
+
continue;
|
|
41
|
+
|
|
42
|
+
// set tile data
|
|
43
|
+
tileLayer.setData(pos, new TileLayerData(1));
|
|
44
|
+
}
|
|
45
|
+
tileLayer.redraw(); // redraw tile layer with new data
|
|
46
|
+
cameraPos = mazeSize.scale(.5); // center camera
|
|
47
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// create example medals
|
|
2
|
+
const medal_openedExample = new Medal(0, 'Opened Example', 'You opened this example!');
|
|
3
|
+
const medal_leftClick = new Medal(1, 'Left Clicked', 'You left clicked!', '🐁');
|
|
4
|
+
const medal_rightClick = new Medal(2, 'Right Clicked', 'You right clicked!', '🐭');
|
|
5
|
+
const medal_spacePressed = new Medal(3, 'Pressed Spacebar', 'You pressed spacebar!', '🚀');
|
|
6
|
+
|
|
7
|
+
// setup medals
|
|
8
|
+
const saveName = 'Medals Example';
|
|
9
|
+
medalsInit(saveName);
|
|
10
|
+
|
|
11
|
+
// clear medals for testing
|
|
12
|
+
medalsForEach(medal=> medal.unlocked = false);
|
|
13
|
+
medal_openedExample.unlock();
|
|
14
|
+
|
|
15
|
+
function gameUpdate()
|
|
16
|
+
{
|
|
17
|
+
if (mouseWasPressed(0))
|
|
18
|
+
medal_leftClick.unlock();
|
|
19
|
+
if (mouseWasPressed(2))
|
|
20
|
+
medal_rightClick.unlock();
|
|
21
|
+
if (keyWasPressed('Space'))
|
|
22
|
+
medal_spacePressed.unlock();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function gameRender()
|
|
26
|
+
{
|
|
27
|
+
const size = 80;
|
|
28
|
+
let pos = mainCanvasSize.scale(.5).subtract(vec2(0,40));
|
|
29
|
+
drawTextScreen('Unlocked Medals', pos, size);
|
|
30
|
+
|
|
31
|
+
// show unlocked medals
|
|
32
|
+
let medalsCount = 0;
|
|
33
|
+
medalsForEach(medal=> medal.unlocked && medalsCount++);
|
|
34
|
+
pos = pos.add(vec2((1-medalsCount)*size/2, 100));
|
|
35
|
+
medalsForEach(medal=>
|
|
36
|
+
{
|
|
37
|
+
if (!medal.unlocked)
|
|
38
|
+
return;
|
|
39
|
+
medal.renderIcon(pos, size);
|
|
40
|
+
pos.x += size + 8;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function gameRender()
|
|
2
|
+
{
|
|
3
|
+
const nineSliceTile = tile(16);
|
|
4
|
+
const threeSliceTile = tile(19);
|
|
5
|
+
|
|
6
|
+
// draw nine slice with thin border and color
|
|
7
|
+
drawNineSlice(vec2(-7,4), vec2(13, 6), nineSliceTile, hsl(.1,.5,.9), .5);
|
|
8
|
+
drawTextOverlay('Nine Slice\nThin Border', vec2(-7,4), 1, BLACK);
|
|
9
|
+
|
|
10
|
+
// draw nine slice in screen space with thick border
|
|
11
|
+
drawNineSliceScreen(vec2(700,150), vec2(250), nineSliceTile);
|
|
12
|
+
drawTextScreen('Nine Slice\nScreen Space', vec2(700,150), 30, BLACK);
|
|
13
|
+
|
|
14
|
+
// draw three slice with thick border and additive color
|
|
15
|
+
drawThreeSlice(vec2(-7,-4), vec2(9, 7), threeSliceTile, WHITE, 2, hsl(.6,1,.5));
|
|
16
|
+
drawTextOverlay('Three Slice\nThick Border', vec2(-7,-4), 1, BLACK);
|
|
17
|
+
|
|
18
|
+
// draw three slice in screen space with thick border
|
|
19
|
+
drawThreeSliceScreen(vec2(700,400), vec2(400,150), threeSliceTile);
|
|
20
|
+
drawTextScreen('Three Slice\nScreen Space', vec2(700,400), 30, BLACK);
|
|
21
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const pianoSound = new Sound([,0,220,,9]), keys = [];
|
|
2
|
+
|
|
3
|
+
class PianoKey extends EngineObject
|
|
4
|
+
{
|
|
5
|
+
constructor(pos, size, semitone, isWhite)
|
|
6
|
+
{
|
|
7
|
+
const keySize = 2;
|
|
8
|
+
size = size.scale(keySize);
|
|
9
|
+
pos = pos.scale(keySize).add(vec2(0,4-size.y/2));
|
|
10
|
+
super(pos, size, 0, 0, hsl(0,0,isWhite ? 1 : .3));
|
|
11
|
+
this.drawSize = size.subtract(vec2(.1,0));
|
|
12
|
+
this.semitone = semitone;
|
|
13
|
+
}
|
|
14
|
+
press()
|
|
15
|
+
{
|
|
16
|
+
if (!this.isDown)
|
|
17
|
+
pianoSound.playNote(this.semitone);
|
|
18
|
+
this.isDown = true;
|
|
19
|
+
}
|
|
20
|
+
release()
|
|
21
|
+
{
|
|
22
|
+
if (this.isDown)
|
|
23
|
+
pianoSound.stop(.2);
|
|
24
|
+
this.isDown = false;
|
|
25
|
+
}
|
|
26
|
+
render()
|
|
27
|
+
{
|
|
28
|
+
const color = this.isDown ? RED : this.color;
|
|
29
|
+
drawRect(this.pos, this.drawSize, color);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function gameInit()
|
|
34
|
+
{
|
|
35
|
+
// create piano keyboard
|
|
36
|
+
for(let i=15; i--;)
|
|
37
|
+
keys.unshift(new PianoKey(vec2(i-7,0), vec2(1,4), [0,2,4,5,7,9,11][i%7]+(i/7|0)*12, 1));
|
|
38
|
+
for(let i=10; i--;)
|
|
39
|
+
keys.unshift(new PianoKey(vec2([1,2,4,5,6][i%5]+(i/5|0)*7-7.5,0), vec2(1,2), [1,3,6,8,10][i%5]+(i/5|0)*12));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function gameUpdate()
|
|
43
|
+
{
|
|
44
|
+
// update state of piano keys
|
|
45
|
+
const pressedKey = keys.find(k=>k.isDown);
|
|
46
|
+
const newPressedKey = mouseIsDown(0) && keys.find(k=>isOverlapping(k.pos, k.size, mousePos));
|
|
47
|
+
if (newPressedKey != pressedKey)
|
|
48
|
+
{
|
|
49
|
+
pressedKey && pressedKey.release();
|
|
50
|
+
newPressedKey && newPressedKey.press();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,31 +1,23 @@
|
|
|
1
|
-
class
|
|
2
|
-
{
|
|
3
|
-
constructor(pos, size, color)
|
|
4
|
-
{
|
|
5
|
-
super(pos, size, 0, 0, color);
|
|
6
|
-
this.setCollision(); // make object collide
|
|
7
|
-
this.mass = 0; // make object have static physics
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
class Player extends PhysicsObject
|
|
1
|
+
class Player extends EngineObject
|
|
12
2
|
{
|
|
13
3
|
constructor(pos)
|
|
14
4
|
{
|
|
15
|
-
super(pos, vec2(2,4), RED);
|
|
16
|
-
this.
|
|
5
|
+
super(pos, vec2(2,4), 0, 0, RED);
|
|
6
|
+
this.setCollision(); // make object collide
|
|
17
7
|
}
|
|
18
8
|
|
|
19
9
|
update()
|
|
20
10
|
{
|
|
11
|
+
super.update();
|
|
12
|
+
|
|
21
13
|
// apply movement controls
|
|
22
14
|
const moveInput = keyDirection();
|
|
23
15
|
this.velocity.x += moveInput.x * (this.groundObject ? .1: .01);
|
|
24
16
|
if (this.groundObject && moveInput.y > 0)
|
|
25
17
|
this.velocity.y = .9; // jump
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
cameraPos = vec2(this.pos.x, 9);
|
|
19
|
+
// move camera with player
|
|
20
|
+
cameraPos = vec2(this.pos.x, 9);
|
|
29
21
|
}
|
|
30
22
|
}
|
|
31
23
|
|
|
@@ -33,10 +25,22 @@ function gameInit()
|
|
|
33
25
|
{
|
|
34
26
|
// setup level
|
|
35
27
|
gravity.y = -.05;
|
|
36
|
-
new Player(vec2(
|
|
28
|
+
new Player(vec2(5,6));
|
|
37
29
|
|
|
38
|
-
// create
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
// create tile layer
|
|
31
|
+
const pos = vec2();
|
|
32
|
+
const tileLayer = new TileCollisionLayer(pos, vec2(256));
|
|
33
|
+
for (pos.x = tileLayer.size.x; pos.x--;)
|
|
34
|
+
for (pos.y = tileLayer.size.y; pos.y--;)
|
|
35
|
+
{
|
|
36
|
+
// check if tile should be solid
|
|
37
|
+
const levelHeight = pos.x<9 ? 2 : (pos.x/4|0)**3.1%7;
|
|
38
|
+
if (pos.y > levelHeight)
|
|
39
|
+
continue;
|
|
40
|
+
|
|
41
|
+
// set tile data
|
|
42
|
+
tileLayer.setData(pos, new TileLayerData(1));
|
|
43
|
+
tileLayer.setCollisionData(pos);
|
|
44
|
+
}
|
|
45
|
+
tileLayer.redraw(); // redraw tile layer with new data
|
|
42
46
|
}
|
|
@@ -32,7 +32,7 @@ function gameUpdate()
|
|
|
32
32
|
ball && ball.destroy(); // destroy old ball
|
|
33
33
|
ball = new PhysicsObject(cameraPos); // create a ball
|
|
34
34
|
ball.velocity = vec2(.2); // give ball some movement
|
|
35
|
-
ball.
|
|
35
|
+
ball.restitution = 1; // make ball bounce
|
|
36
36
|
ball.mass = 1; // make ball have dynamic physics
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
let playerPos = vec2(), playerAngle = 0;
|
|
2
|
+
|
|
3
|
+
// a simple function to generate a level
|
|
4
|
+
const levelTest = (X,Y)=> ((X|0)**3&(Y|0)**2)%30>5;
|
|
5
|
+
|
|
6
|
+
// cast a ray and return the distance to the first wall hit (0-1)
|
|
7
|
+
function raycast(pos, angle)
|
|
8
|
+
{
|
|
9
|
+
const maxDistance = 40, delta = .05;
|
|
10
|
+
const rayX = delta*Math.sin(angle);
|
|
11
|
+
const rayY = delta*Math.cos(angle);
|
|
12
|
+
let posX = pos.x, posY = pos.y;
|
|
13
|
+
for (let distance = 0; distance < maxDistance; distance += delta)
|
|
14
|
+
{
|
|
15
|
+
if (levelTest(posX, posY))
|
|
16
|
+
return distance/maxDistance;
|
|
17
|
+
posX += rayX;
|
|
18
|
+
posY += rayY;
|
|
19
|
+
}
|
|
20
|
+
return 1;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function gameUpdate()
|
|
24
|
+
{
|
|
25
|
+
// update camera angle with mouse pointer lock
|
|
26
|
+
if (mouseWasPressed(0))
|
|
27
|
+
pointerLockRequest();
|
|
28
|
+
if (keyWasPressed('Escape'))
|
|
29
|
+
pointerLockExit()
|
|
30
|
+
if (pointerLockIsActive() || isTouchDevice)
|
|
31
|
+
playerAngle += mouseDelta.x * .003;
|
|
32
|
+
|
|
33
|
+
// update player movement, prevent walking through walls
|
|
34
|
+
const velocity = keyDirection().scale(.1).rotate(playerAngle);
|
|
35
|
+
const newPos = playerPos.add(velocity);
|
|
36
|
+
if (!levelTest(newPos.x, newPos.y))
|
|
37
|
+
playerPos = newPos;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function gameRender()
|
|
41
|
+
{
|
|
42
|
+
{
|
|
43
|
+
// draw horizontal slizes to create floor and ceiling
|
|
44
|
+
const h = 9;
|
|
45
|
+
let pos = vec2(), size = vec2(39, .11), color = WHITE;
|
|
46
|
+
for (let y=-h; y<h; y+=.1)
|
|
47
|
+
{
|
|
48
|
+
const p = 1.01-abs(y/h)
|
|
49
|
+
pos.y = y;
|
|
50
|
+
color.setHSLA(.1, y>0?0:.5, .7-p*.7);
|
|
51
|
+
drawRect(pos, size, color);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
{
|
|
55
|
+
// draw vertical slices to create the walls
|
|
56
|
+
const w = 20;
|
|
57
|
+
const pos = vec2(), size = vec2(.11), color = WHITE;
|
|
58
|
+
for (let x=-w; x<w; x+=.1)
|
|
59
|
+
{
|
|
60
|
+
const p = raycast(playerPos, playerAngle + x/w);
|
|
61
|
+
pos.x = x;
|
|
62
|
+
size.y = .4/p;
|
|
63
|
+
color.setHSLA(.6, .5, .7-p*.7);
|
|
64
|
+
drawRect(pos, size, color);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// draw instructions and pointer lock status
|
|
68
|
+
const instructions = pointerLockIsActive() ? 'Mouse Control Active - ESC To Exit' : 'Click To Enable Mouse Control';
|
|
69
|
+
if (!isTouchDevice)
|
|
70
|
+
drawTextScreen(instructions, vec2(mainCanvasSize.x/2, 50), 24, pointerLockIsActive() ? GREEN : WHITE);
|
|
71
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const gridSize = vec2(4,3);
|
|
2
|
+
const pieceSize = vec2(5,4);
|
|
3
|
+
let emptyGridPos = vec2();
|
|
4
|
+
|
|
5
|
+
class PuzzlePiece extends EngineObject
|
|
6
|
+
{
|
|
7
|
+
constructor(gridPos, size)
|
|
8
|
+
{
|
|
9
|
+
const color = rgb(gridPos.x/(gridSize.x-1), gridPos.y/(gridSize.y-1), 1);
|
|
10
|
+
super(gridPos.multiply(size), size, 0, 0, color);
|
|
11
|
+
this.gridPos = gridPos;
|
|
12
|
+
this.text = gridPos.x + gridPos.y*gridSize.x;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
update()
|
|
16
|
+
{
|
|
17
|
+
if (mouseWasPressed(0) && isOverlapping(this.pos, this.size, mousePos))
|
|
18
|
+
if (abs(this.gridPos.x-emptyGridPos.x) + abs(this.gridPos.y-emptyGridPos.y) == 1)
|
|
19
|
+
{
|
|
20
|
+
// swap with empty space when clicked on
|
|
21
|
+
this.pos = emptyGridPos.multiply(this.size);
|
|
22
|
+
[emptyGridPos, this.gridPos] = [this.gridPos, emptyGridPos];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
render()
|
|
27
|
+
{
|
|
28
|
+
super.render();
|
|
29
|
+
drawTextOverlay(this.text, this.pos, 2.5, BLACK);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function gameInit()
|
|
34
|
+
{
|
|
35
|
+
// create puzzle pieces
|
|
36
|
+
for(let x=gridSize.x; x--;)
|
|
37
|
+
for(let y=gridSize.y; y--;)
|
|
38
|
+
(x||y) && new PuzzlePiece(vec2(x,y), pieceSize);
|
|
39
|
+
|
|
40
|
+
// center camera on grid
|
|
41
|
+
cameraPos = gridSize.subtract(vec2(1)).multiply(pieceSize).scale(.5);
|
|
42
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
class Player extends EngineObject
|
|
2
|
+
{
|
|
3
|
+
constructor(pos)
|
|
4
|
+
{
|
|
5
|
+
super(pos, vec2(1,2), tile(8), 0, CYAN);
|
|
6
|
+
this.damping = .97;
|
|
7
|
+
this.angleDamping = .95;
|
|
8
|
+
this.shootTimer = new Timer;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
update()
|
|
12
|
+
{
|
|
13
|
+
super.update();
|
|
14
|
+
|
|
15
|
+
// space ship controls
|
|
16
|
+
const moveInput = keyDirection();
|
|
17
|
+
this.applyAngularAcceleration(moveInput.x * .005);
|
|
18
|
+
this.applyAcceleration(vec2().setAngle(this.angle, moveInput.y*.02));
|
|
19
|
+
if (!this.shootTimer.active() && (keyIsDown('Space') || mouseIsDown(0)))
|
|
20
|
+
{
|
|
21
|
+
// shoot bullet
|
|
22
|
+
const pos = this.pos.add(vec2(0,1).rotate(cameraAngle));
|
|
23
|
+
const bullet = new EngineObject(pos, vec2(.2,.5), 0, this.angle, YELLOW);
|
|
24
|
+
bullet.velocity = this.velocity.add(vec2(0,.5).rotate(this.angle));
|
|
25
|
+
this.shootTimer.set(.1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// move camera with player
|
|
29
|
+
cameraPos = this.pos;
|
|
30
|
+
cameraAngle = this.angle;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function gameInit()
|
|
35
|
+
{
|
|
36
|
+
new Player(vec2(0,4));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function gameRender()
|
|
40
|
+
{
|
|
41
|
+
// draw wrapped starfield with parallax
|
|
42
|
+
const range = 32, halfRange = range/2;
|
|
43
|
+
|
|
44
|
+
// precreate variables to avoid overhead
|
|
45
|
+
const pos = vec2(), size = vec2(), color = WHITE;
|
|
46
|
+
for (let i=1e3; i--;)
|
|
47
|
+
{
|
|
48
|
+
// use math to generate random star positions
|
|
49
|
+
const parallax = i%.13-1;
|
|
50
|
+
pos.x = mod(i**2.1 + cameraPos.x*parallax, range) + cameraPos.x - halfRange;
|
|
51
|
+
pos.y = mod(i**3.1 + cameraPos.y*parallax, range) + cameraPos.y - halfRange;
|
|
52
|
+
size.x = size.y = i%.07+.03;
|
|
53
|
+
color.a = .1+i%.9;
|
|
54
|
+
drawRect(pos, size, color);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function gameRender()
|
|
2
|
+
{
|
|
3
|
+
setBlendMode(1);
|
|
4
|
+
// precreate variables to avoid overhead
|
|
5
|
+
const pos = vec2(), size = vec2(), color = WHITE;
|
|
6
|
+
for(let i=2e3; i--;)
|
|
7
|
+
{
|
|
8
|
+
// use math to generate random star positions
|
|
9
|
+
const offset = time*(9+i**2.1%15) + i**2.3;
|
|
10
|
+
pos.x = offset%70-35;
|
|
11
|
+
pos.y = i/120-8;
|
|
12
|
+
size.x = size.y = i%.11+.07;
|
|
13
|
+
color.setHSLA(0, 0, Math.sin(i)**4);
|
|
14
|
+
drawRect(pos, size, color);
|
|
15
|
+
}
|
|
16
|
+
setBlendMode(0);
|
|
17
|
+
}
|
|
@@ -3,11 +3,9 @@ function gameInit()
|
|
|
3
3
|
cameraPos = vec2(16); // setup camera
|
|
4
4
|
gravity.y = -.01; // enable gravity
|
|
5
5
|
|
|
6
|
-
// create tile
|
|
6
|
+
// create tile layer
|
|
7
7
|
const pos = vec2();
|
|
8
8
|
const tileLayer = new TileCollisionLayer(pos, vec2(32));
|
|
9
|
-
|
|
10
|
-
// init the tile layer
|
|
11
9
|
for (pos.x = tileLayer.size.x; pos.x--;)
|
|
12
10
|
for (pos.y = tileLayer.size.y; pos.y--;)
|
|
13
11
|
{
|
|
@@ -18,7 +16,7 @@ function gameInit()
|
|
|
18
16
|
// set tile data
|
|
19
17
|
const tileIndex = 1;
|
|
20
18
|
const direction = randInt(4)
|
|
21
|
-
const mirror =
|
|
19
|
+
const mirror = randBool();
|
|
22
20
|
const color = randColor(WHITE, hsl(0,0,.2));
|
|
23
21
|
const data = new TileLayerData(tileIndex, direction, mirror, color);
|
|
24
22
|
tileLayer.setData(pos, data);
|
|
@@ -43,7 +41,7 @@ function gameUpdate()
|
|
|
43
41
|
.99, 1, 1, PI, // damping, angleDamping, gravityScale, cone
|
|
44
42
|
.05, .8, true, false // fadeRate, randomness, collide, additive
|
|
45
43
|
);
|
|
46
|
-
particleEmitter.
|
|
44
|
+
particleEmitter.restitution = .5; // bounce when it collides
|
|
47
45
|
particleEmitter.trailScale = 2; // stretch in direction of motion
|
|
48
46
|
}
|
|
49
47
|
}
|
|
Binary file
|
|
@@ -18,16 +18,17 @@ class Player extends GameObject
|
|
|
18
18
|
{
|
|
19
19
|
update()
|
|
20
20
|
{
|
|
21
|
+
super.update();
|
|
22
|
+
|
|
21
23
|
// apply movement controls
|
|
22
|
-
const moveInput = keyDirection().clampLength(1).scale(.2);
|
|
23
|
-
this.velocity = this.velocity.add(moveInput);
|
|
24
|
+
const moveInput = keyDirection().clampLength(1).scale(.2);
|
|
25
|
+
this.velocity = this.velocity.add(moveInput);
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
cameraPos = this.pos.add(vec2(0,2));
|
|
27
|
+
// move camera with player
|
|
28
|
+
cameraPos = this.pos.add(vec2(0,2));
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
|
|
31
32
|
function gameInit()
|
|
32
33
|
{
|
|
33
34
|
// setup level
|
|
@@ -35,10 +36,10 @@ function gameInit()
|
|
|
35
36
|
new Player(vec2(), vec2(3), tile(5), 0, RED);
|
|
36
37
|
|
|
37
38
|
// create background objects
|
|
38
|
-
for (let i
|
|
39
|
+
for (let i=1; i<300; ++i)
|
|
39
40
|
new EngineObject(randInCircle(90), vec2(rand(59),rand(59)), 0, 0, hsl(.4,.3,rand(.1,.2),.8), -1e5);
|
|
40
41
|
|
|
41
42
|
// create world objects
|
|
42
|
-
for (let i
|
|
43
|
+
for (let i=1; i<1e3; ++i)
|
|
43
44
|
new GameObject(randInCircle(7+i,7), vec2(rand(1,2),rand(4,9)), 0, 0, hsl(.1,.5,rand(.2,.3)));
|
|
44
45
|
}
|
|
@@ -1,30 +1,22 @@
|
|
|
1
|
-
class
|
|
2
|
-
{
|
|
3
|
-
constructor(pos, size, color)
|
|
4
|
-
{
|
|
5
|
-
super(pos, size, 0, 0, color);
|
|
6
|
-
this.setCollision(); // make object collide
|
|
7
|
-
this.mass = 0; // make object have static physics
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
class Player extends PhysicsObject
|
|
1
|
+
class Player extends EngineObject
|
|
12
2
|
{
|
|
13
3
|
constructor(pos)
|
|
14
4
|
{
|
|
15
|
-
super(pos, vec2(2), RED);
|
|
16
|
-
this.
|
|
17
|
-
this.renderOrder = 1; // render player on top
|
|
5
|
+
super(pos, vec2(2), tile(5), 0, RED);
|
|
6
|
+
this.setCollision(); // make object collide
|
|
7
|
+
this.renderOrder = 1; // render player on top
|
|
18
8
|
}
|
|
19
9
|
|
|
20
10
|
update()
|
|
21
11
|
{
|
|
12
|
+
super.update();
|
|
13
|
+
|
|
22
14
|
// apply movement controls
|
|
23
|
-
const moveInput = keyDirection().clampLength(1).scale(.2);
|
|
24
|
-
this.velocity = this.velocity.add(moveInput);
|
|
15
|
+
const moveInput = keyDirection().clampLength(1).scale(.2);
|
|
16
|
+
this.velocity = this.velocity.add(moveInput);
|
|
25
17
|
|
|
26
|
-
|
|
27
|
-
cameraPos = this.pos;
|
|
18
|
+
// move camera with player
|
|
19
|
+
cameraPos = this.pos;
|
|
28
20
|
}
|
|
29
21
|
}
|
|
30
22
|
|
|
@@ -32,13 +24,13 @@ function gameInit()
|
|
|
32
24
|
{
|
|
33
25
|
// setup level
|
|
34
26
|
objectDefaultDamping = .7;
|
|
35
|
-
new Player
|
|
36
|
-
|
|
37
|
-
// create background objects
|
|
38
|
-
for (let i = 1; i < 300; ++i)
|
|
39
|
-
new EngineObject(randInCircle(90), vec2(rand(59),rand(59)), 0, rand(), hsl(.4,.5,rand(.2)));
|
|
27
|
+
new Player;
|
|
40
28
|
|
|
41
|
-
// create
|
|
42
|
-
for (let i
|
|
43
|
-
|
|
29
|
+
// create collision objects
|
|
30
|
+
for (let i=300; i--;)
|
|
31
|
+
{
|
|
32
|
+
const o = new EngineObject(randInCircle(15+i,7), vec2(rand(4,9),rand(4,9)), 0, 0, hsl(0,0,rand(.8,1)));
|
|
33
|
+
o.setCollision(); // make object collide
|
|
34
|
+
o.mass = 0; // make object have static physics
|
|
35
|
+
}
|
|
44
36
|
}
|