melonjs 20.2.0 → 20.4.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/README.md +86 -8
- package/build/application/application.d.ts +0 -17
- package/build/application/application.d.ts.map +1 -1
- package/build/application/settings.d.ts +6 -2
- package/build/application/settings.d.ts.map +1 -1
- package/build/audio/audio.d.ts +2 -2
- package/build/audio/audio.d.ts.map +1 -1
- package/build/audio/backend/buffer.d.ts +26 -0
- package/build/audio/backend/buffer.d.ts.map +1 -0
- package/build/audio/backend/cache.d.ts +2 -0
- package/build/audio/backend/cache.d.ts.map +1 -0
- package/build/audio/backend/core.d.ts +24 -0
- package/build/audio/backend/core.d.ts.map +1 -0
- package/build/audio/backend/engine.d.ts +35 -0
- package/build/audio/backend/engine.d.ts.map +1 -0
- package/build/audio/backend/sound.d.ts +29 -0
- package/build/audio/backend/sound.d.ts.map +1 -0
- package/build/audio/backend/spatial.d.ts +191 -0
- package/build/audio/backend/spatial.d.ts.map +1 -0
- package/build/audio/backend/types.d.ts +107 -0
- package/build/audio/backend/types.d.ts.map +1 -0
- package/build/audio/backend/voice.d.ts +8 -0
- package/build/audio/backend/voice.d.ts.map +1 -0
- package/build/audio/playback.d.ts +49 -4
- package/build/audio/playback.d.ts.map +1 -1
- package/build/audio/procedural.d.ts.map +1 -1
- package/build/audio/state.d.ts +69 -0
- package/build/audio/state.d.ts.map +1 -0
- package/build/audio/types.d.ts +93 -1
- package/build/audio/types.d.ts.map +1 -1
- package/build/camera/camera2d.d.ts +0 -68
- package/build/camera/camera2d.d.ts.map +1 -1
- package/build/camera/camera3d.d.ts +91 -84
- package/build/camera/camera3d.d.ts.map +1 -1
- package/build/camera/effects/fade_effect.d.ts +0 -5
- package/build/camera/effects/fade_effect.d.ts.map +1 -1
- package/build/camera/effects/mask_effect.d.ts +0 -5
- package/build/camera/effects/mask_effect.d.ts.map +1 -1
- package/build/camera/fog.d.ts +118 -0
- package/build/camera/fog.d.ts.map +1 -0
- package/build/const.d.ts +2 -2
- package/build/geometries/box3d.d.ts +0 -28
- package/build/geometries/box3d.d.ts.map +1 -1
- package/build/geometries/ellipse.d.ts +0 -20
- package/build/geometries/ellipse.d.ts.map +1 -1
- package/build/geometries/observablePoint.d.ts +0 -3
- package/build/geometries/observablePoint.d.ts.map +1 -1
- package/build/geometries/path2d.d.ts +0 -19
- package/build/geometries/path2d.d.ts.map +1 -1
- package/build/geometries/polygon.d.ts +0 -12
- package/build/geometries/polygon.d.ts.map +1 -1
- package/build/geometries/roundrect.d.ts +0 -18
- package/build/geometries/roundrect.d.ts.map +1 -1
- package/build/geometries/sphere.d.ts +0 -9
- package/build/geometries/sphere.d.ts.map +1 -1
- package/build/geometries/toarccanvas.d.ts.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +12150 -11289
- package/build/index.js.map +4 -4
- package/build/input/gamepad.d.ts.map +1 -1
- package/build/input/input.d.ts +19 -0
- package/build/input/input.d.ts.map +1 -1
- package/build/input/pointer.d.ts +0 -4
- package/build/input/pointer.d.ts.map +1 -1
- package/build/input/pointerevent.d.ts +0 -6
- package/build/input/pointerevent.d.ts.map +1 -1
- package/build/lang/deprecated.d.ts +4 -2
- package/build/lang/deprecated.d.ts.map +1 -1
- package/build/level/gltf/GLTFModel.d.ts +0 -81
- package/build/level/gltf/GLTFModel.d.ts.map +1 -1
- package/build/level/gltf/GLTFScene.d.ts +13 -44
- package/build/level/gltf/GLTFScene.d.ts.map +1 -1
- package/build/level/gltf/gltf_sampler.d.ts +1 -48
- package/build/level/gltf/gltf_sampler.d.ts.map +1 -1
- package/build/level/level.d.ts +195 -113
- package/build/level/level.d.ts.map +1 -1
- package/build/level/tiled/TMXGroup.d.ts +1 -65
- package/build/level/tiled/TMXGroup.d.ts.map +1 -1
- package/build/level/tiled/TMXLayer.d.ts +0 -44
- package/build/level/tiled/TMXLayer.d.ts.map +1 -1
- package/build/level/tiled/TMXObject.d.ts +1 -136
- package/build/level/tiled/TMXObject.d.ts.map +1 -1
- package/build/level/tiled/TMXObjectFactory.d.ts +1 -40
- package/build/level/tiled/TMXObjectFactory.d.ts.map +1 -1
- package/build/level/tiled/TMXTile.d.ts +1 -30
- package/build/level/tiled/TMXTile.d.ts.map +1 -1
- package/build/level/tiled/TMXTileMap.d.ts +0 -10
- package/build/level/tiled/TMXTileMap.d.ts.map +1 -1
- package/build/level/tiled/TMXTileset.d.ts +0 -113
- package/build/level/tiled/TMXTileset.d.ts.map +1 -1
- package/build/level/tiled/TMXTilesetGroup.d.ts +0 -1
- package/build/level/tiled/TMXTilesetGroup.d.ts.map +1 -1
- package/build/level/tiled/TMXUtils.d.ts +1 -43
- package/build/level/tiled/TMXUtils.d.ts.map +1 -1
- package/build/level/tiled/factories/shape.d.ts +1 -7
- package/build/level/tiled/factories/shape.d.ts.map +1 -1
- package/build/level/tiled/factories/text.d.ts +1 -7
- package/build/level/tiled/factories/text.d.ts.map +1 -1
- package/build/level/tiled/factories/tile.d.ts +1 -7
- package/build/level/tiled/factories/tile.d.ts.map +1 -1
- package/build/level/tiled/renderer/TMXHexagonalRenderer.d.ts +0 -60
- package/build/level/tiled/renderer/TMXHexagonalRenderer.d.ts.map +1 -1
- package/build/level/tiled/renderer/TMXIsometricRenderer.d.ts +0 -42
- package/build/level/tiled/renderer/TMXIsometricRenderer.d.ts.map +1 -1
- package/build/level/tiled/renderer/TMXObliqueRenderer.d.ts +0 -5
- package/build/level/tiled/renderer/TMXObliqueRenderer.d.ts.map +1 -1
- package/build/level/tiled/renderer/TMXOrthogonalRenderer.d.ts +0 -31
- package/build/level/tiled/renderer/TMXOrthogonalRenderer.d.ts.map +1 -1
- package/build/level/tiled/renderer/TMXRenderer.d.ts +2 -2
- package/build/level/tiled/renderer/TMXRenderer.d.ts.map +1 -1
- package/build/level/tiled/renderer/TMXStaggeredRenderer.d.ts.map +1 -1
- package/build/level/tiled/renderer/autodetect.d.ts +1 -6
- package/build/level/tiled/renderer/autodetect.d.ts.map +1 -1
- package/build/lighting/light2d.d.ts +0 -25
- package/build/lighting/light2d.d.ts.map +1 -1
- package/build/lighting/light3d.d.ts +0 -16
- package/build/lighting/light3d.d.ts.map +1 -1
- package/build/loader/loader.d.ts +46 -73
- package/build/loader/loader.d.ts.map +1 -1
- package/build/loader/loadingscreen.d.ts +0 -33
- package/build/loader/loadingscreen.d.ts.map +1 -1
- package/build/loader/parsers/aseprite.d.ts +0 -13
- package/build/loader/parsers/aseprite.d.ts.map +1 -1
- package/build/loader/parsers/audio.d.ts +2 -0
- package/build/loader/parsers/audio.d.ts.map +1 -0
- package/build/loader/parsers/binary.d.ts +1 -10
- package/build/loader/parsers/binary.d.ts.map +1 -1
- package/build/loader/parsers/compressed_textures/compressed_image.d.ts.map +1 -1
- package/build/loader/parsers/compressed_textures/parseDDS.d.ts +1 -7
- package/build/loader/parsers/compressed_textures/parseDDS.d.ts.map +1 -1
- package/build/loader/parsers/compressed_textures/parseKTX.d.ts +1 -7
- package/build/loader/parsers/compressed_textures/parseKTX.d.ts.map +1 -1
- package/build/loader/parsers/compressed_textures/parseKTX2.d.ts +1 -7
- package/build/loader/parsers/compressed_textures/parseKTX2.d.ts.map +1 -1
- package/build/loader/parsers/compressed_textures/parsePKM.d.ts +1 -7
- package/build/loader/parsers/compressed_textures/parsePKM.d.ts.map +1 -1
- package/build/loader/parsers/compressed_textures/parsePVR.d.ts +1 -7
- package/build/loader/parsers/compressed_textures/parsePVR.d.ts.map +1 -1
- package/build/loader/parsers/fontface.d.ts +1 -13
- package/build/loader/parsers/fontface.d.ts.map +1 -1
- package/build/loader/parsers/gltf.d.ts +1 -70
- package/build/loader/parsers/gltf.d.ts.map +1 -1
- package/build/loader/parsers/image.d.ts +1 -22
- package/build/loader/parsers/image.d.ts.map +1 -1
- package/build/loader/parsers/json.d.ts +1 -10
- package/build/loader/parsers/json.d.ts.map +1 -1
- package/build/loader/parsers/mtl.d.ts +1 -28
- package/build/loader/parsers/mtl.d.ts.map +1 -1
- package/build/loader/parsers/obj.d.ts +1 -59
- package/build/loader/parsers/obj.d.ts.map +1 -1
- package/build/loader/parsers/pbr.d.ts +1 -62
- package/build/loader/parsers/pbr.d.ts.map +1 -1
- package/build/loader/parsers/script.d.ts +1 -10
- package/build/loader/parsers/script.d.ts.map +1 -1
- package/build/loader/parsers/shader.d.ts +1 -52
- package/build/loader/parsers/shader.d.ts.map +1 -1
- package/build/loader/parsers/tmx.d.ts +1 -10
- package/build/loader/parsers/tmx.d.ts.map +1 -1
- package/build/loader/parsers/video.d.ts +1 -10
- package/build/loader/parsers/video.d.ts.map +1 -1
- package/build/math/color.d.ts.map +1 -1
- package/build/math/noise.d.ts +0 -40
- package/build/math/noise.d.ts.map +1 -1
- package/build/math/observableVector2d.d.ts +0 -3
- package/build/math/observableVector2d.d.ts.map +1 -1
- package/build/math/observableVector3d.d.ts +0 -3
- package/build/math/observableVector3d.d.ts.map +1 -1
- package/build/math/vector2d.d.ts +0 -6
- package/build/math/vector2d.d.ts.map +1 -1
- package/build/math/vertex.d.ts +25 -0
- package/build/math/vertex.d.ts.map +1 -1
- package/build/particles/emitter.d.ts +0 -65
- package/build/particles/emitter.d.ts.map +1 -1
- package/build/particles/particle.d.ts +0 -81
- package/build/particles/particle.d.ts.map +1 -1
- package/build/physics/adapter.d.ts +3 -3
- package/build/physics/bounds.d.ts +0 -1
- package/build/physics/bounds.d.ts.map +1 -1
- package/build/physics/broadphase/broadphase.d.ts +0 -7
- package/build/physics/broadphase/broadphase.d.ts.map +1 -1
- package/build/physics/broadphase/octree.d.ts +0 -91
- package/build/physics/broadphase/octree.d.ts.map +1 -1
- package/build/physics/broadphase/quadtree.d.ts +0 -47
- package/build/physics/broadphase/quadtree.d.ts.map +1 -1
- package/build/physics/builtin/body.d.ts +5 -69
- package/build/physics/builtin/body.d.ts.map +1 -1
- package/build/physics/builtin/detector.d.ts +0 -312
- package/build/physics/builtin/detector.d.ts.map +1 -1
- package/build/physics/builtin/sat.d.ts +1 -48
- package/build/physics/builtin/sat.d.ts.map +1 -1
- package/build/physics/builtin/sat3d.d.ts +1 -56
- package/build/physics/builtin/sat3d.d.ts.map +1 -1
- package/build/physics/collision.d.ts +0 -2
- package/build/physics/collision.d.ts.map +1 -1
- package/build/physics/response.d.ts +0 -1
- package/build/physics/response.d.ts.map +1 -1
- package/build/physics/world.d.ts.map +1 -1
- package/build/plugin/plugin.d.ts +9 -1
- package/build/plugin/plugin.d.ts.map +1 -1
- package/build/polyfill/index.d.ts +1 -4
- package/build/polyfill/index.d.ts.map +1 -1
- package/build/renderable/anchorPoint.d.ts +1 -73
- package/build/renderable/anchorPoint.d.ts.map +1 -1
- package/build/renderable/animation.d.ts +0 -7
- package/build/renderable/animation.d.ts.map +1 -1
- package/build/renderable/colorlayer.d.ts +0 -5
- package/build/renderable/colorlayer.d.ts.map +1 -1
- package/build/renderable/container.d.ts +0 -55
- package/build/renderable/container.d.ts.map +1 -1
- package/build/renderable/draggable.d.ts +0 -5
- package/build/renderable/draggable.d.ts.map +1 -1
- package/build/renderable/dragndrop.d.ts +1 -12
- package/build/renderable/dragndrop.d.ts.map +1 -1
- package/build/renderable/entity/entity.d.ts +0 -8
- package/build/renderable/entity/entity.d.ts.map +1 -1
- package/build/renderable/frameAnimation.d.ts +0 -41
- package/build/renderable/frameAnimation.d.ts.map +1 -1
- package/build/renderable/groundshadow.d.ts +1 -91
- package/build/renderable/groundshadow.d.ts.map +1 -1
- package/build/renderable/imagelayer.d.ts +0 -29
- package/build/renderable/imagelayer.d.ts.map +1 -1
- package/build/renderable/instanced_mesh.d.ts +26 -104
- package/build/renderable/instanced_mesh.d.ts.map +1 -1
- package/build/renderable/mesh.d.ts +145 -140
- package/build/renderable/mesh.d.ts.map +1 -1
- package/build/renderable/nineslicesprite.d.ts +0 -4
- package/build/renderable/nineslicesprite.d.ts.map +1 -1
- package/build/renderable/renderable.d.ts +17 -54
- package/build/renderable/renderable.d.ts.map +1 -1
- package/build/renderable/sprite.d.ts +7 -52
- package/build/renderable/sprite.d.ts.map +1 -1
- package/build/renderable/sprite3d.d.ts +0 -95
- package/build/renderable/sprite3d.d.ts.map +1 -1
- package/build/renderable/text/bitmaptext.d.ts +0 -14
- package/build/renderable/text/bitmaptext.d.ts.map +1 -1
- package/build/renderable/text/bitmaptextdata.d.ts +0 -22
- package/build/renderable/text/bitmaptextdata.d.ts.map +1 -1
- package/build/renderable/text/glyph.d.ts +1 -39
- package/build/renderable/text/glyph.d.ts.map +1 -1
- package/build/renderable/text/text.d.ts +0 -20
- package/build/renderable/text/text.d.ts.map +1 -1
- package/build/renderable/text/textstyle.d.ts +1 -5
- package/build/renderable/text/textstyle.d.ts.map +1 -1
- package/build/renderable/trail.d.ts +0 -29
- package/build/renderable/trail.d.ts.map +1 -1
- package/build/renderable/trigger.d.ts +0 -6
- package/build/renderable/trigger.d.ts.map +1 -1
- package/build/renderable/ui/uibaseelement.d.ts +0 -40
- package/build/renderable/ui/uibaseelement.d.ts.map +1 -1
- package/build/renderable/ui/uispriteelement.d.ts +0 -35
- package/build/renderable/ui/uispriteelement.d.ts.map +1 -1
- package/build/state/stage.d.ts +4 -68
- package/build/state/stage.d.ts.map +1 -1
- package/build/state/state.d.ts.map +1 -1
- package/build/system/device.d.ts +0 -12
- package/build/system/device.d.ts.map +1 -1
- package/build/system/dom.d.ts +1 -8
- package/build/system/dom.d.ts.map +1 -1
- package/build/system/event.d.ts +1 -1
- package/build/system/legacy_pool.d.ts +1 -6
- package/build/system/legacy_pool.d.ts.map +1 -1
- package/build/system/platform.d.ts +21 -2
- package/build/system/platform.d.ts.map +1 -1
- package/build/system/pool.d.ts +0 -9
- package/build/system/pool.d.ts.map +1 -1
- package/build/system/save.d.ts.map +1 -1
- package/build/system/timer.d.ts +0 -20
- package/build/system/timer.d.ts.map +1 -1
- package/build/tweens/tween.d.ts +0 -62
- package/build/tweens/tween.d.ts.map +1 -1
- package/build/utils/array-multimap.d.ts +1 -13
- package/build/utils/array-multimap.d.ts.map +1 -1
- package/build/utils/decode.d.ts.map +1 -1
- package/build/utils/fetchdata.d.ts +2 -0
- package/build/utils/fetchdata.d.ts.map +1 -0
- package/build/utils/utils.d.ts +0 -13
- package/build/utils/utils.d.ts.map +1 -1
- package/build/video/blendmodes.d.ts +1 -106
- package/build/video/blendmodes.d.ts.map +1 -1
- package/build/video/buffer/index.d.ts +1 -39
- package/build/video/buffer/index.d.ts.map +1 -1
- package/build/video/buffer/vertex.d.ts +1 -82
- package/build/video/buffer/vertex.d.ts.map +1 -1
- package/build/video/canvas/canvas_renderer.d.ts +7 -25
- package/build/video/canvas/canvas_renderer.d.ts.map +1 -1
- package/build/video/canvas_factory.d.ts +1 -24
- package/build/video/canvas_factory.d.ts.map +1 -1
- package/build/video/effects/blendEffect.d.ts +0 -54
- package/build/video/effects/blendEffect.d.ts.map +1 -1
- package/build/video/effects/blur.d.ts +4 -4
- package/build/video/effects/blur.d.ts.map +1 -1
- package/build/video/effects/chromaticAberration.d.ts +5 -5
- package/build/video/effects/chromaticAberration.d.ts.map +1 -1
- package/build/video/effects/colorMatrix.d.ts +5 -15
- package/build/video/effects/colorMatrix.d.ts.map +1 -1
- package/build/video/effects/desaturate.d.ts +5 -5
- package/build/video/effects/desaturate.d.ts.map +1 -1
- package/build/video/effects/dissolve.d.ts +4 -4
- package/build/video/effects/dissolve.d.ts.map +1 -1
- package/build/video/effects/dropShadow.d.ts +5 -5
- package/build/video/effects/dropShadow.d.ts.map +1 -1
- package/build/video/effects/flash.d.ts +4 -4
- package/build/video/effects/flash.d.ts.map +1 -1
- package/build/video/effects/glow.d.ts +5 -5
- package/build/video/effects/glow.d.ts.map +1 -1
- package/build/video/effects/glsl_realization.d.ts +1 -17
- package/build/video/effects/glsl_realization.d.ts.map +1 -1
- package/build/video/effects/hologram.d.ts +4 -4
- package/build/video/effects/hologram.d.ts.map +1 -1
- package/build/video/effects/invert.d.ts +5 -5
- package/build/video/effects/invert.d.ts.map +1 -1
- package/build/video/effects/outline.d.ts +6 -6
- package/build/video/effects/outline.d.ts.map +1 -1
- package/build/video/effects/pixelate.d.ts +4 -4
- package/build/video/effects/pixelate.d.ts.map +1 -1
- package/build/video/effects/radialGradient.d.ts +2 -3
- package/build/video/effects/radialGradient.d.ts.map +1 -1
- package/build/video/effects/scanline.d.ts +6 -6
- package/build/video/effects/scanline.d.ts.map +1 -1
- package/build/video/effects/sepia.d.ts +5 -5
- package/build/video/effects/sepia.d.ts.map +1 -1
- package/build/video/effects/shadereffect.d.ts +12 -123
- package/build/video/effects/shadereffect.d.ts.map +1 -1
- package/build/video/effects/shine.d.ts +3 -3
- package/build/video/effects/shine.d.ts.map +1 -1
- package/build/video/effects/tintPulse.d.ts +4 -4
- package/build/video/effects/tintPulse.d.ts.map +1 -1
- package/build/video/effects/vignette.d.ts +6 -6
- package/build/video/effects/vignette.d.ts.map +1 -1
- package/build/video/effects/wave.d.ts +4 -4
- package/build/video/effects/wave.d.ts.map +1 -1
- package/build/video/effects/wgsl/layout.d.ts +1 -27
- package/build/video/effects/wgsl/layout.d.ts.map +1 -1
- package/build/video/effects/wgsl/parse.d.ts +1 -8
- package/build/video/effects/wgsl/parse.d.ts.map +1 -1
- package/build/video/effects/wgsl/scaffold.d.ts +1 -42
- package/build/video/effects/wgsl/scaffold.d.ts.map +1 -1
- package/build/video/effects/wgsl_realization.d.ts +1 -82
- package/build/video/effects/wgsl_realization.d.ts.map +1 -1
- package/build/video/gpu/batcher.d.ts +1 -13
- package/build/video/gpu/batcher.d.ts.map +1 -1
- package/build/video/gpu/instancerecord.d.ts +1 -163
- package/build/video/gpu/instancerecord.d.ts.map +1 -1
- package/build/video/gpu/meshchunk.d.ts +1 -48
- package/build/video/gpu/meshchunk.d.ts.map +1 -1
- package/build/video/gpu/meshvertex.d.ts +1 -53
- package/build/video/gpu/meshvertex.d.ts.map +1 -1
- package/build/video/gpu/primitives.d.ts +1 -59
- package/build/video/gpu/primitives.d.ts.map +1 -1
- package/build/video/gpu/quadcorners.d.ts +1 -10
- package/build/video/gpu/quadcorners.d.ts.map +1 -1
- package/build/video/gpu/textureslots.d.ts +1 -121
- package/build/video/gpu/textureslots.d.ts.map +1 -1
- package/build/video/gpu/texturestore.d.ts +1 -138
- package/build/video/gpu/texturestore.d.ts.map +1 -1
- package/build/video/gpu/topology.d.ts.map +1 -1
- package/build/video/gpu/vertexformat.d.ts +0 -28
- package/build/video/gpu/vertexformat.d.ts.map +1 -1
- package/build/video/gradient.d.ts +0 -81
- package/build/video/gradient.d.ts.map +1 -1
- package/build/video/renderer.d.ts +21 -102
- package/build/video/renderer.d.ts.map +1 -1
- package/build/video/renderstate.d.ts +0 -51
- package/build/video/renderstate.d.ts.map +1 -1
- package/build/video/rendertarget/canvasrendertarget.d.ts +0 -10
- package/build/video/rendertarget/canvasrendertarget.d.ts.map +1 -1
- package/build/video/rendertarget/render_target_pool.d.ts +1 -82
- package/build/video/rendertarget/render_target_pool.d.ts.map +1 -1
- package/build/video/rendertarget/webglrendertarget.d.ts +1 -64
- package/build/video/rendertarget/webglrendertarget.d.ts.map +1 -1
- package/build/video/rendertarget/webgpurendertarget.d.ts +0 -8
- package/build/video/rendertarget/webgpurendertarget.d.ts.map +1 -1
- package/build/video/texture/atlas.d.ts +2 -76
- package/build/video/texture/atlas.d.ts.map +1 -1
- package/build/video/texture/cache.d.ts +0 -136
- package/build/video/texture/cache.d.ts.map +1 -1
- package/build/video/texture/frametexture.d.ts +1 -71
- package/build/video/texture/frametexture.d.ts.map +1 -1
- package/build/video/texture/noise_texture2d.d.ts +0 -43
- package/build/video/texture/noise_texture2d.d.ts.map +1 -1
- package/build/video/texture/parser/aseprite.d.ts +1 -8
- package/build/video/texture/parser/aseprite.d.ts.map +1 -1
- package/build/video/texture/parser/spritesheet.d.ts +1 -8
- package/build/video/texture/parser/spritesheet.d.ts.map +1 -1
- package/build/video/texture/parser/texturepacker.d.ts +1 -8
- package/build/video/texture/parser/texturepacker.d.ts.map +1 -1
- package/build/video/texture/resource.d.ts +0 -9
- package/build/video/texture/resource.d.ts.map +1 -1
- package/build/video/texture/texture2d.d.ts +0 -11
- package/build/video/texture/texture2d.d.ts.map +1 -1
- package/build/video/utils/autodetect.d.ts +1 -5
- package/build/video/utils/autodetect.d.ts.map +1 -1
- package/build/video/webgl/batchers/batcher.d.ts +0 -55
- package/build/video/webgl/batchers/batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/lit_mesh_batcher.d.ts +0 -14
- package/build/video/webgl/batchers/lit_mesh_batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/lit_quad_batcher.d.ts +0 -72
- package/build/video/webgl/batchers/lit_quad_batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/material_batcher.d.ts +0 -89
- package/build/video/webgl/batchers/material_batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/mesh_batcher.d.ts +14 -343
- package/build/video/webgl/batchers/mesh_batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/primitive_batcher.d.ts +0 -10
- package/build/video/webgl/batchers/primitive_batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/quad_batcher.d.ts +0 -30
- package/build/video/webgl/batchers/quad_batcher.d.ts.map +1 -1
- package/build/video/webgl/buffer/index.d.ts +1 -36
- package/build/video/webgl/buffer/index.d.ts.map +1 -1
- package/build/video/webgl/buffer/instance_buffer.d.ts +1 -53
- package/build/video/webgl/buffer/instance_buffer.d.ts.map +1 -1
- package/build/video/webgl/buffer/retained_geometry.d.ts +1 -81
- package/build/video/webgl/buffer/retained_geometry.d.ts.map +1 -1
- package/build/video/webgl/buffer/uniformblock.d.ts +1 -80
- package/build/video/webgl/buffer/uniformblock.d.ts.map +1 -1
- package/build/video/webgl/buffer/vertexstate.d.ts +1 -100
- package/build/video/webgl/buffer/vertexstate.d.ts.map +1 -1
- package/build/video/webgl/glshader.d.ts +2 -51
- package/build/video/webgl/glshader.d.ts.map +1 -1
- package/build/video/webgl/lighting/pack3d.d.ts +1 -47
- package/build/video/webgl/lighting/pack3d.d.ts.map +1 -1
- package/build/video/webgl/lighting/std140.d.ts +1 -109
- package/build/video/webgl/lighting/std140.d.ts.map +1 -1
- package/build/video/webgl/renderers/tmxlayer/orthogonal.d.ts +1 -103
- package/build/video/webgl/renderers/tmxlayer/orthogonal.d.ts.map +1 -1
- package/build/video/webgl/shaders/multitexture-lit.d.ts +1 -26
- package/build/video/webgl/shaders/multitexture-lit.d.ts.map +1 -1
- package/build/video/webgl/shaders/multitexture.d.ts +1 -9
- package/build/video/webgl/shaders/multitexture.d.ts.map +1 -1
- package/build/video/webgl/texture/store.d.ts +1 -50
- package/build/video/webgl/texture/store.d.ts.map +1 -1
- package/build/video/webgl/utils/attributes.d.ts +1 -11
- package/build/video/webgl/utils/attributes.d.ts.map +1 -1
- package/build/video/webgl/utils/maxtextures.d.ts +1 -36
- package/build/video/webgl/utils/maxtextures.d.ts.map +1 -1
- package/build/video/webgl/utils/precision.d.ts +1 -14
- package/build/video/webgl/utils/precision.d.ts.map +1 -1
- package/build/video/webgl/utils/program.d.ts +1 -5
- package/build/video/webgl/utils/program.d.ts.map +1 -1
- package/build/video/webgl/utils/samplercache.d.ts +1 -68
- package/build/video/webgl/utils/samplercache.d.ts.map +1 -1
- package/build/video/webgl/utils/string.d.ts +1 -21
- package/build/video/webgl/utils/string.d.ts.map +1 -1
- package/build/video/webgl/utils/topology.d.ts +1 -23
- package/build/video/webgl/utils/topology.d.ts.map +1 -1
- package/build/video/webgl/utils/uniforms.d.ts +1 -25
- package/build/video/webgl/utils/uniforms.d.ts.map +1 -1
- package/build/video/webgl/utils/vertexformat.d.ts +1 -26
- package/build/video/webgl/utils/vertexformat.d.ts.map +1 -1
- package/build/video/webgl/webgl_renderer.d.ts +24 -286
- package/build/video/webgl/webgl_renderer.d.ts.map +1 -1
- package/build/video/webgpu/batchers/lit_mesh_batcher.d.ts +0 -6
- package/build/video/webgpu/batchers/lit_mesh_batcher.d.ts.map +1 -1
- package/build/video/webgpu/batchers/lit_quad_batcher.d.ts +0 -8
- package/build/video/webgpu/batchers/lit_quad_batcher.d.ts.map +1 -1
- package/build/video/webgpu/batchers/mesh_batcher.d.ts +1 -230
- package/build/video/webgpu/batchers/mesh_batcher.d.ts.map +1 -1
- package/build/video/webgpu/batchers/primitive_batcher.d.ts.map +1 -1
- package/build/video/webgpu/batchers/quad_batcher.d.ts +0 -82
- package/build/video/webgpu/batchers/quad_batcher.d.ts.map +1 -1
- package/build/video/webgpu/buffer/arena.d.ts +1 -63
- package/build/video/webgpu/buffer/arena.d.ts.map +1 -1
- package/build/video/webgpu/buffer/instance_buffer.d.ts +1 -64
- package/build/video/webgpu/buffer/instance_buffer.d.ts.map +1 -1
- package/build/video/webgpu/buffer/retained_geometry.d.ts +1 -54
- package/build/video/webgpu/buffer/retained_geometry.d.ts.map +1 -1
- package/build/video/webgpu/buffer/uniformring.d.ts +1 -67
- package/build/video/webgpu/buffer/uniformring.d.ts.map +1 -1
- package/build/video/webgpu/effect_binding.d.ts +1 -16
- package/build/video/webgpu/effect_binding.d.ts.map +1 -1
- package/build/video/webgpu/pipeline/bindgroups.d.ts +1 -32
- package/build/video/webgpu/pipeline/bindgroups.d.ts.map +1 -1
- package/build/video/webgpu/pipeline/cache.d.ts +1 -163
- package/build/video/webgpu/pipeline/cache.d.ts.map +1 -1
- package/build/video/webgpu/renderers/tmxlayer/orthogonal.d.ts +1 -87
- package/build/video/webgpu/renderers/tmxlayer/orthogonal.d.ts.map +1 -1
- package/build/video/webgpu/shaders/mesh-instanced.d.ts +1 -43
- package/build/video/webgpu/shaders/mesh-instanced.d.ts.map +1 -1
- package/build/video/webgpu/texture/compressed.d.ts +1 -32
- package/build/video/webgpu/texture/compressed.d.ts.map +1 -1
- package/build/video/webgpu/texture/frametexture.d.ts +1 -62
- package/build/video/webgpu/texture/frametexture.d.ts.map +1 -1
- package/build/video/webgpu/texture/store.d.ts +1 -147
- package/build/video/webgpu/texture/store.d.ts.map +1 -1
- package/build/video/webgpu/webgpu_renderer.d.ts +2 -89
- package/build/video/webgpu/webgpu_renderer.d.ts.map +1 -1
- package/package.json +8 -11
- package/skills/AGENTS.md +67 -0
- package/skills/melonjs/SKILL.md +156 -0
- package/skills/melonjs-20-migration/SKILL.md +160 -0
- package/skills/melonjs-3d/SKILL.md +525 -0
- package/skills/melonjs-3d-assets/SKILL.md +258 -0
- package/skills/melonjs-audio/SKILL.md +236 -0
- package/skills/melonjs-camera-and-drawing/SKILL.md +175 -0
- package/skills/melonjs-deployment/SKILL.md +113 -0
- package/skills/melonjs-effects-and-shaders/SKILL.md +178 -0
- package/skills/melonjs-events/SKILL.md +159 -0
- package/skills/melonjs-getting-started/SKILL.md +183 -0
- package/skills/melonjs-input/SKILL.md +166 -0
- package/skills/melonjs-lighting/SKILL.md +139 -0
- package/skills/melonjs-loading-assets/SKILL.md +186 -0
- package/skills/melonjs-particles-and-trails/SKILL.md +136 -0
- package/skills/melonjs-performance/SKILL.md +183 -0
- package/skills/melonjs-physics/SKILL.md +321 -0
- package/skills/melonjs-plugins/SKILL.md +191 -0
- package/skills/melonjs-renderables/SKILL.md +214 -0
- package/skills/melonjs-renderer-backends/SKILL.md +173 -0
- package/skills/melonjs-scenes-and-state/SKILL.md +180 -0
- package/skills/melonjs-sprites-and-animation/SKILL.md +173 -0
- package/skills/melonjs-tilemaps/SKILL.md +213 -0
- package/skills/melonjs-ui-and-text/SKILL.md +65 -0
- package/build/audio/backend.d.ts +0 -140
- package/build/audio/backend.d.ts.map +0 -1
- package/build/loader/parsers/fetchdata.d.ts +0 -32
- package/build/loader/parsers/fetchdata.d.ts.map +0 -1
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: melonjs-3d-assets
|
|
3
|
+
description: "Use this skill when loading 3D models into melonJS — glTF and GLB scenes, OBJ/MTL models, materials, imported lights, node animation, ground shadows and GPU instancing. Covers level.load options including the async flag, the rightHanded conversion, and exactly what the loader does and does not support. Triggers on: glTF, gltf, glb, OBJ, MTL, 3D model, getGLTF, getOBJ, getMTL, GLTFModel, GLTFScene, level.load glb, rightHanded, lightIntensityScale, castGroundShadow, shadowGroundY, EXT_mesh_gpu_instancing, KHR_lights_punctual, skinning, Blender export, 3D asset."
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Loading 3D assets
|
|
8
|
+
|
|
9
|
+
> glTF/GLB is the primary path for 3D content, and it goes through the **level
|
|
10
|
+
> director** rather than the world directly: `level.load("scene")`, the same call
|
|
11
|
+
> a Tiled map uses. OBJ/MTL is the simpler path for a single static model.
|
|
12
|
+
|
|
13
|
+
## Loading a glTF/GLB scene
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
await loader.preload([
|
|
17
|
+
{ name: "diorama", type: "glb", src: "data/scenes/diorama.glb" },
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
level.load("diorama", { scale: 50 });
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`type: "gltf"` (JSON plus external buffers) and `type: "glb"` (single binary)
|
|
24
|
+
are both loader types. A self-contained GLB is the better shipping format — one
|
|
25
|
+
request, nothing to resolve relatively.
|
|
26
|
+
|
|
27
|
+
The scene loads under whatever camera the stage has; view it under a `Camera3d`
|
|
28
|
+
or it renders flat. See `melonjs-3d` for the camera.
|
|
29
|
+
|
|
30
|
+
### `level.load` options for glTF/GLB
|
|
31
|
+
|
|
32
|
+
| option | default | what it does |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `scale` | `1` | pixels per glTF unit, applied to the whole scene. Blender's metre-scale export usually needs 20–100. |
|
|
35
|
+
| `container` | `game.world` | where the nodes are added |
|
|
36
|
+
| `onLoaded` | `app.onLevelLoaded` | called with the **level id**, not the scene |
|
|
37
|
+
| `async` | `false` | return a promise that settles once the scene is in the world, instead of a boolean |
|
|
38
|
+
| `rightHanded` | `true` | see below |
|
|
39
|
+
| `lights` | `true` | instantiate authored `KHR_lights_punctual` lights as `Light3d` world children |
|
|
40
|
+
| `lightIntensityScale` | — | keep authored intensity ratios instead of normalising every light to 1 |
|
|
41
|
+
| `castGroundShadow` | inherits the app setting (**on**) | blob shadows for this scene's meshes |
|
|
42
|
+
| `shadowGroundY` | each object's own base | world Y of the floor the blobs land on |
|
|
43
|
+
|
|
44
|
+
`onLoaded` receives the level id — it is a "done" signal, not a handle on the
|
|
45
|
+
scene. You need it, or `async`: with the game loop running, `level.load` stops
|
|
46
|
+
the loop and defers the actual load to a timer, so by default it returns
|
|
47
|
+
*before* anything is in the world.
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
await level.load("diorama", { scale: 50, async: true });
|
|
51
|
+
// the scene is in the world here
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Note `await level.load("diorama")` without the flag does not await the load — the
|
|
55
|
+
call returns a boolean, and `await true` resolves immediately. To get at what was
|
|
56
|
+
loaded, load into a container you own, or look the nodes up by their authored
|
|
57
|
+
names:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
level.load("diorama", { scale: 50, onLoaded: () => {
|
|
61
|
+
const sun = app.world.getChildByName("Sun")[0]; // note: returns an array
|
|
62
|
+
sun.intensity = 2;
|
|
63
|
+
}});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## `rightHanded` — and the default that differs between the two APIs
|
|
67
|
+
|
|
68
|
+
glTF is authored **Y-up, right-handed**; melonJS is **Y-down, +Z forward**.
|
|
69
|
+
There are two ways to bridge that, and they are not equivalent:
|
|
70
|
+
|
|
71
|
+
- a **rotation** — preserves chirality, matches the authoring tool
|
|
72
|
+
- a **mirror** (negate Y only) — flips the scene left/right
|
|
73
|
+
|
|
74
|
+
`level.load` defaults `rightHanded: true`, so a scene loaded through the level
|
|
75
|
+
director comes in correctly. **The `Mesh` constructor defaults it to `false`**,
|
|
76
|
+
so glTF or OBJ geometry you feed to a `Mesh` yourself comes in mirrored unless
|
|
77
|
+
you pass `rightHanded: true`. A model that is subtly wrong — text backwards, a
|
|
78
|
+
character's gear on the wrong side — is this and nothing else.
|
|
79
|
+
|
|
80
|
+
Do not add a flip of your own on top; two corrections cancel back to wrong.
|
|
81
|
+
|
|
82
|
+
## Materials — what actually arrives
|
|
83
|
+
|
|
84
|
+
The importer covers a deliberate subset:
|
|
85
|
+
|
|
86
|
+
- `pbrMetallicRoughness` **base colour texture and factor**
|
|
87
|
+
- metallic/roughness **factors** converted to the engine's specular model
|
|
88
|
+
- `emissiveFactor`, including `KHR_materials_emissive_strength`
|
|
89
|
+
- `KHR_materials_unlit` — honoured, for baked/stylised workflows
|
|
90
|
+
- `alphaMode: "MASK"` — the cutout threshold is applied
|
|
91
|
+
- `doubleSided`
|
|
92
|
+
|
|
93
|
+
Not imported: **normal maps**, metallic/roughness *textures*, occlusion maps,
|
|
94
|
+
morph targets, `KHR_texture_transform`. Nothing errors — the material simply
|
|
95
|
+
arrives without them, which reads as "flatter than the preview in my authoring
|
|
96
|
+
tool". Bake what you need into the base colour.
|
|
97
|
+
|
|
98
|
+
**Draco compression is the exception that does error.** Its geometry sits in
|
|
99
|
+
accessors with no buffer view, which the parser rejects outright, so the whole
|
|
100
|
+
asset fails to load. Export uncompressed.
|
|
101
|
+
|
|
102
|
+
`textureFilter` on the Application settings (`"nearest"` / `"linear"` /
|
|
103
|
+
`"auto"`) drives sampling; glTF materials that declare their own sampler carry
|
|
104
|
+
it through. Pixel-art models want `"nearest"`.
|
|
105
|
+
|
|
106
|
+
## Lights
|
|
107
|
+
|
|
108
|
+
Authored `KHR_lights_punctual` lights — sun, point, spot — become `Light3d`
|
|
109
|
+
world children, plus a soft ambient fill, and each keeps its authored name.
|
|
110
|
+
A scene carrying any of them renders through the **lit** path automatically.
|
|
111
|
+
|
|
112
|
+
glTF stores physical units — lux for suns, candela for lamps — and a Blender
|
|
113
|
+
daylight sun is 1000+, which blows out the engine's stylised shading. So every
|
|
114
|
+
light is normalised to intensity 1 by default. To keep the *ratios* the artist
|
|
115
|
+
set, scale instead of normalising:
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
// a 1000-lux sun lands at 1, a 500-lux fill lands at 0.5
|
|
119
|
+
level.load("diorama", { scale: 50, lightIntensityScale: 0.001 });
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Pass `lights: false` to manage lighting yourself.
|
|
123
|
+
|
|
124
|
+
## Animation
|
|
125
|
+
|
|
126
|
+
Node-TRS animation **is** supported: translation, rotation and scale channels,
|
|
127
|
+
the rigid hierarchical animation used by blocky/low-poly character packs. An
|
|
128
|
+
animated asset instantiates as a single `GLTFModel` keeping the node hierarchy
|
|
129
|
+
intact, with an API deliberately mirroring `Sprite`. The model carries the asset
|
|
130
|
+
name, which is how you get hold of it after loading:
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
const model = app.world.getChildByName("hero")[0]; // the GLTFModel
|
|
134
|
+
|
|
135
|
+
model.getAnimationNames(); // ["idle", "walk", ...]
|
|
136
|
+
model.setCurrentAnimation("walk", { loop: true, speed: 1, onComplete });
|
|
137
|
+
model.setCurrentAnimation("jump", { next: "idle" }); // chain
|
|
138
|
+
model.isCurrentAnimation("walk");
|
|
139
|
+
model.play();
|
|
140
|
+
model.pause();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`speed` is a playback multiplier (1 = authored speed), not a frame delay. Only
|
|
144
|
+
an explicit `loop: false` stops looping. `setCurrentAnimation` **throws** on a
|
|
145
|
+
clip name the asset does not define — check `getAnimationNames()` first.
|
|
146
|
+
|
|
147
|
+
**Vertex skinning is out of scope** — `JOINTS_0` / `WEIGHTS_0` are not read, and
|
|
148
|
+
neither are morph targets. A smoothly-deforming character will not deform. The
|
|
149
|
+
options are: rig it hierarchically instead (separate meshes parented into a
|
|
150
|
+
node tree), use `Sprite3d` billboards, or use the Spine plugin for 2D skeletal
|
|
151
|
+
work.
|
|
152
|
+
|
|
153
|
+
## Instancing
|
|
154
|
+
|
|
155
|
+
A node using `EXT_mesh_gpu_instancing` loads as an `InstancedMesh` — one draw
|
|
156
|
+
call for every copy, which is the difference between a hundred trees and a
|
|
157
|
+
hundred thousand. Export with instancing enabled where your tool supports it.
|
|
158
|
+
Sparse accessors on the instancing attributes are rejected with a clear error
|
|
159
|
+
rather than silently misplacing every instance.
|
|
160
|
+
|
|
161
|
+
## Ground shadows
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
level.load("diorama", { scale: 50, castGroundShadow: true, shadowGroundY: 0 });
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`castGroundShadow` is tri-state: set it and it overrides the application setting
|
|
168
|
+
for this scene in both directions; omit it and the scene inherits — and that
|
|
169
|
+
setting is `true` by default, so shadows are already on. As a scene-wide opt-in
|
|
170
|
+
it skips nodes with no vertical extent — a ground plane is exactly that, and
|
|
171
|
+
shadowing it with itself smears a blob across the whole floor. Blob shadows need
|
|
172
|
+
a GPU backend and a `Camera3d`; nothing is drawn on the 2D-camera or Canvas
|
|
173
|
+
paths.
|
|
174
|
+
|
|
175
|
+
Omit `shadowGroundY` and each blob sits at its own object's base at full
|
|
176
|
+
strength, which is right for props already resting on the ground. Set it when
|
|
177
|
+
things jump or fly, so the shadow stays on the floor and shrinks with height.
|
|
178
|
+
|
|
179
|
+
A blob is centred on its caster's x/z and is never offset by light direction, so
|
|
180
|
+
a wide flat-bottomed prop hides its own shadow under itself. Raising
|
|
181
|
+
`shadowGroundY` to force one into view floats the blob up over the object as a
|
|
182
|
+
dark ring rather than sliding it clear — the setting is for things that leave
|
|
183
|
+
the ground, not a visibility knob.
|
|
184
|
+
|
|
185
|
+
## OBJ/MTL
|
|
186
|
+
|
|
187
|
+
A different shape entirely: OBJ produces raw geometry you hand to a `Mesh`,
|
|
188
|
+
not a scene. Preload the two files and name them in the `Mesh` settings — the
|
|
189
|
+
`model` and `material` names are independent, the same name for both is just a
|
|
190
|
+
convention:
|
|
191
|
+
|
|
192
|
+
```js
|
|
193
|
+
await loader.preload([
|
|
194
|
+
{ name: "fox", type: "obj", src: "models/fox.obj" },
|
|
195
|
+
{ name: "fox", type: "mtl", src: "models/fox.mtl" },
|
|
196
|
+
]);
|
|
197
|
+
|
|
198
|
+
const mesh = new Mesh(400, 300, {
|
|
199
|
+
model: "fox",
|
|
200
|
+
material: "fox", // texture resolved from the material's map_Kd
|
|
201
|
+
width: 200,
|
|
202
|
+
height: 200,
|
|
203
|
+
rightHanded: true, // the Mesh default is false — see above
|
|
204
|
+
});
|
|
205
|
+
world.addChild(mesh);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**The MTL loader fetches the textures it references itself** — `map_Kd` and
|
|
209
|
+
`map_d` are resolved relative to the `.mtl` and preloaded for you, so there is
|
|
210
|
+
no image entry in the manifest above. Passing `texture:` explicitly overrides
|
|
211
|
+
that and pins *one* binding over the whole model, which on a multi-material
|
|
212
|
+
model suppresses the per-material texture split; leave it out unless you mean
|
|
213
|
+
that.
|
|
214
|
+
|
|
215
|
+
MTL contributes `Kd` (diffuse tint), `d` / `Tr` (opacity), `Ke` (emissive),
|
|
216
|
+
`Ks` + `Ns` (specular highlight), `map_Kd` (diffuse texture) and `map_d`
|
|
217
|
+
(per-texel opacity). Normal and specular *maps* are not supported.
|
|
218
|
+
`loader.getOBJ(name)` and `loader.getMTL(name)` return the parsed data if you
|
|
219
|
+
want it directly. OBJ has no scene graph, no lights, no animation — use glTF for
|
|
220
|
+
anything beyond a single static model.
|
|
221
|
+
|
|
222
|
+
## Packaging
|
|
223
|
+
|
|
224
|
+
A self-contained GLB is one file with nothing to resolve — the safest thing to
|
|
225
|
+
ship. External references still work in both formats: `.bin` buffers and image
|
|
226
|
+
`uri`s are resolved **relative to the asset's own URL** (a GLB with an external
|
|
227
|
+
texture loads as-shipped). But an external file that 404s rejects the parse, so
|
|
228
|
+
the whole asset fails to load rather than arriving partially — no untextured
|
|
229
|
+
fallback. Note that `loader.setBaseURL("*", …)` deliberately skips `gltf`,
|
|
230
|
+
`glb`, `obj` and `mtl` for this reason; set those types individually if you
|
|
231
|
+
need a prefix.
|
|
232
|
+
|
|
233
|
+
## Symptom → cause
|
|
234
|
+
|
|
235
|
+
| symptom | cause |
|
|
236
|
+
|---|---|
|
|
237
|
+
| model mirrored — text backwards, gear on the wrong side | `Mesh` defaults `rightHanded` to `false`; pass `true` |
|
|
238
|
+
| model upside down | a manual axis flip on top of the loader's conversion |
|
|
239
|
+
| scene is enormous or invisibly small | `scale` left at 1 against a metre-scale export |
|
|
240
|
+
| the asset fails to load entirely | an external buffer/image `uri` that 404s, or Draco-compressed geometry |
|
|
241
|
+
| everything is blown out white | authored lux/candela intensities; use `lightIntensityScale` |
|
|
242
|
+
| materials flatter than the authoring-tool preview | no normal or metallic/roughness *textures* are imported |
|
|
243
|
+
| a character does not deform | vertex skinning is out of scope; rig hierarchically or billboard |
|
|
244
|
+
| animation names come back empty | the asset has no node-TRS channels (skin-only rig) |
|
|
245
|
+
| a hundred copies tank the frame rate | exported without `EXT_mesh_gpu_instancing` |
|
|
246
|
+
| a prop casts no visible shadow | wide and flat-bottomed — the blob is under it; `shadowGroundY` haloes it rather than revealing it |
|
|
247
|
+
| a shadow smeared across the whole floor | a ground plane cast its own blob — use the scene-wide opt-in |
|
|
248
|
+
| `onLoaded` gets a string, not the scene | it is called with the level id; load into your own container instead |
|
|
249
|
+
| scene renders flat and unlit | no `Camera3d` — the 2D-camera path is CPU-projected and unlit (with a `Camera3d` on Canvas you get a black canvas instead) |
|
|
250
|
+
|
|
251
|
+
## Related skills
|
|
252
|
+
|
|
253
|
+
- `melonjs-3d` — conventions, `Camera3d`, meshes, `Light3d`, instancing, and
|
|
254
|
+
`camera.setFog` (an outdoor scene almost always wants it; it is set on the
|
|
255
|
+
camera, so a loaded scene needs no per-node work)
|
|
256
|
+
- `melonjs-lighting` — how `Light3d` behaves once imported
|
|
257
|
+
- `melonjs-loading-assets` — the loader, asset types and base URLs
|
|
258
|
+
- `melonjs-plugins` — the Spine plugin, for skeletal characters
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: melonjs-audio
|
|
3
|
+
description: "Use this skill for sound and music in melonJS — loading audio, playing effects, background tracks, audio sprites, volume and muting, spatial audio, and procedural tone/noise generation. Covers the mandatory audio.init format list, the directory-not-file src convention, playTrack versus play, and browser autoplay unlocking. Triggers on: audio, sound, audio.init, audio.play, playTrack, stopTrack, audio.load, sfx, music, volume, mute, sprite audio, stereo, panner, audio.tone, audio.noise, getAudioContext, autoplay."
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Audio
|
|
8
|
+
|
|
9
|
+
## Two setup rules
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { audio, loader } from "melonjs";
|
|
13
|
+
|
|
14
|
+
audio.init("mp3,ogg"); // 1. BEFORE preloading any audio
|
|
15
|
+
|
|
16
|
+
await loader.preload([
|
|
17
|
+
{ name: "cling", type: "audio", src: "data/sfx/" }, // 2. a PREFIX, not a file
|
|
18
|
+
]);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
1. **`audio.init(format)` must run before any audio asset is preloaded**, and
|
|
22
|
+
lists the formats you actually ship. Preloading first throws
|
|
23
|
+
`target audio extension(s) should be set through me.audio.init() before
|
|
24
|
+
calling the preloader.` It returns `false` when no audio backend is
|
|
25
|
+
available, so it is worth checking. The format list defaults to `"mp3"`.
|
|
26
|
+
2. **`src` is a prefix, not a file.** The loader appends the asset `name` plus
|
|
27
|
+
each configured extension and uses the first that loads — so
|
|
28
|
+
`data/sfx/` + `cling` + `mp3` → `data/sfx/cling.mp3`. Passing a full filename
|
|
29
|
+
gives you a 404. A `data:audio/...` URL is the one exception: it is used
|
|
30
|
+
verbatim, prefix and extension skipped.
|
|
31
|
+
|
|
32
|
+
Order matters — melonJS tries the listed formats left to right, so put the
|
|
33
|
+
preferred one first. Two formats (`"webm,mp3"` or `"mp3,ogg"`) is the usual
|
|
34
|
+
belt-and-braces for codec coverage. Accepted tokens: `mp3`, `mpeg`, `opus`,
|
|
35
|
+
`ogg`, `oga`, `wav`, `aac`, `caf`, `m4a`, `m4b`, `mp4`, `weba`, `webm`, `dolby`,
|
|
36
|
+
`flac`.
|
|
37
|
+
|
|
38
|
+
## Effects versus music
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
audio.play("cling"); // fire and forget
|
|
42
|
+
audio.play("cling", false, null, 0.5); // loop, onend, volume
|
|
43
|
+
const id = audio.play("engine", true); // looping; keep the id to stop it
|
|
44
|
+
|
|
45
|
+
audio.playTrack("theme"); // background music
|
|
46
|
+
audio.stopTrack();
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Use **`playTrack`** for music, not `play`. `playTrack(name, volume?)` always
|
|
50
|
+
loops, and it records the name as the current track — which is what
|
|
51
|
+
`app.pauseOnBlur` / `resumeOnFocus` / `stopOnBlur` act on, via
|
|
52
|
+
`state.pause(true)` → `pauseTrack()`. `stopTrack()`, `pauseTrack()`,
|
|
53
|
+
`resumeTrack()` and `getCurrentTrack()` all read that same single slot, so there
|
|
54
|
+
is only ever one current track. Stop it in `onDestroyEvent`.
|
|
55
|
+
|
|
56
|
+
Every per-clip function throws `audio clip <name> does not exist` if the clip was
|
|
57
|
+
never loaded, and `play` additionally throws when a named sprite region is
|
|
58
|
+
missing.
|
|
59
|
+
|
|
60
|
+
## Audio sprites
|
|
61
|
+
|
|
62
|
+
One file carrying many effects, with named regions in milliseconds:
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
await loader.preload([{
|
|
66
|
+
name: "sfx", type: "audio", src: "data/sfx/",
|
|
67
|
+
sprite: { jump: [0, 450], hit: [2000, 250], music: [4000, 12000, true] },
|
|
68
|
+
}]);
|
|
69
|
+
|
|
70
|
+
audio.play("sfx", { sprite: "jump" });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The optional third element marks a region as looping. `play()`'s second argument
|
|
74
|
+
takes either the original `loop` boolean or a `PlayOptions` object
|
|
75
|
+
(`sprite`, `loop`, `onend`, `volume`) — both forms work. Object fields win over
|
|
76
|
+
the positional `onend` / `volume` arguments when both are supplied.
|
|
77
|
+
|
|
78
|
+
## Clip state
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
audio.duration("theme"); // seconds — 0 while still loading
|
|
82
|
+
audio.duration("sfx", id); // duration of the region THAT instance plays
|
|
83
|
+
audio.playing("theme"); // is anything playing?
|
|
84
|
+
audio.playing("theme", id); // is that instance playing?
|
|
85
|
+
audio.state("theme"); // "unloaded" | "loading" | "loaded"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`stop()`, `pause()` and `resume()` take an optional instance `id` too; omit it
|
|
89
|
+
and the whole group is affected. `audio.stop()` with no arguments at all stops
|
|
90
|
+
every sound. `audio.seek(name)` reads the position, `audio.seek(name, s, id?)`
|
|
91
|
+
writes it; `audio.rate` and `audio.fade(name, from, to, ms, id?)` round it out.
|
|
92
|
+
|
|
93
|
+
## Volume and muting
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
audio.setVolume(0.5); // global, 0..1
|
|
97
|
+
audio.getVolume(); // read it back
|
|
98
|
+
audio.mute("cling"); // one clip — mute(name, id?, shouldMute = true)
|
|
99
|
+
audio.unmute("cling");
|
|
100
|
+
audio.muteAll(); // everything (audio.disable() is an alias)
|
|
101
|
+
audio.unmuteAll(); // (audio.enable() is an alias)
|
|
102
|
+
audio.muted(); // global mute state
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`audio.unload(name)` / `audio.unloadAll()` free the decoded buffers; `unload`
|
|
106
|
+
also clears the current-track pointer if it named that clip.
|
|
107
|
+
|
|
108
|
+
## Spatial audio
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
audio.position("engine", x, y, z);
|
|
112
|
+
audio.orientation("engine", x, y, z);
|
|
113
|
+
audio.stereo("engine", -1); // -1 left … 1 right
|
|
114
|
+
audio.panner("engine", { coneInnerAngle: 90, /* … */ });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`position(name, x, y = 0, z = -0.5, id?)` and
|
|
118
|
+
`orientation(name, x, y, z, id?)` both default `id` to "the whole group".
|
|
119
|
+
Called with just the clip name, each of the four returns the current value —
|
|
120
|
+
`stereo` gives `0` and `position` gives `[0, 0, 0]` before they have ever been
|
|
121
|
+
set.
|
|
122
|
+
|
|
123
|
+
**Spatial audio is WebAudio-only.** On a clip loaded with `stream: true` (or
|
|
124
|
+
`html5: true`) `stereo` / `position` / `orientation` return early and do
|
|
125
|
+
nothing — which is exactly the case for the long music tracks people reach for
|
|
126
|
+
first.
|
|
127
|
+
|
|
128
|
+
## Procedural sound
|
|
129
|
+
|
|
130
|
+
For beeps, blips and noise without shipping files. Both take **one options
|
|
131
|
+
object**, and `duration` (in seconds) is required:
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
audio.tone({ freq: 440, duration: 0.2, gain: 0.3, pan: -0.5 });
|
|
135
|
+
audio.tone({ freq: [440, 660, 880], duration: 0.4 }); // layered partials
|
|
136
|
+
audio.noise({ duration: 0.5, filter: { type: "lowpass", frequency: 800 } });
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`tone` also takes `wave` (default `"sine"`), `attack` (`0.005`) and `pitchSlide`
|
|
140
|
+
(`1`). `noise` takes `type` (`"white"` | `"pink"` | `"brown"`, default
|
|
141
|
+
`"white"`), `attack`, `pan`, `filter` and `filterSweep`. `gain` defaults to `0.1`
|
|
142
|
+
on both.
|
|
143
|
+
|
|
144
|
+
Both are **silent no-ops** when there is no WebAudio context — they bail on
|
|
145
|
+
`getAudioContext() === null` rather than throwing. Neither needs the clip to be
|
|
146
|
+
loaded; neither goes through the file-playback path at all.
|
|
147
|
+
|
|
148
|
+
`audio.getAudioContext()` and `audio.getMasterGain()` are the escape hatches for
|
|
149
|
+
custom Web Audio work; both return `null` when audio is unavailable, so guard.
|
|
150
|
+
Connect a custom graph to the master gain rather than `ctx.destination` if you
|
|
151
|
+
want it to respect `setVolume` / `muteAll`.
|
|
152
|
+
|
|
153
|
+
## Autoplay: sound is silent until the first gesture
|
|
154
|
+
|
|
155
|
+
Browsers create the audio context in the `suspended` state and keep it there
|
|
156
|
+
until a user interaction. Nothing errors — audio simply does not play, which
|
|
157
|
+
reads as a bug. melonJS installs one-shot `touchstart` / `touchend` / `click` /
|
|
158
|
+
`keydown` unlock listeners on `document`, so the first real gesture anywhere
|
|
159
|
+
unlocks it and fires the clip's `on.unlock` callback. Design for it: start music
|
|
160
|
+
on the first click or key press, not on load. `tone` / `noise` additionally call
|
|
161
|
+
`ctx.resume()` themselves, best-effort, on every invocation.
|
|
162
|
+
|
|
163
|
+
Playback also starts **asynchronously**: `play()` returns an id while the
|
|
164
|
+
instance is still starting, so `playing()` can legitimately be `false` on the
|
|
165
|
+
very next line.
|
|
166
|
+
|
|
167
|
+
## Load-time options
|
|
168
|
+
|
|
169
|
+
```js
|
|
170
|
+
{ name: "sfx", type: "audio", src: "data/sfx/",
|
|
171
|
+
sprite: { jump: [0, 450] },
|
|
172
|
+
pool: 5, // finished instances kept for reuse — NOT a concurrency cap
|
|
173
|
+
rate: 1.0, // initial playback rate, 0.5..4.0
|
|
174
|
+
mute: false,
|
|
175
|
+
loop: false,
|
|
176
|
+
autoplay: false,
|
|
177
|
+
preload: true, // or "metadata"
|
|
178
|
+
format: "mp3", // explicit hint when the URL has no usable extension
|
|
179
|
+
stream: true, // long music: stream rather than decode into memory
|
|
180
|
+
on: { play() {}, end() {}, stop() {}, unlock() {} },
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`pool` (default `5`) is a **reuse cap on finished voices**, not a limit on
|
|
185
|
+
simultaneous playback: when the number of ended voices exceeds it, the surplus
|
|
186
|
+
are disconnected and dropped. Raise it for a clip triggered in rapid bursts, not
|
|
187
|
+
to allow more overlap.
|
|
188
|
+
|
|
189
|
+
Use `stream: true` for long music tracks — it plays through an HTML5 `<audio>`
|
|
190
|
+
element instead of decoding the whole file into memory. (`html5: true` is the
|
|
191
|
+
same switch under its backend name.) `on` accepts the full lifecycle set:
|
|
192
|
+
`play`, `pause`, `stop`, `end`, `fade`, `seek`, `rate`, `volume`, `mute`,
|
|
193
|
+
`unlock`.
|
|
194
|
+
|
|
195
|
+
Re-preloading a manifest that already contains a loaded clip is a no-op —
|
|
196
|
+
`audio.unload(name)` first if you genuinely want to reload it.
|
|
197
|
+
|
|
198
|
+
**Credentials use the same global switch as every other asset type** —
|
|
199
|
+
`loader.setOptions({ withCredentials: true })`, not an audio-specific option.
|
|
200
|
+
Buffered audio fetches through the shared loader path, so it honours it exactly
|
|
201
|
+
as an image or a JSON file does. A `stream: true` clip does not: it plays
|
|
202
|
+
through an `<audio>` element, which needs a `crossorigin` attribute rather than
|
|
203
|
+
fetch credentials. Preload a clip buffered if it sits behind a login.
|
|
204
|
+
|
|
205
|
+
**Failing clips and `setStopOnAudioError(false)`.** The default is to fail the
|
|
206
|
+
preload when a clip cannot be loaded after its retries: the error reaches the
|
|
207
|
+
loader, so `await loader.preload(...)` rejects and your `catch` runs, and the
|
|
208
|
+
reason is logged. Turn the flag off and the engine mutes audio, warns
|
|
209
|
+
(`failed loading <name>, disabling audio`) and lets the load *continue* — the
|
|
210
|
+
preload finishes and the game reaches the next scene without sound.
|
|
211
|
+
|
|
212
|
+
Before 20.4 both halves were broken: with the flag off it disabled audio and
|
|
213
|
+
failed the preload anyway, and a clip whose bytes arrived but would not decode
|
|
214
|
+
(a missing file served as HTML by an SPA rewrite, say) reported nothing at all
|
|
215
|
+
either way — blank screen, empty console.
|
|
216
|
+
|
|
217
|
+
## Symptom → cause
|
|
218
|
+
|
|
219
|
+
| symptom | cause |
|
|
220
|
+
|---|---|
|
|
221
|
+
| audio assets 404 | `src` given as a full filename instead of a directory prefix |
|
|
222
|
+
| `target audio extension(s) should be set...` thrown at preload | `audio.init()` not called before preloading |
|
|
223
|
+
| `audio clip X does not exist` | the clip was never preloaded, or the name is mis-cased — every per-clip call throws this |
|
|
224
|
+
| nothing plays until the user clicks | browser autoplay policy — expected, design around it |
|
|
225
|
+
| `playing()` is false right after `play()` | playback starts asynchronously |
|
|
226
|
+
| music keeps playing after leaving a scene | used `play` instead of `playTrack`, or no `stopTrack` in teardown |
|
|
227
|
+
| `stereo` / `position` do nothing | the clip was loaded with `stream: true` — spatial is WebAudio-only |
|
|
228
|
+
| one format works, another does not | that codec is not in the `audio.init()` list |
|
|
229
|
+
| audio behind a login fails, or the preload hangs | `loader.setOptions({ withCredentials: true })` — the same switch every asset type uses |
|
|
230
|
+
| a streamed clip ignores `withCredentials` | `stream: true` plays through an `<audio>` element; preload it buffered instead |
|
|
231
|
+
| `audio.tone(440, {...})` does nothing / errors | `tone` takes a single options object with a required `duration` |
|
|
232
|
+
| `tone` / `noise` are silent with no error | no WebAudio context — `getAudioContext()` returned `null` |
|
|
233
|
+
|
|
234
|
+
## Related skills
|
|
235
|
+
|
|
236
|
+
- `melonjs-getting-started` — preloading and asset ordering
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: melonjs-camera-and-drawing
|
|
3
|
+
description: "Use this skill for camera control and immediate-mode drawing in melonJS — following a target, viewport bounds, shake and fade, secondary cameras, and drawing shapes, lines and gradients inside a custom draw(). Covers world versus screen coordinate conversion, clipping and masking, and baking with CanvasRenderTarget. Triggers on: Camera2d, viewport, follow, setBounds, shake, fadeIn, fadeOut, worldToLocal, localToWorld, colorMatrix, renderer.fill, renderer.stroke, Rect, Ellipse, Polygon, Line, Gradient, clipRect, mask, CanvasRenderTarget, NoiseTexture2d."
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Camera and immediate-mode drawing
|
|
8
|
+
|
|
9
|
+
## Following a target
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
app.viewport.follow(player, app.viewport.AXIS.BOTH, 0.1);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Pass the renderable, not `renderable.pos`.** `follow()` accepts a `Renderable`,
|
|
16
|
+
a `Vector2d` or a `Vector3d` and **throws** `invalid target for me.Camera2d.follow`
|
|
17
|
+
for anything else. A renderable's `pos` is an `ObservableVector3d`, which is not
|
|
18
|
+
a `Vector3d` subclass, so `follow(player.pos, …)` throws.
|
|
19
|
+
|
|
20
|
+
The third argument is a damping factor in `[0 .. 1]` — lower is smoother and
|
|
21
|
+
laggier, `1` snaps. Omit it for a hard lock (it defaults to `1`). It is
|
|
22
|
+
frame-rate independent since 19.7. `AXIS.HORIZONTAL` / `AXIS.VERTICAL` /
|
|
23
|
+
`AXIS.BOTH` / `AXIS.NONE`.
|
|
24
|
+
|
|
25
|
+
Call it from the followed entity's `onActivateEvent`, using `this.parentApp`.
|
|
26
|
+
|
|
27
|
+
## Bounds are the thing people forget
|
|
28
|
+
|
|
29
|
+
The camera's bounds default to the **renderer size**, so it cannot scroll until
|
|
30
|
+
you widen them to the world:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
app.viewport.setBounds(0, 0, mapWidth, mapHeight);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Symptom: `follow()` is called, looks right, and the view never moves. Note a
|
|
37
|
+
canvas resize resets the default camera's bounds to `(0, 0, w, h)`, so re-apply
|
|
38
|
+
them from a `CANVAS_ONRESIZE` handler if your game resizes. Loading a Tiled map
|
|
39
|
+
sets them for you from the map size.
|
|
40
|
+
|
|
41
|
+
## Camera effects
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
app.viewport.shake(4, 200); // intensity, ms
|
|
45
|
+
app.viewport.fadeIn("#000000", 500); // fade TO black
|
|
46
|
+
app.viewport.fadeOut("#000000", 500); // start black, fade back to normal
|
|
47
|
+
app.viewport.colorMatrix.contrast(1.1).saturate(1.1);
|
|
48
|
+
app.viewport.addPostEffect(new VignetteEffect(app.renderer));
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The fade pair is named from the *colour's* point of view, not the scene's:
|
|
52
|
+
`fadeIn` fades the colour in (screen goes to `color`), `fadeOut` fades it out
|
|
53
|
+
(screen starts at `color` and clears). Both default to a 1000 ms duration and
|
|
54
|
+
take an optional completion callback.
|
|
55
|
+
|
|
56
|
+
`colorMatrix` (`brightness` / `contrast` / `saturate` / `hueRotate` / `sepia` /
|
|
57
|
+
`invertColors`, all chainable) is the cheap way to grade a whole camera: the
|
|
58
|
+
camera appends it as a final post-effect pass by itself whenever the matrix is
|
|
59
|
+
non-identity, and drops it again after the frame. It is **not** shader-free —
|
|
60
|
+
it is a `ColorMatrixEffect`, i.e. a `ShaderEffect`, so like every post effect it
|
|
61
|
+
is inert on the Canvas renderer.
|
|
62
|
+
|
|
63
|
+
## Coordinate conversion
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
app.viewport.worldToLocal(x, y); // world → screen
|
|
67
|
+
app.viewport.localToWorld(x, y); // screen → world
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Both return a `Vector2d`; with no third argument that vector comes from the
|
|
71
|
+
shared pool, so in a per-frame path pass your own `v` as the third argument, or
|
|
72
|
+
release it with `getPool("vector2d").release(v)`.
|
|
73
|
+
|
|
74
|
+
Pointer events already carry every frame of reference: `gameWorldX`/`gameWorldY`
|
|
75
|
+
(world), `gameScreenX`/`gameScreenY` (screen), `gameLocalX`/`gameLocalY`
|
|
76
|
+
(relative to the registered region's container) and `gameX`/`gameY`, which is
|
|
77
|
+
whichever of world/screen matches the region — screen for a `floating` region,
|
|
78
|
+
world otherwise. Use the screen pair for anything that *moves* the camera, or
|
|
79
|
+
the drag feeds back on itself.
|
|
80
|
+
|
|
81
|
+
## Secondary cameras
|
|
82
|
+
|
|
83
|
+
Cameras are first-class — a minimap is a second camera with `autoResize = false`
|
|
84
|
+
and an overridden `postDraw`:
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
this.cameras.set("minimap", new MinimapCamera());
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
View state is per camera, not per scene: a `Camera3d` carries its own distance
|
|
91
|
+
fog (`setFog`), so a minimap or split-screen view fogs independently of the main
|
|
92
|
+
one — and a `Camera2d` never fogs. See `melonjs-3d`.
|
|
93
|
+
|
|
94
|
+
## Immediate-mode drawing
|
|
95
|
+
|
|
96
|
+
Inside a custom `draw(renderer)` you can draw shapes directly. Remember the two
|
|
97
|
+
renderable rules: read `this.pos`, and zero the anchor.
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
draw(renderer) {
|
|
101
|
+
renderer.setColor("#ff8800");
|
|
102
|
+
renderer.fillRect(this.pos.x, this.pos.y, this.width, this.height);
|
|
103
|
+
|
|
104
|
+
renderer.setColor("#ffffff");
|
|
105
|
+
renderer.lineWidth = 2; // property, not setLineWidth()
|
|
106
|
+
renderer.stroke(new Line(0, 0, [/* … */]));
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Geometry available: `Rect`, `RoundRect`, `Ellipse`, `Polygon`, `Line`, `Point`
|
|
111
|
+
(and a `Bounds`). `renderer.fill(shape)` and `renderer.stroke(shape)` take any
|
|
112
|
+
of them and throw `Invalid geometry for fill/stroke` for anything else.
|
|
113
|
+
|
|
114
|
+
`Gradient` gives linear and radial fills, built with
|
|
115
|
+
`renderer.createLinearGradient(x0, y0, x1, y1)` /
|
|
116
|
+
`createRadialGradient(x0, y0, r0, x1, y1, r1)` and then handed to
|
|
117
|
+
`renderer.setColor(gradient)`. `NoiseTexture2d` generates cellular and simplex
|
|
118
|
+
noise — including seamless tiling and `asNormalMap` — so you rarely need to ship
|
|
119
|
+
noise PNGs.
|
|
120
|
+
|
|
121
|
+
## Clipping and masking
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
renderer.clipRect(x, y, w, h); // rectangular clip
|
|
125
|
+
renderable.mask = new Ellipse(/* … */); // shape mask on an object
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Note that a `Container` with `clipping` enabled clips **after** its own
|
|
129
|
+
`translate(pos)`, in container-local coordinates — `clipRect(0, 0, width,
|
|
130
|
+
height)`. It also silently does nothing unless the container is non-root and has
|
|
131
|
+
a finite `width`/`height`: a `Container` built with no explicit size is
|
|
132
|
+
`Infinity × Infinity`, and `clipping = true` on it is a no-op.
|
|
133
|
+
|
|
134
|
+
## Bake once, draw many
|
|
135
|
+
|
|
136
|
+
When you would otherwise issue hundreds of identical draws every frame, render
|
|
137
|
+
them once into a `CanvasRenderTarget` and draw the result:
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
const rt = new CanvasRenderTarget(width, height, { context: "2d" });
|
|
141
|
+
const ctx = rt.context; // a CanvasRenderingContext2D — draw into it once…
|
|
142
|
+
// then draw the backing canvas, not the target object:
|
|
143
|
+
renderer.drawImage(rt.canvas, x, y);
|
|
144
|
+
// or wrap it: new Sprite(0, 0, { image: rt.canvas })
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Pass `rt.canvas`, never `rt` — a `CanvasRenderTarget` is a wrapper, not a
|
|
148
|
+
drawable, and the engine's own bakes (the particle emitter's default texture)
|
|
149
|
+
hand `.canvas` on for exactly that reason.
|
|
150
|
+
|
|
151
|
+
This is the sanctioned performance idiom before reaching for a custom shader.
|
|
152
|
+
|
|
153
|
+
`renderer.toFrameTexture()` is the related tool for capturing the *current frame*
|
|
154
|
+
into a texture for a shader to sample.
|
|
155
|
+
|
|
156
|
+
## Symptom → cause
|
|
157
|
+
|
|
158
|
+
| symptom | cause |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `follow()` set but the view never moves | viewport bounds still at renderer size |
|
|
161
|
+
| `invalid target for me.Camera2d.follow` | passed `player.pos` — pass the renderable, a `Vector2d` or a `Vector3d` |
|
|
162
|
+
| camera drag jumps around | using world (`gameWorldX`) instead of screen (`gameScreenX`) coordinates |
|
|
163
|
+
| `colorMatrix` does nothing | it is a shader effect — inert on the Canvas renderer |
|
|
164
|
+
| custom drawing appears at the origin | `draw()` not reading `this.pos` |
|
|
165
|
+
| custom drawing offset by half its size | centred `anchorPoint` not zeroed |
|
|
166
|
+
| `setLineWidth` is not a function | it is the `lineWidth` property |
|
|
167
|
+
| clipping in the wrong place inside a container | container clips in local coordinates, after its own translate |
|
|
168
|
+
| `container.clipping = true` does nothing | container has no explicit size, so `width`/`height` are `Infinity` |
|
|
169
|
+
| baked target draws nothing / throws | passed the `CanvasRenderTarget`, not its `.canvas` |
|
|
170
|
+
| frame rate drops with many static draws | bake into a `CanvasRenderTarget` instead |
|
|
171
|
+
|
|
172
|
+
## Related skills
|
|
173
|
+
|
|
174
|
+
- `melonjs-renderables` — the `draw()` contract and anchors
|
|
175
|
+
- `melonjs-3d` — `Camera3d`, which extends `Camera2d` and keeps all of the above
|