littlejsengine 1.19.3 → 1.21.0
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/FAQ.md +841 -820
- package/README.md +29 -25
- package/dist/littlejs.d.ts +2857 -955
- package/dist/littlejs.esm.js +33428 -20995
- package/dist/littlejs.esm.min.js +4 -3
- package/dist/littlejs.js +33386 -20996
- package/dist/littlejs.min.js +2 -2
- package/dist/littlejs.release.js +27841 -20422
- package/package.json +10 -5
- package/plugins/audioEffects.js +28 -24
- package/plugins/box2d.js +2516 -2073
- package/plugins/drawUtilities.js +206 -31
- package/plugins/gltf.js +786 -0
- package/plugins/jsconfig.json +19 -0
- package/plugins/lightSystem.js +719 -332
- package/plugins/math3d.js +148 -27
- package/plugins/medalSystem.js +326 -280
- package/plugins/newgrounds.js +400 -199
- package/plugins/pathFinder.js +208 -175
- package/plugins/pluginExport.js +25 -0
- package/plugins/postProcess.js +96 -24
- package/plugins/render3d.js +2067 -1632
- package/plugins/render3dDebug.js +110 -0
- package/plugins/render3dEditor.js +1812 -0
- package/plugins/render3dExtras.js +1948 -0
- package/plugins/render3dLevel.js +189 -0
- package/plugins/render3dVoxels.js +514 -0
- package/plugins/sceneSystem.js +58 -0
- package/plugins/textureSheet.js +496 -458
- package/plugins/threejs.js +183 -163
- package/plugins/tweakables.js +411 -0
- package/plugins/tweenSystem.js +265 -145
- package/plugins/uiSystem.js +2024 -1687
- package/plugins/zzfxm.js +159 -159
- package/src/engine.js +378 -97
- package/src/engineAudio.js +231 -127
- package/src/engineBuild.mjs +292 -256
- package/src/engineDebug.js +967 -743
- package/src/engineDraw.js +391 -198
- package/src/engineEditor.js +2452 -0
- package/src/engineExport.js +18 -0
- package/src/engineInput.js +1466 -1293
- package/src/engineLogo.js +19 -0
- package/src/engineMath.js +1274 -1252
- package/src/engineObject.js +197 -82
- package/src/engineParticles.js +583 -532
- package/src/engineRelease.js +79 -45
- package/src/engineSettings.js +115 -29
- package/src/engineTileLayer.js +995 -741
- package/src/engineUtilities.js +19 -13
- package/src/engineWebGL.js +239 -82
- package/src/jsconfig.json +17 -13
- package/plugins/box2d.wasm.js +0 -630
- package/plugins/box2d.wasm.wasm +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LittleJS 3D Level Plugin
|
|
3
|
+
* - A 3D level is a list of objects, each a type name, a position, and a rotation, scale and properties where
|
|
4
|
+
* they are not the default, kept as plain JSON that can be written by hand
|
|
5
|
+
* - level3DAddType names the types a game makes them from, as objectLayersAddType does in 2D
|
|
6
|
+
* - level3DLoad makes every object of a level
|
|
7
|
+
* - Box, Sphere, Cylinder and Light are built in, to block out and light a level with no code
|
|
8
|
+
* - The 3D level editor, in debug builds, edits the level a game loaded
|
|
9
|
+
* @namespace Level3D
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
15
|
+
|
|
16
|
+
const LEVEL3D_VERSION = 1; // the format a level's littlejs3D names
|
|
17
|
+
|
|
18
|
+
// the types a level's objects are made from, by name
|
|
19
|
+
const level3DTypes = new Map;
|
|
20
|
+
|
|
21
|
+
// the scale each object had when it was made, the level's scale multiplies it
|
|
22
|
+
const level3DBaseScale = new WeakMap;
|
|
23
|
+
|
|
24
|
+
/** Add a type of object, so level3DLoad makes one wherever a level has an object of that type
|
|
25
|
+
* - The name is a string because minified builds rename classes
|
|
26
|
+
* - A class, or any function with a prototype, is made with new make(pos3D, properties); an arrow function is
|
|
27
|
+
* called as make(pos3D, properties), for what is not an object, like a player start
|
|
28
|
+
* - properties is the defaults with the object's own values over them, and each of the type's own is also set on
|
|
29
|
+
* what was made; a property the type has no default for is in properties and is not set
|
|
30
|
+
* - Give a class a constructor of its own that takes the position: one that hands every argument on to
|
|
31
|
+
* EngineObject3D would hand it the properties as its mesh
|
|
32
|
+
* - An EngineObject3D then gets the object's rotation, and its scale times the scale it was made with
|
|
33
|
+
* - Adding a name again replaces it, Box, Sphere, Cylinder and Light too
|
|
34
|
+
* @param {string} name - The type the objects have in the level
|
|
35
|
+
* @param {Function} make - A class made at each object's position, or a function called with it
|
|
36
|
+
* @param {Object} [defaults] - Properties of each one made, the level editor shows inputs for them
|
|
37
|
+
* @param {TileInfo} [tileInfo] - An icon for the level editor
|
|
38
|
+
* @memberof Level3D
|
|
39
|
+
* @example
|
|
40
|
+
* level3DAddType('Crate', Crate, {health: 3});
|
|
41
|
+
* level3DAddType('PlayerStart', (pos)=> playerStart = pos); */
|
|
42
|
+
function level3DAddType(name, make, defaults={}, tileInfo)
|
|
43
|
+
{
|
|
44
|
+
ASSERT(isStringLike(name), 'object type name must be a string');
|
|
45
|
+
ASSERT(typeof make === 'function', 'make must be a class or function');
|
|
46
|
+
ASSERT(!!defaults && typeof defaults === 'object', 'defaults must be an object');
|
|
47
|
+
level3DTypes.set(String(name), {make, defaults, tileInfo});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Add a type that is a mesh and nothing more, a static prop with no class to write, for a built mesh or a model
|
|
51
|
+
* - Each object has a color and a solid property, solid collides as the box around the mesh
|
|
52
|
+
* @param {string} name - The type the objects have in the level
|
|
53
|
+
* @param {Mesh} mesh - Shared by every object of the type
|
|
54
|
+
* @param {TileInfo} [tileInfo] - Its texture
|
|
55
|
+
* @param {Color} [color] - Its color, an object's own color property goes over it
|
|
56
|
+
* @memberof Level3D
|
|
57
|
+
* @example
|
|
58
|
+
* level3DAddMesh('Tree', treeMesh, tile(4)); */
|
|
59
|
+
function level3DAddMesh(name, mesh, tileInfo, color=WHITE)
|
|
60
|
+
{
|
|
61
|
+
ASSERT(mesh instanceof Mesh, 'mesh must be a Mesh');
|
|
62
|
+
ASSERT(isColor(color), 'color must be a color');
|
|
63
|
+
level3DAddType(name, function(pos, properties) { return level3DMakeShape(pos, properties, mesh, tileInfo); },
|
|
64
|
+
{color, solid: false}, tileInfo);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Make the objects of a level, each from the type added for its name
|
|
68
|
+
* - The level is an object: {littlejs3D: 1, objects: [{id, type, pos: [x, y, z]}, ...]}, and {} is a new one
|
|
69
|
+
* - rotation is pitch, yaw and roll in degrees, scale is a number for each axis, both left out when they are
|
|
70
|
+
* the default, and properties holds what differs from the type's defaults
|
|
71
|
+
* - A Color property is a #rrggbb or #rrggbbaa string, a Vector2 or Vector3 an array, as the default says
|
|
72
|
+
* - An object whose type was not added is skipped, with a warning in debug builds
|
|
73
|
+
* - What a file written by hand gets wrong uses the default: a value that is not of its default's type
|
|
74
|
+
* - An object its type can not make is skipped with an error in debug builds, where asserts throw, and the rest
|
|
75
|
+
* of the level is made
|
|
76
|
+
* @param {Object} level - The level, the level editor edits this same object
|
|
77
|
+
* @return {Array<any>} - What each object's type made, a function that made nothing is left out
|
|
78
|
+
* @memberof Level3D */
|
|
79
|
+
function level3DLoad(level)
|
|
80
|
+
{
|
|
81
|
+
ASSERT(!!level && typeof level === 'object', 'a level is an object, {} for a new one');
|
|
82
|
+
ASSERT(!(level.littlejs3D > LEVEL3D_VERSION), 'the level was made by a newer LittleJS');
|
|
83
|
+
editor3DLevelLoaded(level); // debug builds: the 3D editor takes the level, its autosaved edits go in first
|
|
84
|
+
const made = [];
|
|
85
|
+
for (const object of isArray(level.objects) ? level.objects : [])
|
|
86
|
+
{
|
|
87
|
+
if (!object || typeof object !== 'object') continue;
|
|
88
|
+
const result = level3DMake(object);
|
|
89
|
+
editor3DObjectMade(object, result); // debug builds link it for the 3D editor
|
|
90
|
+
result && made.push(result);
|
|
91
|
+
}
|
|
92
|
+
return made;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// a vec3 of an array of three numbers, as the file has them, or the fallback
|
|
96
|
+
function level3DVector(value, fallback)
|
|
97
|
+
{
|
|
98
|
+
return isArray(value) && value.length === 3 && value.every((v)=> isNumber(v)) ?
|
|
99
|
+
vec3(value[0], value[1], value[2]) : fallback;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// the defaults of an object's type, a Color or vector copied for each object, then its own properties over them,
|
|
103
|
+
// each read as its default is; one the file got wrong, a value not of its default's type, keeps the default, and
|
|
104
|
+
// one the type has no default for is kept as it is
|
|
105
|
+
function level3DProperties(type, object)
|
|
106
|
+
{
|
|
107
|
+
const properties = {}, own = object.properties;
|
|
108
|
+
for (const [key, value] of Object.entries(type.defaults))
|
|
109
|
+
properties[key] = value?.copy ? value.copy() : value;
|
|
110
|
+
for (const [key, value] of Object.entries(own && typeof own === 'object' ? own : {}))
|
|
111
|
+
{
|
|
112
|
+
const d = type.defaults[key];
|
|
113
|
+
if (isColor(d))
|
|
114
|
+
/^#([0-9a-f]{6}|[0-9a-f]{8})$/i.test(value) && (properties[key] = new Color().setHex(value));
|
|
115
|
+
else if (isVector3(d))
|
|
116
|
+
properties[key] = level3DVector(value, properties[key]);
|
|
117
|
+
else if (isVector2(d))
|
|
118
|
+
isArray(value) && value.length === 2 && value.every((v)=> isNumber(v)) &&
|
|
119
|
+
(properties[key] = vec2(value[0], value[1]));
|
|
120
|
+
else if (d === undefined || typeof value === typeof d)
|
|
121
|
+
properties[key] = value;
|
|
122
|
+
}
|
|
123
|
+
return properties;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// make one object of a level from the type added for its name, undefined when there is no such type or it made
|
|
127
|
+
// nothing
|
|
128
|
+
function level3DMake(object)
|
|
129
|
+
{
|
|
130
|
+
const type = level3DTypes.get(object.type);
|
|
131
|
+
if (!type)
|
|
132
|
+
{
|
|
133
|
+
debug && console.warn(`level3DLoad: no type added for ${object.type}, skipped`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const pos = level3DVector(object.pos, vec3()), properties = level3DProperties(type, object);
|
|
137
|
+
const {make} = type, count = engineObjects.length;
|
|
138
|
+
let result;
|
|
139
|
+
try { result = make.prototype ? new make(pos, properties) : make(pos, properties); }
|
|
140
|
+
catch (error)
|
|
141
|
+
{
|
|
142
|
+
// a value the type can not be made with: in debug builds, where asserts throw, the object is skipped with
|
|
143
|
+
// what it made so far, so the rest of the level loads and the level editor can put the value right
|
|
144
|
+
if (!debug) throw error;
|
|
145
|
+
console.error(`level3DLoad: ${object.type} ${object.id} could not be made, skipped:`, error);
|
|
146
|
+
for (const o of engineObjects.slice(count))
|
|
147
|
+
o.destroy();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (!result || typeof result !== 'object') return;
|
|
151
|
+
if (result instanceof EngineObject3D)
|
|
152
|
+
{
|
|
153
|
+
level3DBaseScale.set(result, result.scale3D.copy());
|
|
154
|
+
result.rotation3D = level3DVector(object.rotation, vec3()).scale(PI / 180);
|
|
155
|
+
result.scale3D = result.scale3D.multiply(level3DVector(object.scale, vec3(1)));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// the type's own properties are set on it, one the type has no default for could be a field of the engine's
|
|
159
|
+
for (const key in type.defaults)
|
|
160
|
+
result[key] = properties[key];
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
165
|
+
// the built-in types
|
|
166
|
+
|
|
167
|
+
// a static object of a mesh, with the color, tile and solid properties the built-in types have
|
|
168
|
+
function level3DMakeShape(pos, properties, mesh, tileInfo, asSphere=false)
|
|
169
|
+
{
|
|
170
|
+
const o = new EngineObject3D(pos, mesh, properties.tile >= 0 ? tile(properties.tile) : tileInfo, properties.color);
|
|
171
|
+
o.collideAsSphere3D = asSphere;
|
|
172
|
+
properties.solid && o.setCollision();
|
|
173
|
+
return o;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// the cylinder all Cylinder objects share, built the first time one is made
|
|
177
|
+
let level3DCylinderMesh;
|
|
178
|
+
|
|
179
|
+
level3DAddType('Box', function(pos, properties) { return level3DMakeShape(pos, properties, render3D.boxMesh); },
|
|
180
|
+
{color: WHITE, tile: -1, solid: true});
|
|
181
|
+
level3DAddType('Sphere', function(pos, properties)
|
|
182
|
+
{ return level3DMakeShape(pos, properties, render3D.sphereMesh, undefined, true); },
|
|
183
|
+
{color: WHITE, tile: -1, solid: true});
|
|
184
|
+
level3DAddType('Cylinder', function(pos, properties)
|
|
185
|
+
{ return level3DMakeShape(pos, properties, level3DCylinderMesh ||= buildCylinder()); },
|
|
186
|
+
{color: WHITE, tile: -1, solid: true});
|
|
187
|
+
level3DAddType('Light', function(pos, properties)
|
|
188
|
+
{ return new Light3D(pos, properties.radius, properties.color, properties.intensity); },
|
|
189
|
+
{color: WHITE, radius: 5, intensity: 1});
|