littlejsengine 1.17.11 → 1.17.15
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/AI.md +162 -0
- package/README.md +50 -63
- package/dist/littlejs.d.ts +150 -68
- package/dist/littlejs.esm.js +323 -105
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +320 -104
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +318 -101
- package/examples/electron/{build.js → build.mjs} +26 -23
- package/examples/electron/game.js +5 -50
- package/examples/electron/index.html +2 -2
- package/examples/index.html +1 -0
- package/examples/module/{build.js → build.mjs} +22 -19
- package/examples/shorts/base.html +1 -1
- package/examples/shorts/hillGlideGame.js +1 -1
- package/examples/shorts/nineSlice.js +3 -3
- package/examples/shorts/shapes.js +1 -1
- package/examples/shorts/uiSystem.js +17 -16
- package/examples/starter/build.bat +1 -1
- package/examples/starter/{build.js → build.mjs} +25 -22
- package/examples/starter/index.html +2 -2
- package/examples/typescript/build.mjs +60 -0
- package/examples/typescript/game.js +2 -2
- package/examples/typescript/tsconfig.json +11 -2
- package/package.json +2 -2
- package/plugins/pluginExport.js +1 -0
- package/plugins/uiSystem.js +143 -20
- package/reference.md +0 -1
- package/src/engine.js +16 -14
- package/src/engineAudio.js +9 -6
- package/src/{engineBuild.js → engineBuild.mjs} +95 -78
- package/src/engineDebug.js +8 -5
- package/src/engineDraw.js +16 -14
- package/src/engineExport.js +2 -1
- package/src/engineInput.js +29 -8
- package/src/engineMath.js +46 -14
- package/src/engineMedals.js +6 -3
- package/src/engineObject.js +14 -3
- package/src/engineParticles.js +8 -3
- package/src/engineRelease.js +6 -2
- package/src/engineTileLayer.js +8 -4
- package/src/engineUtilities.js +6 -2
- package/src/engineWebGL.js +11 -8
- package/src/jsconfig.json +2 -1
- package/examples/electron/build.bat +0 -7
- package/examples/module/build.bat +0 -7
- package/examples/typescript/build.bat +0 -5
- package/examples/typescript/build.js +0 -31
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* LittleJS Build System
|
|
5
3
|
*/
|
|
6
4
|
|
|
7
5
|
'use strict';
|
|
8
6
|
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
|
|
9
14
|
const PROGRAM_TITLE = 'Little JS Electron Project';
|
|
10
15
|
const PROGRAM_NAME = 'game';
|
|
11
|
-
const BUILD_FOLDER = 'build';
|
|
16
|
+
const BUILD_FOLDER = join(__dirname, 'build');
|
|
12
17
|
const USE_ROADROLLER = false; // enable for extra compression
|
|
13
18
|
const sourceFiles =
|
|
14
19
|
[
|
|
15
|
-
'../../dist/littlejs.release.js',
|
|
16
|
-
'game.js',
|
|
20
|
+
join(__dirname, '../../dist/littlejs.release.js'),
|
|
21
|
+
join(__dirname, 'game.js'),
|
|
17
22
|
// add your game's files here
|
|
18
23
|
];
|
|
19
24
|
const dataFiles =
|
|
@@ -24,24 +29,22 @@ const dataFiles =
|
|
|
24
29
|
|
|
25
30
|
console.log(`Building ${PROGRAM_NAME}...`);
|
|
26
31
|
const startTime = Date.now();
|
|
27
|
-
const fs = require('node:fs');
|
|
28
|
-
const child_process = require('node:child_process');
|
|
29
32
|
|
|
30
33
|
// rebuild engine
|
|
31
|
-
//
|
|
34
|
+
//execSync(`npm run build`, { stdio: 'inherit' });
|
|
32
35
|
|
|
33
36
|
// remove old files and setup build folder
|
|
34
37
|
fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
|
|
35
|
-
fs.rmSync(`${PROGRAM_NAME}.zip
|
|
38
|
+
fs.rmSync(join(__dirname, `${PROGRAM_NAME}.zip`), { force: true });
|
|
36
39
|
fs.mkdirSync(BUILD_FOLDER);
|
|
37
40
|
|
|
38
41
|
// copy data files
|
|
39
42
|
for (const file of dataFiles)
|
|
40
|
-
fs.copyFileSync(file,
|
|
43
|
+
fs.copyFileSync(join(__dirname, file), join(BUILD_FOLDER, file));
|
|
41
44
|
|
|
42
45
|
Build
|
|
43
46
|
(
|
|
44
|
-
|
|
47
|
+
join(BUILD_FOLDER, 'index.js'),
|
|
45
48
|
sourceFiles,
|
|
46
49
|
USE_ROADROLLER ?
|
|
47
50
|
[closureCompilerStep, uglifyBuildStep, roadrollerBuildStep, htmlBuildStep, electronBuildStep] :
|
|
@@ -77,21 +80,21 @@ function closureCompilerStep(filename)
|
|
|
77
80
|
// use closer compiler to minify the code
|
|
78
81
|
const filenameTemp = filename + '.tmp';
|
|
79
82
|
fs.copyFileSync(filename, filenameTemp);
|
|
80
|
-
|
|
83
|
+
execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
|
|
81
84
|
fs.rmSync(filenameTemp);
|
|
82
|
-
}
|
|
85
|
+
}
|
|
83
86
|
|
|
84
87
|
function uglifyBuildStep(filename)
|
|
85
88
|
{
|
|
86
89
|
console.log('Running uglify...');
|
|
87
|
-
|
|
88
|
-
}
|
|
90
|
+
execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
|
|
91
|
+
}
|
|
89
92
|
|
|
90
93
|
function roadrollerBuildStep(filename)
|
|
91
94
|
{
|
|
92
95
|
console.log('Running roadroller...');
|
|
93
|
-
|
|
94
|
-
}
|
|
96
|
+
execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
|
|
97
|
+
}
|
|
95
98
|
|
|
96
99
|
function htmlBuildStep(filename)
|
|
97
100
|
{
|
|
@@ -108,17 +111,17 @@ function htmlBuildStep(filename)
|
|
|
108
111
|
buffer += `<script src='index.js'></script>`;
|
|
109
112
|
|
|
110
113
|
// output html file
|
|
111
|
-
fs.writeFileSync(
|
|
112
|
-
}
|
|
114
|
+
fs.writeFileSync(join(BUILD_FOLDER, 'index.html'), buffer, {flag: 'w+'});
|
|
115
|
+
}
|
|
113
116
|
|
|
114
117
|
function electronBuildStep(filename)
|
|
115
118
|
{
|
|
116
119
|
console.log('Building executable with electron...');
|
|
117
120
|
|
|
118
121
|
// copy elecron files to build folder
|
|
119
|
-
fs.copyFileSync('electron.js',
|
|
120
|
-
fs.copyFileSync('package.json',
|
|
122
|
+
fs.copyFileSync(join(__dirname, 'electron.js'), join(BUILD_FOLDER, 'electron.js'));
|
|
123
|
+
fs.copyFileSync(join(__dirname, 'package.json'), join(BUILD_FOLDER, 'package.json'));
|
|
121
124
|
|
|
122
125
|
// run electron packager
|
|
123
|
-
|
|
124
|
-
}
|
|
126
|
+
execSync(`npx electron-packager "${BUILD_FOLDER}" --overwrite --out="${__dirname}"`, {stdio: 'inherit'});
|
|
127
|
+
}
|
|
@@ -10,47 +10,13 @@
|
|
|
10
10
|
// show the LittleJS splash screen
|
|
11
11
|
setShowSplashScreen(true);
|
|
12
12
|
|
|
13
|
-
// fix texture bleeding by shrinking tile slightly
|
|
14
|
-
setTileDefaultBleed(.5);
|
|
15
|
-
|
|
16
13
|
// sound effects
|
|
17
14
|
const sound_click = new Sound([1,.5]);
|
|
18
15
|
|
|
19
16
|
///////////////////////////////////////////////////////////////////////////////
|
|
20
17
|
function gameInit()
|
|
21
18
|
{
|
|
22
|
-
|
|
23
|
-
const pos = vec2();
|
|
24
|
-
const tileLayer = new TileCollisionLayer(pos, vec2(32,16));
|
|
25
|
-
|
|
26
|
-
// get level data from the tiles image
|
|
27
|
-
const tileImage = textureInfos[0].image;
|
|
28
|
-
mainContext.drawImage(tileImage,0,0);
|
|
29
|
-
const imageData = mainContext.getImageData(0,0,tileImage.width,tileImage.height).data;
|
|
30
|
-
for (pos.x = tileLayer.size.x; pos.x--;)
|
|
31
|
-
for (pos.y = tileLayer.size.y; pos.y--;)
|
|
32
|
-
{
|
|
33
|
-
// check if this pixel is set
|
|
34
|
-
const i = pos.x + tileImage.width*(15 + tileLayer.size.y - pos.y);
|
|
35
|
-
if (!imageData[4*i])
|
|
36
|
-
continue;
|
|
37
|
-
|
|
38
|
-
// set tile data
|
|
39
|
-
const tileIndex = 1;
|
|
40
|
-
const direction = randInt(4)
|
|
41
|
-
const mirror = randBool();
|
|
42
|
-
const color = randColor();
|
|
43
|
-
const data = new TileLayerData(tileIndex, direction, mirror, color);
|
|
44
|
-
tileLayer.setData(pos, data);
|
|
45
|
-
tileLayer.setCollisionData(pos);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// draw tile layer with new data
|
|
49
|
-
tileLayer.redraw();
|
|
50
|
-
|
|
51
|
-
// setup camera
|
|
52
|
-
setCameraPos(vec2(16,8));
|
|
53
|
-
setCameraScale(32);
|
|
19
|
+
setCanvasClearColor(GRAY);
|
|
54
20
|
}
|
|
55
21
|
|
|
56
22
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -61,37 +27,26 @@ function gameUpdate()
|
|
|
61
27
|
// play sound when mouse is pressed
|
|
62
28
|
sound_click.play(mousePos);
|
|
63
29
|
}
|
|
64
|
-
|
|
65
|
-
if (mouseWheel)
|
|
66
|
-
{
|
|
67
|
-
// zoom in and out with mouse wheel
|
|
68
|
-
cameraScale -= sign(mouseWheel)*cameraScale/5;
|
|
69
|
-
cameraScale = clamp(cameraScale, 10, 300);
|
|
70
|
-
}
|
|
71
30
|
}
|
|
72
31
|
|
|
73
32
|
///////////////////////////////////////////////////////////////////////////////
|
|
74
33
|
function gameUpdatePost()
|
|
75
34
|
{
|
|
76
|
-
|
|
77
35
|
}
|
|
78
36
|
|
|
79
37
|
///////////////////////////////////////////////////////////////////////////////
|
|
80
38
|
function gameRender()
|
|
81
39
|
{
|
|
82
|
-
// draw a grey square in the background
|
|
83
|
-
drawRect(vec2(16,8), vec2(20,14), hsl(0,0,.6));
|
|
84
|
-
|
|
85
40
|
// draw the logo as a tile
|
|
86
|
-
drawTile(vec2(
|
|
41
|
+
drawTile(vec2(sin(time)*4, 0), vec2(10), tile(3,128));
|
|
87
42
|
}
|
|
88
43
|
|
|
89
44
|
///////////////////////////////////////////////////////////////////////////////
|
|
90
45
|
function gameRenderPost()
|
|
91
46
|
{
|
|
92
|
-
drawTextScreen('LittleJS
|
|
93
|
-
vec2(mainCanvasSize.x/2,
|
|
94
|
-
hsl(0,0,1), 6, hsl(0,0,0));
|
|
47
|
+
drawTextScreen('LittleJS\nElectron Demo',
|
|
48
|
+
vec2(mainCanvasSize.x/2, 100), 80, // position, size
|
|
49
|
+
hsl(0,0,1), 6, hsl(0,0,0)); // color, outline size and color
|
|
95
50
|
}
|
|
96
51
|
|
|
97
52
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -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></script>
|
|
11
11
|
|
|
12
12
|
<!-- Add your game scripts here -->
|
|
13
|
-
<script src=game.js
|
|
13
|
+
<script src=game.js></script>
|
package/examples/index.html
CHANGED
|
@@ -58,6 +58,7 @@ Theme:
|
|
|
58
58
|
<select id=selectExample onchange=setExample() size=2></select>
|
|
59
59
|
</div>
|
|
60
60
|
</div>
|
|
61
|
+
<a href="https://github.com/KilledByAPixel/LittleJS" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#70B7FD; color:#fff; position: absolute; top: 0; border: 0; left: 0; transform: scale(-1, 1);" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
|
61
62
|
<script>
|
|
62
63
|
'use strict';
|
|
63
64
|
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* LittleJS Build System
|
|
5
3
|
*/
|
|
6
4
|
|
|
7
5
|
'use strict';
|
|
8
6
|
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
|
|
9
14
|
const PROGRAM_TITLE = 'Little JS Starter Project';
|
|
10
15
|
const PROGRAM_NAME = 'game';
|
|
11
|
-
const BUILD_FOLDER = 'build';
|
|
16
|
+
const BUILD_FOLDER = join(__dirname, 'build');
|
|
12
17
|
const sourceFiles =
|
|
13
18
|
[
|
|
14
19
|
'game.js',
|
|
15
20
|
// add your game's source files here
|
|
16
21
|
];
|
|
17
|
-
const engineFile = '../../dist/littlejs.esm.min.js'; // Use the minified ES module
|
|
22
|
+
const engineFile = join(__dirname, '../../dist/littlejs.esm.min.js'); // Use the minified ES module
|
|
18
23
|
const dataFiles =
|
|
19
24
|
[
|
|
20
25
|
'tiles.png',
|
|
@@ -23,23 +28,21 @@ const dataFiles =
|
|
|
23
28
|
|
|
24
29
|
console.log(`Building ${PROGRAM_NAME}...`);
|
|
25
30
|
const startTime = Date.now();
|
|
26
|
-
const fs = require('node:fs');
|
|
27
|
-
const child_process = require('node:child_process');
|
|
28
31
|
|
|
29
32
|
// rebuild engine
|
|
30
|
-
//
|
|
33
|
+
//execSync(`npm run build`, { stdio: 'inherit' });
|
|
31
34
|
|
|
32
35
|
// remove old files and setup build folder
|
|
33
36
|
fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
|
|
34
|
-
fs.rmSync(`${PROGRAM_NAME}.zip
|
|
37
|
+
fs.rmSync(join(__dirname, `${PROGRAM_NAME}.zip`), { force: true });
|
|
35
38
|
fs.mkdirSync(BUILD_FOLDER);
|
|
36
39
|
|
|
37
40
|
// copy data files
|
|
38
41
|
for (const file of dataFiles)
|
|
39
|
-
fs.copyFileSync(file,
|
|
42
|
+
fs.copyFileSync(join(__dirname, file), join(BUILD_FOLDER, file));
|
|
40
43
|
|
|
41
44
|
// copy engine module
|
|
42
|
-
fs.copyFileSync(engineFile,
|
|
45
|
+
fs.copyFileSync(engineFile, join(BUILD_FOLDER, 'littlejs.esm.min.js'));
|
|
43
46
|
|
|
44
47
|
Build
|
|
45
48
|
(
|
|
@@ -59,8 +62,8 @@ function Build(files=[], buildSteps=[])
|
|
|
59
62
|
// process each source file separately (don't concatenate modules!)
|
|
60
63
|
for (const file of files)
|
|
61
64
|
{
|
|
62
|
-
const outputFile =
|
|
63
|
-
fs.copyFileSync(file, outputFile);
|
|
65
|
+
const outputFile = join(BUILD_FOLDER, file);
|
|
66
|
+
fs.copyFileSync(join(__dirname, file), outputFile);
|
|
64
67
|
moduleFixStep(outputFile);
|
|
65
68
|
uglifyBuildStep(outputFile);
|
|
66
69
|
}
|
|
@@ -89,8 +92,8 @@ function moduleFixStep(filename)
|
|
|
89
92
|
function uglifyBuildStep(filename)
|
|
90
93
|
{
|
|
91
94
|
console.log('Running uglify...');
|
|
92
|
-
|
|
93
|
-
}
|
|
95
|
+
execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
|
|
96
|
+
}
|
|
94
97
|
|
|
95
98
|
function htmlBuildStep()
|
|
96
99
|
{
|
|
@@ -108,14 +111,14 @@ function htmlBuildStep()
|
|
|
108
111
|
buffer += '</body>';
|
|
109
112
|
|
|
110
113
|
// output html file
|
|
111
|
-
fs.writeFileSync(
|
|
112
|
-
}
|
|
114
|
+
fs.writeFileSync(join(BUILD_FOLDER, 'index.html'), buffer, {flag: 'w+'});
|
|
115
|
+
}
|
|
113
116
|
|
|
114
117
|
function zipBuildStep()
|
|
115
118
|
{
|
|
116
119
|
console.log('Zipping...');
|
|
117
120
|
const sources = ['index.html', 'littlejs.esm.min.js', ...sourceFiles, ...dataFiles];
|
|
118
121
|
const sourceList = sources.join(' ');
|
|
119
|
-
|
|
120
|
-
console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(`${PROGRAM_NAME}.zip`).size} bytes`);
|
|
121
|
-
}
|
|
122
|
+
execSync(`npx bestzip ../${PROGRAM_NAME}.zip ${sourceList}`, {cwd:BUILD_FOLDER, stdio: 'inherit'});
|
|
123
|
+
console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(join(__dirname, `${PROGRAM_NAME}.zip`)).size} bytes`);
|
|
124
|
+
}
|
|
@@ -6,7 +6,7 @@ function gameRender()
|
|
|
6
6
|
{
|
|
7
7
|
// draw nine slice with thin border and color
|
|
8
8
|
const pos = vec2(-7,4);
|
|
9
|
-
const size = vec2(11+
|
|
9
|
+
const size = vec2(11+oscillate(.5,2), 6);
|
|
10
10
|
const color = hsl(.1,.5,.9);
|
|
11
11
|
const border = .5;
|
|
12
12
|
drawNineSlice(pos, size, nineSliceTile, color, border);
|
|
@@ -25,7 +25,7 @@ function gameRender()
|
|
|
25
25
|
// draw three slice with variable border and additive color
|
|
26
26
|
const pos = vec2(-7,-4);
|
|
27
27
|
const size = vec2(9, 7);
|
|
28
|
-
const border = 2 +
|
|
28
|
+
const border = 2 + oscillate(.2)*2;
|
|
29
29
|
const additive = hsl(time/30,.5,.5);
|
|
30
30
|
drawThreeSlice(pos, size, threeSliceTile, WHITE, border, additive);
|
|
31
31
|
drawText('Three Slice\nVariable\nBorder', pos, 1, BLACK);
|
|
@@ -33,7 +33,7 @@ function gameRender()
|
|
|
33
33
|
{
|
|
34
34
|
// draw three slice in screen space with changing size
|
|
35
35
|
const pos = vec2(700,420);
|
|
36
|
-
const size = vec2(350-
|
|
36
|
+
const size = vec2(350-oscillate(.3,90),120+oscillate(.3,60));
|
|
37
37
|
drawThreeSliceScreen(pos, size, threeSliceTile);
|
|
38
38
|
drawTextScreen('Three Slice\nScreen Space', pos, 30, BLACK);
|
|
39
39
|
}
|
|
@@ -2,7 +2,7 @@ function gameRender()
|
|
|
2
2
|
{
|
|
3
3
|
// circles and ellipses
|
|
4
4
|
drawEllipse(vec2(-6,5), vec2(3,2), YELLOW, .5);
|
|
5
|
-
drawCircle(vec2(0,5), 2+
|
|
5
|
+
drawCircle(vec2(0,5), 2+oscillate(.5), RED);
|
|
6
6
|
drawEllipse(vec2(6,5), vec2(2,4), CLEAR_BLACK, .3, .5, CYAN)
|
|
7
7
|
|
|
8
8
|
// polygon shapes
|
|
@@ -9,43 +9,44 @@ function gameInit()
|
|
|
9
9
|
|
|
10
10
|
// setup example menu
|
|
11
11
|
let navigationIndex = 0;
|
|
12
|
-
const uiMenu = new UIObject(mainCanvasSize.scale(.5), vec2(
|
|
12
|
+
const uiMenu = new UIObject(mainCanvasSize.scale(.5), vec2(700,450));
|
|
13
13
|
canvasClearColor = hsl(0,0,.8);
|
|
14
14
|
|
|
15
15
|
// example text
|
|
16
|
-
uiMenu.addChild(new UIText(vec2(-
|
|
16
|
+
uiMenu.addChild(new UIText(vec2(-100,-120), vec2(450, 80),
|
|
17
17
|
'LittleJS UI\nSystem Demo'));
|
|
18
18
|
|
|
19
19
|
// example image
|
|
20
|
-
uiMenu.addChild(new UITile(vec2(
|
|
20
|
+
uiMenu.addChild(new UITile(vec2(230,-140), vec2(170), tile(3, 128)));
|
|
21
21
|
|
|
22
22
|
// example checkbox
|
|
23
|
-
const checkbox = new UICheckbox(vec2(-
|
|
23
|
+
const checkbox = new UICheckbox(vec2(-170,0), vec2(50));
|
|
24
24
|
checkbox.navigationIndex = ++navigationIndex;
|
|
25
25
|
checkbox.onChange = ()=> button1.disabled = checkbox.checked;
|
|
26
26
|
uiMenu.addChild(checkbox);
|
|
27
27
|
|
|
28
28
|
// example button
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
const textInput = new UITextInput(vec2(50,0), vec2(300, 80), 'Text Input');
|
|
30
|
+
textInput.textHeight = 60;
|
|
31
|
+
textInput.maxLength = 16;
|
|
32
|
+
textInput.navigationIndex = ++navigationIndex;
|
|
33
|
+
uiMenu.addChild(textInput);
|
|
34
|
+
textInput.onChange = ()=> canvasClearColor = randColor();
|
|
34
35
|
|
|
35
36
|
// example scrollbar
|
|
36
|
-
const scrollbar = new UIScrollbar(vec2(0,90), vec2(
|
|
37
|
+
const scrollbar = new UIScrollbar(vec2(0,90), vec2(400, 50),
|
|
37
38
|
soundVolume, 'Volume');
|
|
38
39
|
scrollbar.navigationIndex = ++navigationIndex;
|
|
39
40
|
uiMenu.addChild(scrollbar);
|
|
40
41
|
scrollbar.onChange = ()=> setSoundVolume(scrollbar.value);
|
|
41
42
|
|
|
42
43
|
// exit button
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
uiMenu.addChild(
|
|
48
|
-
|
|
44
|
+
const button1 = new UIButton(vec2(0,170), vec2(200, 50), 'Exit Menu');
|
|
45
|
+
button1.textHeight = 40;
|
|
46
|
+
button1.navigationIndex = ++navigationIndex;
|
|
47
|
+
button1.navigationAutoSelect = true;
|
|
48
|
+
uiMenu.addChild(button1);
|
|
49
|
+
button1.onClick = ()=> uiSystem.showConfirmDialog('Exit menu?',
|
|
49
50
|
()=> { uiMenu.visible=false; buttonBack.visible=true; });
|
|
50
51
|
|
|
51
52
|
// example button that returns to menu
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* LittleJS Build System
|
|
5
3
|
*/
|
|
6
4
|
|
|
7
5
|
'use strict';
|
|
8
6
|
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
|
|
9
14
|
const PROGRAM_TITLE = 'Little JS Starter Project';
|
|
10
15
|
const PROGRAM_NAME = 'game';
|
|
11
|
-
const BUILD_FOLDER = 'build';
|
|
16
|
+
const BUILD_FOLDER = join(__dirname, 'build');
|
|
12
17
|
const USE_ROADROLLER = false; // enable for extra compression
|
|
13
18
|
const sourceFiles =
|
|
14
19
|
[
|
|
15
|
-
'../../dist/littlejs.release.js',
|
|
16
|
-
'game.js',
|
|
20
|
+
join(__dirname, '../../dist/littlejs.release.js'),
|
|
21
|
+
join(__dirname, 'game.js'),
|
|
17
22
|
// add your game's files here
|
|
18
23
|
];
|
|
19
24
|
const dataFiles =
|
|
@@ -24,24 +29,22 @@ const dataFiles =
|
|
|
24
29
|
|
|
25
30
|
console.log(`Building ${PROGRAM_NAME}...`);
|
|
26
31
|
const startTime = Date.now();
|
|
27
|
-
const fs = require('node:fs');
|
|
28
|
-
const child_process = require('node:child_process');
|
|
29
32
|
|
|
30
33
|
// rebuild engine
|
|
31
|
-
//
|
|
34
|
+
//execSync(`npm run build`, { stdio: 'inherit' });
|
|
32
35
|
|
|
33
36
|
// remove old files and setup build folder
|
|
34
37
|
fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
|
|
35
|
-
fs.rmSync(`${PROGRAM_NAME}.zip
|
|
38
|
+
fs.rmSync(join(__dirname, `${PROGRAM_NAME}.zip`), { force: true });
|
|
36
39
|
fs.mkdirSync(BUILD_FOLDER);
|
|
37
40
|
|
|
38
41
|
// copy data files
|
|
39
42
|
for (const file of dataFiles)
|
|
40
|
-
fs.copyFileSync(file,
|
|
43
|
+
fs.copyFileSync(join(__dirname, file), join(BUILD_FOLDER, file));
|
|
41
44
|
|
|
42
45
|
Build
|
|
43
46
|
(
|
|
44
|
-
|
|
47
|
+
join(BUILD_FOLDER, 'index.js'),
|
|
45
48
|
sourceFiles,
|
|
46
49
|
USE_ROADROLLER ?
|
|
47
50
|
[closureCompilerStep, uglifyBuildStep, roadrollerBuildStep, htmlBuildStep, zipBuildStep] :
|
|
@@ -77,21 +80,21 @@ function closureCompilerStep(filename)
|
|
|
77
80
|
// use closer compiler to minify the code
|
|
78
81
|
const filenameTemp = filename + '.tmp';
|
|
79
82
|
fs.copyFileSync(filename, filenameTemp);
|
|
80
|
-
|
|
83
|
+
execSync(`npx google-closure-compiler --js=${filenameTemp} --js_output_file=${filename} --compilation_level=ADVANCED --warning_level=VERBOSE --jscomp_off=* --assume_function_wrapper`, {stdio: 'inherit'});
|
|
81
84
|
fs.rmSync(filenameTemp);
|
|
82
|
-
}
|
|
85
|
+
}
|
|
83
86
|
|
|
84
87
|
function uglifyBuildStep(filename)
|
|
85
88
|
{
|
|
86
89
|
console.log('Running uglify...');
|
|
87
|
-
|
|
88
|
-
}
|
|
90
|
+
execSync(`npx uglifyjs ${filename} -c -m -o ${filename}`, {stdio: 'inherit'});
|
|
91
|
+
}
|
|
89
92
|
|
|
90
93
|
function roadrollerBuildStep(filename)
|
|
91
94
|
{
|
|
92
95
|
console.log('Running roadroller...');
|
|
93
|
-
|
|
94
|
-
}
|
|
96
|
+
execSync(`npx roadroller ${filename} -o ${filename}`, {stdio: 'inherit'});
|
|
97
|
+
}
|
|
95
98
|
|
|
96
99
|
function htmlBuildStep(filename)
|
|
97
100
|
{
|
|
@@ -110,14 +113,14 @@ function htmlBuildStep(filename)
|
|
|
110
113
|
buffer += '</script>';
|
|
111
114
|
|
|
112
115
|
// output html file
|
|
113
|
-
fs.writeFileSync(
|
|
114
|
-
}
|
|
116
|
+
fs.writeFileSync(join(BUILD_FOLDER, 'index.html'), buffer, {flag: 'w+'});
|
|
117
|
+
}
|
|
115
118
|
|
|
116
119
|
function zipBuildStep(filename)
|
|
117
120
|
{
|
|
118
121
|
console.log('Zipping...');
|
|
119
122
|
const sources = ['index.html', ...dataFiles];
|
|
120
123
|
const sourceList = sources.join(' ');
|
|
121
|
-
|
|
122
|
-
console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(`${PROGRAM_NAME}.zip`).size} bytes`);
|
|
123
|
-
}
|
|
124
|
+
execSync(`npx bestzip ../${PROGRAM_NAME}.zip ${sourceList}`, {cwd:BUILD_FOLDER, stdio: 'inherit'});
|
|
125
|
+
console.log(`Size of ${PROGRAM_NAME}.zip: ${fs.statSync(join(__dirname, `${PROGRAM_NAME}.zip`)).size} bytes`);
|
|
126
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</head><body>
|
|
8
8
|
|
|
9
9
|
<!-- LittleJS Engine -->
|
|
10
|
-
<script src=../../dist/littlejs.js?1.17.
|
|
10
|
+
<script src=../../dist/littlejs.js?1.17.15></script>
|
|
11
11
|
|
|
12
12
|
<!-- LittleJS Engine Source
|
|
13
13
|
<script src=../../src/engine.js></script>
|
|
@@ -32,4 +32,4 @@
|
|
|
32
32
|
-->
|
|
33
33
|
|
|
34
34
|
<!-- Add your game scripts here -->
|
|
35
|
-
<script src=game.js?1.17.
|
|
35
|
+
<script src=game.js?1.17.15></script>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LittleJS TypeScript Example Build System
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const PROGRAM_NAME = 'game';
|
|
14
|
+
const BUILD_FOLDER = join(__dirname, 'build');
|
|
15
|
+
|
|
16
|
+
// Define TypeScript source files
|
|
17
|
+
const tsSourceFiles = [
|
|
18
|
+
'game.ts',
|
|
19
|
+
// add your TypeScript files here
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
// Corresponding JS output files
|
|
23
|
+
const jsSourceFiles = tsSourceFiles.map(file => file.replace('.ts', '.js'));
|
|
24
|
+
|
|
25
|
+
console.log(`Building TypeScript for ${PROGRAM_NAME}...`);
|
|
26
|
+
const startTime = Date.now();
|
|
27
|
+
|
|
28
|
+
console.log(`Removing old build folder...`);
|
|
29
|
+
fs.rmSync(BUILD_FOLDER, { recursive: true, force: true });
|
|
30
|
+
|
|
31
|
+
console.log(`Compiling TypeScript...`);
|
|
32
|
+
|
|
33
|
+
// Use tsconfig.json for compilation settings
|
|
34
|
+
try
|
|
35
|
+
{
|
|
36
|
+
const result = execSync(`npx -p typescript tsc`, {cwd: __dirname, encoding: 'utf8', stdio: 'pipe'});
|
|
37
|
+
console.log(result);
|
|
38
|
+
} catch (error)
|
|
39
|
+
{
|
|
40
|
+
console.error('TypeScript compilation errors:');
|
|
41
|
+
if (error.stdout) console.log(error.stdout);
|
|
42
|
+
if (error.stderr) console.error(error.stderr);
|
|
43
|
+
console.error('TypeScript compilation failed!');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(`Copying js files back to root...`);
|
|
48
|
+
for (const file of jsSourceFiles)
|
|
49
|
+
{
|
|
50
|
+
// TypeScript outputs to build/examples/typescript/ because of relative paths
|
|
51
|
+
const buildFile = join(BUILD_FOLDER, 'examples', 'typescript', file);
|
|
52
|
+
const targetFile = join(__dirname, file);
|
|
53
|
+
console.log(`Copying ${file}...`);
|
|
54
|
+
if (fs.existsSync(buildFile))
|
|
55
|
+
fs.copyFileSync(buildFile, targetFile);
|
|
56
|
+
else
|
|
57
|
+
console.error(`✗ Build file not found: ${buildFile}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log(`TypeScript built in ${((Date.now() - startTime)/1e3).toFixed(2)} seconds!`);
|
|
@@ -61,7 +61,7 @@ function gameInit() {
|
|
|
61
61
|
.05, .5, true, true // fadeRate, randomness, collide, additive
|
|
62
62
|
);
|
|
63
63
|
particleEmitter.restitution = .3; // bounce when it collides
|
|
64
|
-
particleEmitter.trailScale = 2;
|
|
64
|
+
particleEmitter.trailScale = 2; // stretch stretch as it moves
|
|
65
65
|
particleEmitter.velocityInheritance = .3; // inherit emitter velocity
|
|
66
66
|
}
|
|
67
67
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -97,4 +97,4 @@ function gameRenderPost() {
|
|
|
97
97
|
}
|
|
98
98
|
///////////////////////////////////////////////////////////////////////////////
|
|
99
99
|
// Startup LittleJS Engine
|
|
100
|
-
LJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
|
|
100
|
+
LJS.engineInit(gameInit, gameUpdate, gameUpdatePost, gameRender, gameRenderPost, ['tiles.png']);
|