@lampdotdev/lamp 0.0.0-stage → 0.36.2-nightly.16
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/LICENSE +21 -0
- package/README.md +397 -2
- package/Resources/Devices/roku.json +410 -0
- package/Resources/Devices/xbox-one.json +367 -0
- package/Resources/GameKit/NOTICE.md +63 -0
- package/Resources/GameKit/apple/LampPage.swift +1813 -0
- package/Resources/GameKit/apple/LampPlayer.swift +46 -0
- package/Resources/GameKit/apple/LampWebApp.swift +63 -0
- package/Resources/GameKit/apple/LampWebGame.swift +87 -0
- package/Resources/GameKit/apple/Native.swift +12 -0
- package/Resources/GameKit/build.sh +55 -0
- package/Resources/GameKit/lamp_game.h +116 -0
- package/Resources/GameKit/lamp_host.h +19 -0
- package/Resources/GameKit/lamp_kit.cpp +61 -0
- package/Resources/GameKit/lamp_sound.cpp +455 -0
- package/Resources/GameKit/lamp_xbox.cpp +374 -0
- package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
- package/Resources/GameKit/libraries/cgltf.h +7240 -0
- package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
- package/Resources/GameKit/libraries/dr_wav.h +9209 -0
- package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
- package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
- package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
- package/Resources/GameKit/libraries/sokol_log.h +335 -0
- package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
- package/Resources/GameKit/libraries/stb_image.h +7988 -0
- package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
- package/Resources/GameKit/page/lamp-live.js +672 -0
- package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
- package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
- package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
- package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
- package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
- package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
- package/Resources/GameKit/web/lamp-game.js +3042 -0
- package/Resources/GameKit/web/lamp-phaser.js +128 -0
- package/Resources/WebHost/App.exe +0 -0
- package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
- package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
- package/Resources/WebHost/lamp_controllers.h +1506 -0
- package/Resources/WebHost/lamp_web_host.cpp +1173 -0
- package/Resources/WebLibraries/earlier.txt +318 -0
- package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
- package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
- package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
- package/Resources/WebLibraries/qrcode/LICENSE +21 -0
- package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
- package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
- package/Resources/WebLibraries/rapier/LICENSE +201 -0
- package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
- package/Resources/WebLibraries/rapier/rapier.js +2 -0
- package/Resources/WebLibraries/three/LICENSE +21 -0
- package/Resources/WebLibraries/three/NOTICE.md +4 -0
- package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
- package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
- package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
- package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
- package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
- package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
- package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
- package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
- package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
- package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
- package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
- package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
- package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
- package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
- package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
- package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
- package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
- package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
- package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
- package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
- package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
- package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
- package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
- package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
- package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
- package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
- package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
- package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
- package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
- package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
- package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
- package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
- package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
- package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
- package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
- package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
- package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
- package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
- package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
- package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
- package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
- package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
- package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
- package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
- package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
- package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
- package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
- package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
- package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
- package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
- package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
- package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
- package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
- package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
- package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
- package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
- package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
- package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
- package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
- package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
- package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
- package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
- package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
- package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
- package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
- package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
- package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
- package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
- package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
- package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
- package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
- package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
- package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
- package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
- package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
- package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
- package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
- package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
- package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
- package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
- package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
- package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
- package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
- package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
- package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
- package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
- package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
- package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
- package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
- package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
- package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
- package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
- package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
- package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
- package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
- package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
- package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
- package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
- package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
- package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
- package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
- package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
- package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
- package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
- package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
- package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
- package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
- package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
- package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
- package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
- package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
- package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
- package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
- package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
- package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
- package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
- package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
- package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
- package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
- package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
- package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
- package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
- package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
- package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
- package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
- package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
- package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
- package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
- package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
- package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
- package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
- package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
- package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
- package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
- package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
- package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
- package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
- package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
- package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
- package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
- package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
- package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
- package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
- package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
- package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
- package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
- package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
- package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
- package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
- package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
- package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
- package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
- package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
- package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
- package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
- package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
- package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
- package/Resources/WebLibraries/three/three.core.js +61162 -0
- package/Resources/WebLibraries/three/three.module.js +19537 -0
- package/Resources/WebLibraries/three/three.tsl.js +41903 -0
- package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
- package/Resources/share-rules.json +64 -0
- package/Resources/skills/2d-game/SKILL.md +305 -0
- package/Resources/skills/3d-game/SKILL.md +274 -0
- package/Resources/skills/accounts/SKILL.md +41 -0
- package/Resources/skills/android-design/SKILL.md +159 -0
- package/Resources/skills/app-ai/SKILL.md +154 -0
- package/Resources/skills/app-intents/SKILL.md +31 -0
- package/Resources/skills/app-kinds/SKILL.md +122 -0
- package/Resources/skills/apple-watch/SKILL.md +43 -0
- package/Resources/skills/assets/SKILL.md +183 -0
- package/Resources/skills/building-blocks/SKILL.md +97 -0
- package/Resources/skills/device-control/SKILL.md +56 -0
- package/Resources/skills/device-integrations/SKILL.md +278 -0
- package/Resources/skills/finder-files/SKILL.md +19 -0
- package/Resources/skills/game/SKILL.md +416 -0
- package/Resources/skills/game-3d/SKILL.md +12 -0
- package/Resources/skills/game-art/SKILL.md +11 -0
- package/Resources/skills/game-feel/SKILL.md +13 -0
- package/Resources/skills/game-levels/SKILL.md +12 -0
- package/Resources/skills/game-live/SKILL.md +12 -0
- package/Resources/skills/game-physics/SKILL.md +13 -0
- package/Resources/skills/game-playtest/SKILL.md +26 -0
- package/Resources/skills/game-ui/SKILL.md +278 -0
- package/Resources/skills/github-projects/SKILL.md +62 -0
- package/Resources/skills/icloud-sync/SKILL.md +30 -0
- package/Resources/skills/iphone-hardware/SKILL.md +57 -0
- package/Resources/skills/iphone-widgets/SKILL.md +53 -0
- package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
- package/Resources/skills/mac-widgets/SKILL.md +60 -0
- package/Resources/skills/maps/SKILL.md +8 -0
- package/Resources/skills/menu-bar/SKILL.md +36 -0
- package/Resources/skills/more-apps/SKILL.md +53 -0
- package/Resources/skills/phone-controllers/SKILL.md +79 -0
- package/Resources/skills/phone-pages/SKILL.md +173 -0
- package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
- package/Resources/skills/scene-3d/SKILL.md +27 -0
- package/Resources/skills/scripting/SKILL.md +17 -0
- package/Resources/skills/share-extension/SKILL.md +22 -0
- package/Resources/skills/tv-design/SKILL.md +72 -0
- package/Resources/skills/web-app/SKILL.md +170 -0
- package/Resources/skills/web-game/SKILL.md +95 -0
- package/Resources/skills/web-or-native/SKILL.md +108 -0
- package/Resources/skills/wish-links/SKILL.md +156 -0
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/cli/ai.mjs +237 -0
- package/cli/android.mjs +941 -0
- package/cli/app-ai.mjs +473 -0
- package/cli/browser.mjs +284 -0
- package/cli/calls.mjs +594 -0
- package/cli/dev.mjs +820 -0
- package/cli/devices.mjs +984 -0
- package/cli/lamp.mjs +1326 -0
- package/cli/lampapp.mjs +332 -0
- package/cli/lamps/android-host/LampPageGateway.kt +345 -0
- package/cli/lamps/android-host/app/build.gradle.kts +40 -0
- package/cli/lamps/android-host/build.gradle.kts +4 -0
- package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
- package/cli/lamps/android-host/game/MainActivity.kt +173 -0
- package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
- package/cli/lamps/android-host/gradle.properties +8 -0
- package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
- package/cli/lamps/android-host/page/MainActivity.kt +193 -0
- package/cli/lamps/android-host/settings.gradle.kts +30 -0
- package/cli/lamps/android-host/tools.json +43 -0
- package/cli/lamps/lamp-controllers.js +2 -0
- package/cli/lamps/lamp-for-games.js +6922 -0
- package/cli/lamps/lamp.js +7082 -0
- package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
- package/cli/lamps/mac-starter/APP.md +12 -0
- package/cli/lamps/mac-starter/Package.swift +8 -0
- package/cli/lamps/mac-starter/Sources/App.swift +11 -0
- package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
- package/cli/lamps/mac-starter/Sources/LampSupport.swift +18215 -0
- package/cli/lamps/mac-starter/build.sh +336 -0
- package/cli/lamps/mac-starter/gitignore +3 -0
- package/cli/lamps/mac-starter/lamp-starter.json +6 -0
- package/cli/lamps/web-starter/APP.md +8 -0
- package/cli/lamps/web-starter/app.js +1 -0
- package/cli/lamps/web-starter/index.html +17 -0
- package/cli/lamps/web-starter/lamp-starter.json +5 -0
- package/cli/lamps/web-starter/lamp.js +7082 -0
- package/cli/lamps/web-starter/style.css +25 -0
- package/cli/link.mjs +202 -0
- package/cli/local-ai.mjs +193 -0
- package/cli/mac.mjs +621 -0
- package/cli/mdns.mjs +205 -0
- package/cli/msix.mjs +413 -0
- package/cli/network.mjs +209 -0
- package/cli/openrouter.mjs +133 -0
- package/cli/outside.mjs +203 -0
- package/cli/page.js +317 -0
- package/cli/place.mjs +298 -0
- package/cli/png.mjs +184 -0
- package/cli/share.mjs +270 -0
- package/cli/skill/SKILL.md +280 -0
- package/cli/skills.mjs +71 -0
- package/cli/state.mjs +176 -0
- package/cli/update.mjs +162 -0
- package/package.json +20 -4
- package/site/lib/quota.js +59 -0
- package/site/lib/shared-wishes.js +1727 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: finder-files
|
|
3
|
+
description: A Mac app that takes files or folders from Finder - dropped on its icon, Open With, a Quick Action - with what it declares in capabilities.json, how to try it, and Quick Actions that survive a move. Read before writing any of it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Files and folders from Finder
|
|
7
|
+
|
|
8
|
+
An app that takes files or folders from Finder (dropped on its icon, Open With, a Quick Action) says what it opens in
|
|
9
|
+
`capabilities.json` at the app's root: `{"opens": ["folder", "png", "public.image"]}`, with "folder", "file" for any
|
|
10
|
+
file, file extensions or type identifiers. Lamp declares them for the app; without that macOS hands it nothing. It is
|
|
11
|
+
only ever offered for a kind another app opens, never put in that app's place; a kind nothing else opens (your own
|
|
12
|
+
extension) is the app's to open.
|
|
13
|
+
|
|
14
|
+
To try it, make test files in the app's folder or a temporary folder and hand them over with the `open` command
|
|
15
|
+
`look_at_app` then gives you, which does what Finder does.
|
|
16
|
+
|
|
17
|
+
A Finder Quick Action is a workflow the app writes into ~/Library/Services, and it stores the app's full path: it
|
|
18
|
+
stops working when the app is moved or renamed, until the app runs again and rewrites it. So have the app write it at
|
|
19
|
+
every launch from `Bundle.main.bundlePath`, never once.
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game
|
|
3
|
+
description: Games, 2D or 3D, made either way - what makes one fun and playtesting it, the frame loop, controls (a controller, keys, touch, a TV remote), sound, saves, keeping every frame smooth and light rendering - with the tools for each (Lamp's game runtime in a web page, a Samsung or LG TV app's page, in 2D or with three.js, for a game played with phones, SpriteKit and Lamp's blocks in Swift, an integration's own), and turning an app into a game. Read before writing or changing a game; a new web game at home on the Mac starts from the web-game guide and game-feel instead, and the parts of this it needs come as the skills that guide names.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Games
|
|
7
|
+
|
|
8
|
+
A game is something played in real time, rather than used. What follows holds for every game, whichever way it's
|
|
9
|
+
made; each part then names the tools for each make. For a game in 2D, open the 2d-game skill too (Phaser or SpriteKit,
|
|
10
|
+
and which to choose); for one in 3D, the 3d-game skill (or scene-3d for RealityKit in Swift). Before designing its
|
|
11
|
+
opening, title, menus, level select, HUD, pause or results, read the game-ui skill: a new game picks its screen flow
|
|
12
|
+
there before any screen is drawn, however it's made.
|
|
13
|
+
|
|
14
|
+
The tools Lamp has for games:
|
|
15
|
+
|
|
16
|
+
- **Web**: Lamp's game runtime, `Web/lamp-game.js`, with Phaser for 2D (through `Web/lamp-phaser.js`) or three.js for
|
|
17
|
+
3D, in a game `make_app_for` made with `kind` "game". It's a game's default make, 2D or 3D, wherever Lamp has a host
|
|
18
|
+
for a page, and the same on every one of them. Read lamp-game.js first, all of it (and lamp-phaser.js for 2D): their
|
|
19
|
+
comments are the whole interface. (A new game at home on the Mac starts from the web-game guide, which needs neither read whole.) Below, "Web" means this runtime.
|
|
20
|
+
- **TypeScript**: a game whose source is TypeScript (one brought in from a Vite project, or when the person asks for
|
|
21
|
+
it) keeps it in `src/` with `src/main.ts` as its entry, and Lamp bundles it into `Web/app/` before every build and
|
|
22
|
+
look (types stripped, not checked): `Web/index.html` loads `app/main.js` (and `app/main.css` when the source imports
|
|
23
|
+
CSS), and its import map names the bare imports, `three` and `lamp-game` (`./lamp-game.js`) among them. As in a
|
|
24
|
+
Vite build, `import.meta.env` reads as a published build's, and a worker is a `src/**/*.worker.ts` file, started with
|
|
25
|
+
`new Worker(new URL("./<name>.worker.js", import.meta.url), { type: "module" })` (`.js`: every file is bundled flat
|
|
26
|
+
into `Web/app/`; a module worker, since what it shares with the page comes as an import). Edit `src/`,
|
|
27
|
+
never `Web/app/`. A game in plain JavaScript stays as it is, its modules in `Web/`.
|
|
28
|
+
- **AI in a game** (`LampAI` in Web/lamp.js): checked and shown where it can't answer as the web-app skill's
|
|
29
|
+
"LampAI" says, with lamp.js's own line and its link, never words of the game's own.
|
|
30
|
+
- **Phones as players**: a game on the runtime takes phones on the Wi‑Fi with `Lamp.controllers` (Web/lamp.js) and
|
|
31
|
+
its page for them in Phone/ (the phone-controllers and phone-pages skills), on the Mac, in the TV preview, on a
|
|
32
|
+
Samsung or LG TV and on the Xbox; elsewhere `Lamp.controllers` says it can't start, so the game stays whole with a controller,
|
|
33
|
+
the keys or touch. Lamp plays the game with a controller of its own, never as a phone: only the person's phones
|
|
34
|
+
join. Read a phone's buttons in `frame(f)` from `f.phones`, as the pads are read (`frame().phones`
|
|
35
|
+
in a Phaser scene): one `{ player, down, pressed, released }` for each phone joined, each button by the name the phone
|
|
36
|
+
page gave it, so `for (const p of f.phones) if (p.pressed.go) start()`. `pressed` and `released` last the one frame after
|
|
37
|
+
it happened, and a press let go again between two frames is still a press. `onButton` runs between frames, so a flag
|
|
38
|
+
it sets and `frame` clears is lost: keep it for what can't wait for a frame. Sticks and messages still come by
|
|
39
|
+
`onAxis` and `onMessage`, so the game keeps its own queue for them (the phone-pages skill's "Views and moves").
|
|
40
|
+
- **A TV app's page**: a game made as a Samsung or LG TV app before games took phones (`kind` "app") has no
|
|
41
|
+
lamp-game.js: it follows the TV rules and lamp.js instead, with its own `requestAnimationFrame`. The rest of this
|
|
42
|
+
skill holds for it wherever it doesn't name the runtime.
|
|
43
|
+
- **Native Apple** (Mac, iPhone, iPad, Apple TV): SpriteKit for 2D, SwiftUI for menus and scores, and Lamp's blocks
|
|
44
|
+
in LampSupport.swift: a game made natively, where the person asked for that, it needs what only Apple's apps have
|
|
45
|
+
(Game Center, a widget, a place inside an app of theirs) or the device has no host for a page (an Apple TV). It stays
|
|
46
|
+
on Apple's devices: it can't go to Android, the Xbox, a TV's browser or the web later. For 3D in Swift, LampSceneView (the scene-3d skill) is for a Mac app made natively; a native 3D game
|
|
47
|
+
on iPhone, iPad or Apple TV writes its own 3D with that device's frameworks (RealityKit or SceneKit).
|
|
48
|
+
- **Native Android**: Lamp has no game help in Kotlin yet: write the game's own frame loop on a SurfaceView or a
|
|
49
|
+
Canvas, and its controls, sound and saves with Android's own APIs.
|
|
50
|
+
- **An integration's device** (Roku…): what its integration declares; read the device-integrations skill.
|
|
51
|
+
- **Apple Watch**: Lamp has no game help there.
|
|
52
|
+
|
|
53
|
+
## Fun
|
|
54
|
+
|
|
55
|
+
A game is for fun, and fun is designed from the first build, not added at the end:
|
|
56
|
+
|
|
57
|
+
- **A clear core loop.** One thing the player does again and again (jump, aim, steer, match) that feels good on its
|
|
58
|
+
own, and a reason to do it once more: a score to beat, the next level, something new just ahead.
|
|
59
|
+
- **Quick feedback.** Every action answers at once, in sight and sound: a hit flashes and pops, a coin chimes and
|
|
60
|
+
leaps to the score, a landing squashes. This is the game's juice: particles, a little screen shake on the big
|
|
61
|
+
moments (never on every frame, and less on a TV across the room), a tween in place of a jump cut, a short freeze on
|
|
62
|
+
a big hit.
|
|
63
|
+
- **A learning curve.** The first minute teaches by playing, never by a page of rules; then it gets harder in steps the
|
|
64
|
+
player feels coming, with a breather after each rise.
|
|
65
|
+
- **Variety.** New enemies, places, rules or tools keep coming, so the tenth minute isn't the first again.
|
|
66
|
+
- **Surprise and delight the player frequently.** Small things nobody asked for: a character that waves back, a
|
|
67
|
+
secret, a joke in a name, a combo that does something special, weather that changes, a celebration that's over the
|
|
68
|
+
top. Many small ones beat one big one.
|
|
69
|
+
|
|
70
|
+
What's in it is made in code (3D models from three.js shapes, the 3d-game skill; pictures drawn in code or painted with
|
|
71
|
+
`make_art`) or ready-made from Lamp's free assets: models, characters with their animations, sprite sheets, tilesets,
|
|
72
|
+
textures, sound effects and music, fetched and credited by the `assets` tool (the assets skill says when each suits and
|
|
73
|
+
how to keep one style). Sound looks in those assets first ("Sound", below). Either way it's the person's to share. Any other file only when the person gives it or names where it comes from and its license allows sharing; it goes into the game's own
|
|
74
|
+
folder, credited as the rules say. The game never loads anything from the network while it's played.
|
|
75
|
+
|
|
76
|
+
When asked to make a game more fun, look at it first and find what's flat (a loop that doesn't pull, a curve that's
|
|
77
|
+
too easy or too hard, an action that answers with nothing), then work on those four: the loop and the curve, the
|
|
78
|
+
juice, the surprises, and the variety. Keep what the person likes about it, and its controls.
|
|
79
|
+
|
|
80
|
+
## The frame loop
|
|
81
|
+
|
|
82
|
+
Everything that moves is moved by the time since the last frame, never by a fixed step per frame: devices draw at
|
|
83
|
+
different rates, and a slow frame must not slow the game.
|
|
84
|
+
|
|
85
|
+
- Web (the runtime): `game({ renderer, init, frame })` from lamp-game.js, moving by `f.dt`; in 2D, Phaser's scenes
|
|
86
|
+
through `phaser({ scenes })` from lamp-phaser.js, moving by `update`'s `delta`, on the same one loop. Never requestAnimationFrame, timers, the
|
|
87
|
+
clock, Math.random or localStorage: `random()`, `save()` and `load()` from the runtime, which keep through a change
|
|
88
|
+
of the code.
|
|
89
|
+
Physics is the one exception to moving by `f.dt`: it steps at a fixed 1/60 s inside the frame, through `fixedStep`
|
|
90
|
+
from lamp-game.js, so it behaves the same at any frame rate (Rapier for 3D, in the 3d-game skill).
|
|
91
|
+
- SpriteKit: in a SpriteView, one SKScene subclass for each screen with `scaleMode = .resizeFill`; movement in
|
|
92
|
+
`update(_:)` scaled by the time since the last frame; collisions with SKPhysicsBody, its category and contact masks,
|
|
93
|
+
and an SKPhysicsContactDelegate. An SKCameraNode follows the player through a world bigger than the screen.
|
|
94
|
+
|
|
95
|
+
## Controls
|
|
96
|
+
|
|
97
|
+
Controls follow the input the player has, not the device: the same player may pick up an Xbox, PlayStation or
|
|
98
|
+
Switch controller, the keyboard or the touch screen, and switch while playing.
|
|
99
|
+
|
|
100
|
+
- **Web**: lamp-game.js reads all of them as one pad, `f.pads[0]` (`pad()` in a Phaser scene). Write the controls once, as actions mapped to the
|
|
101
|
+
pad (`const CONTROLS = { jump: BUTTON.A, pause: BUTTON.MENU, move: STICK.LEFT, gas: TRIGGER.RT }`), and read the pad
|
|
102
|
+
through them. `input()` says what the player holds (`kind` is `controller`, with its `family`: `xbox`,
|
|
103
|
+
`playstation`, `switch` or `other`; or `keyboard`, or `touch`); `onInput(draw)` draws now and again each time they
|
|
104
|
+
take up another. Build every prompt and help screen inside it from the actions: `label(CONTROLS.jump)` is the
|
|
105
|
+
button's name on that input ("A", "✕", "Space") and `glyph(CONTROLS.jump)` its badge, an element to put in the text.
|
|
106
|
+
Both are null where the input has nothing for that action: leave the line out. Never write a key's or a button's
|
|
107
|
+
name yourself; a page that reads the keys itself (`keyboard: false`) names its own keys by their codes,
|
|
108
|
+
`label('KeyH')`. When the person names the keys to move with, the hints use them: `keyboardHints: { leftStick:
|
|
109
|
+
'arrows' }` to `game()` or `phaser()` makes `label(STICK.LEFT)` and `glyph(STICK.LEFT)` name the arrow keys (`'wasd'`
|
|
110
|
+
is the default). Both sets of keys still move the player.
|
|
111
|
+
- **Swift**: GameController's `GCController` for a controller, with the button's name from the controller itself
|
|
112
|
+
(`localizedName`, `sfSymbolsName`) rather than a fixed letter; keys on a Mac with
|
|
113
|
+
`NSEvent.addLocalMonitorForEvents`.
|
|
114
|
+
- **Touch**: big targets for thumbs, and few of them. Web: the runtime draws a stick and the buttons `touch` names;
|
|
115
|
+
keep the game playable with those few.
|
|
116
|
+
- **A TV remote**: arrows and OK, and a back key; a game that needs more wants a controller, or phones (the
|
|
117
|
+
phone-controllers skill).
|
|
118
|
+
|
|
119
|
+
B (or Esc, or Back) is the game's own back or cancel; Menu pauses.
|
|
120
|
+
|
|
121
|
+
## Sound
|
|
122
|
+
|
|
123
|
+
Every game has sound: a short effect (under a second) for each thing the player does or meets, and music only when it
|
|
124
|
+
suits, quiet (0.3 to 0.4) under effects at 0.6 to 0.8. Settings or the pause menu turn sound and music on and off.
|
|
125
|
+
|
|
126
|
+
**Look in the `assets` tool before writing any sound.** List what the game needs to sound like (each thing the player
|
|
127
|
+
does or meets, and its music), then see the whole catalog: `assets` with `kind: sound`, `limit: 30` and no `find` lists
|
|
128
|
+
every effect, and `kind: music` every loop. Fetch one for every moment it can serve, by name and notes (the assets
|
|
129
|
+
skill's "Sounds and music" has more). Only files the person gave come before this. Write a sound in code only for a
|
|
130
|
+
moment nothing in those lists fits, or one that has to follow the game as it's played (an engine's pitch, notes on a
|
|
131
|
+
scale), and name each of those in your report. They're chosen as the game is made, and every one ships inside it.
|
|
132
|
+
|
|
133
|
+
- Web: `sound` in lamp-game.js. A file loads with `await sound.load('assets/…')`. Written in code, effects come from
|
|
134
|
+
`sound.tone`, and music from a loop of a few bars written out note by note into `sound.samples` (a bass line, chords,
|
|
135
|
+
a melody, in one key). Either way `sound.play` plays an effect and `sound.music` a loop, a calmer one for menus and a
|
|
136
|
+
livelier one for play.
|
|
137
|
+
- Swift: files in Assets/ (.wav, .m4a or .mp3, and what the `assets` tool brought in) play with an
|
|
138
|
+
`AVAudioPlayer(contentsOf: LampAssets.url(name)!)` made once and `prepareToPlay()`ed, a few of them for an effect
|
|
139
|
+
that overlaps itself; music is one looping (`numberOfLoops = -1`). Written in code, effects come from one
|
|
140
|
+
`AVAudioEngine` started at launch with an `AVAudioPlayerNode`, each effect a few hundredths of a second of a wave
|
|
141
|
+
written once into an `AVAudioPCMBuffer`, with soft ends so it doesn't click. On iPhone set the session to
|
|
142
|
+
`.ambient`, so the silent switch mutes the game and the person's own music keeps playing.
|
|
143
|
+
|
|
144
|
+
## Saves
|
|
145
|
+
|
|
146
|
+
Scores, progress and settings are kept on the device, and only ever added to: a new field gets a default where it's
|
|
147
|
+
read, so an update never loses a player's progress. Web: `save(name, value)` and `load(name)` from lamp-game.js.
|
|
148
|
+
Swift: LampStore.
|
|
149
|
+
|
|
150
|
+
## Changes while it's played
|
|
151
|
+
|
|
152
|
+
Lamp puts each change into the game while the person plays it (Web: lamp-game.js, "Changes while it's played"), so a
|
|
153
|
+
game is written to keep the player's place through one:
|
|
154
|
+
|
|
155
|
+
- **Everything that has to last is registered, by name, once.** That's how every new game is written, and the scaffold
|
|
156
|
+
starts that way. Web, with `const live = hot(import.meta)` from lamp-game.js:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
const renderer = live.renderer(() => new THREE.WebGLRenderer({ antialias: true }));
|
|
160
|
+
const camera = live.camera('main', () => {
|
|
161
|
+
const c = new THREE.PerspectiveCamera(60, 16 / 9, 0.1, 500);
|
|
162
|
+
c.position.set(0, 4, 12); // its starting pose and lens are made here, and nowhere else
|
|
163
|
+
return c;
|
|
164
|
+
}, { target: () => controls.target });
|
|
165
|
+
const play = live.state('play', {
|
|
166
|
+
version: 1,
|
|
167
|
+
start: () => ({ mode: 'opening', menu: null, level: 1, score: 0, lives: 3, player: { x: 0, z: 0, heading: 0, speed: 0 } }),
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- `live.renderer(build)`: new code gets the renderer the game has before it could make another, so there's one, with
|
|
172
|
+
its compiled shaders. It's made again only when `build` itself changes. An async build (the 3d-game skill's
|
|
173
|
+
WebGPU) is awaited.
|
|
174
|
+
- `live.camera(id, build, { target })`: keeps the camera's pose, lens and what it looks at (`target` gives anything
|
|
175
|
+
with x, y and z that new code makes again, as OrbitControls' `target`). At the first frame it's where the player
|
|
176
|
+
left it, whatever the start set. A change to `build` gives the new lens at the old pose.
|
|
177
|
+
- `live.state(id, { version, start, migrate })`: everything that says where the game is goes in one plain object,
|
|
178
|
+
the mode (playing, paused, a menu), which menu, overlay or card is open, the level, the player's position, heading
|
|
179
|
+
and speed, what they ride or hold, the score, lives, the clock, the time of day. Change its fields and never
|
|
180
|
+
replace it. Lamp snapshots it as plain JSON by itself, so it holds no objects of three.js or Phaser, and nothing
|
|
181
|
+
derived from it is kept elsewhere. A field added to `start()` takes its start value, and every other field keeps its value.
|
|
182
|
+
Raise `version` when a field changes its meaning, with `migrate(old, oldVersion)` to carry the old state over; with
|
|
183
|
+
none, that state starts over from `start()`.
|
|
184
|
+
- Each part of the world is kept with `live.keep` (below).
|
|
185
|
+
|
|
186
|
+
Only what's registered is kept. A renderer or camera the game's code makes for itself, or a variable of its own,
|
|
187
|
+
starts again with the code.
|
|
188
|
+
- **One start path.** Everything registered is back before `init` runs and before the first frame, at a fresh start
|
|
189
|
+
it's `start()`, and the same object stays the whole time. So `init` (in a 2D game, the first scene's `init` or
|
|
190
|
+
`create`) reads the state and builds exactly that screen: that mode, that menu or overlay open, and nothing a fresh
|
|
191
|
+
start shows (a title card, an intro, a tutorial prompt, a fade in) built or shown at all. Never start fresh and then
|
|
192
|
+
put the place back, which leaves the opening over the game and input in the opening's mode. A later restart (a new
|
|
193
|
+
round, a death) sets the state's fields back itself. A 2D game registers its state; Phaser's game and cameras are made
|
|
194
|
+
again from it.
|
|
195
|
+
- **A game from before this**, or one brought in, may use `snapshot()` in game() (or phaser()), plain JSON of where it
|
|
196
|
+
is, with `pendingRestore()` (the state while it starts, null for a fresh start and once it has started) or
|
|
197
|
+
`restore(state)` (called after init when it didn't read pendingRestore()). They're still taken, and a change keeps
|
|
198
|
+
its place through them. Without either it starts again, from its saves. When you're asked to change such a game, register what your change
|
|
199
|
+
touches as you make it, and leave the rest for the changes that touch it: move its renderer into `live.renderer` first, its
|
|
200
|
+
main camera into `live.camera`, then its state, field by field out of snapshot() into `live.state`.
|
|
201
|
+
- **Lamp checks and says.** With your request comes what the game hasn't registered. A change that would start play over
|
|
202
|
+
(no state registered, and no snapshot() it reads back) waits for the person's Reload rather than going in, and the
|
|
203
|
+
look names what's missing: register it in the same turn, and Reload takes both in. Those are the one change a game
|
|
204
|
+
needs to adopt this: after that, changes go in as it's played. After a run of the code, a look says what was kept, built again and reset,
|
|
205
|
+
and what isn't registered. Anything reset that you didn't mean to reset is the place the person lost: register it
|
|
206
|
+
now, so the next change keeps it.
|
|
207
|
+
- A game with phones keeps them through all of this: they stay joined with their numbers, and the code never stops or
|
|
208
|
+
starts `Lamp.controllers` for a change. So the state holds which player owns which slot (the seat, side, color or
|
|
209
|
+
team each player number has), and the new code restores those slots before it sits anyone down. As its first frame
|
|
210
|
+
nears, `onLeave` and `onJoin` are called again for who left and who is here, so `onJoin` for a player who already has
|
|
211
|
+
a slot leaves the slot alone, and only a new player takes a free one. What a phone has held down stays in
|
|
212
|
+
`f.phones`' `down`; a press or message from before the new code started isn't sent again and isn't in `pressed`, so
|
|
213
|
+
anything read while held is read from `down` (or `isHeld`), not remembered from `onButton`.
|
|
214
|
+
- Pictures, models, sounds and data load through the runtime (`texture()`, `model()`, `sound.load()`, `asset()`), never
|
|
215
|
+
by a URL of the game's own: a new copy of one of those goes into the running game with no reload. What the game makes
|
|
216
|
+
of a file itself (a material from shader source, clones of a model, a mixer for its animations, a level from JSON) is
|
|
217
|
+
made again in `assetChanged(path)`, which returns true when it has.
|
|
218
|
+
- Code goes into the running game too, never by opening the page again, in one of two ways, and the log says which,
|
|
219
|
+
what was kept and how long it took:
|
|
220
|
+
- **Swapped**, at once: a change to the methods of a class in a module that ends with `hot(import.meta).accept()`
|
|
221
|
+
from lamp-game.js. Every object the game made of that class runs the new methods with its fields kept.
|
|
222
|
+
- **Run again in place**, for anything else (the HTML, the module that starts the game, a class's constructor or
|
|
223
|
+
fields, an exported function, a new module): the page is put back as the new HTML has it, every module of the game
|
|
224
|
+
runs again, and the game starts straight from what it registered, as a reload would but without one. What's
|
|
225
|
+
registered stays: the renderer and its compiled shaders, the cameras, the state, and each part kept with
|
|
226
|
+
`hot(import.meta).keep(key, build, { inputs, from, background })`, and so do the files the runtime loaded, so the change costs only
|
|
227
|
+
what's built again, and a part built in the background costs the person nothing. The listeners,
|
|
228
|
+
timers, sound contexts and workers the old code started are taken away by Lamp, and so are its `Lamp.controllers`
|
|
229
|
+
callbacks, which the new code sets again as it starts; `dispose` in game() is for anything else it must let go of,
|
|
230
|
+
and never stops the phones (a `stop()` there is ignored).
|
|
231
|
+
|
|
232
|
+
So a game is written in parts, each in a module of its own:
|
|
233
|
+
|
|
234
|
+
- **The module that starts the game only puts the parts together** (`game.js`; New York's `main.js`). It registers
|
|
235
|
+
the renderer, the cameras and the state, and keeps each part of the world:
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
import { game, hot } from './lamp-game.js';
|
|
239
|
+
const live = hot(import.meta);
|
|
240
|
+
const renderer = live.renderer(() => new THREE.WebGLRenderer({ antialias: true }));
|
|
241
|
+
const ground = live.keep('ground', () => buildGround());
|
|
242
|
+
const trees = live.keep('trees', () => buildTrees(ground.heights), { inputs: [ground] });
|
|
243
|
+
scene.add(ground.group, trees.group);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
A kept part is built again only when its own module (or one it imports) changed, its build function changed, one
|
|
247
|
+
of its `inputs` (the parts it's built from) was built again, or a file it read as it was built changed. So build
|
|
248
|
+
each part of the world (the ground, the buildings, the trees and street details, the props, the traffic) in a
|
|
249
|
+
module of its own, into a group of its own that's added to the scene at each start, and do everything to it
|
|
250
|
+
(setting it on the ground, cutting it for culling) inside its build, never to a kept part afterwards. The build
|
|
251
|
+
function in the starting module names the module it builds from (`buildTrees`), since that's how Lamp tells which
|
|
252
|
+
change is its own. Declare the data each part is built from in its `from` (files beside the page, a module of
|
|
253
|
+
generated data, or a folder ending in /), so a change to that data builds the part again in place, with the rest
|
|
254
|
+
of the world and the player's place kept:
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
const streets = live.keep('streets', () => buildStreets(), { from: ['js/map-data.js'] });
|
|
258
|
+
const paint = live.keep('roadPaint', () => buildRoadPaint(streets.network), { inputs: [streets], from: ['js/map-data.js'] });
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
A part that takes more than a frame or two to build (a city from its map data, a terrain, a road network, the
|
|
262
|
+
traffic on it) is built in the background with `background: true`, so a change to it never holds the game still:
|
|
263
|
+
the person plays on with the part they have, "Building…" shows over the game, and once the new part is built its
|
|
264
|
+
shaders are compiled and it swaps in, in about a frame. Until then the game's logic and the controller use the old
|
|
265
|
+
part, so code that reads a part works with either. Its build is either a generator that yields every few
|
|
266
|
+
milliseconds of work (a row of blocks, a chunk of terrain), which Lamp steps between frames, or an async function
|
|
267
|
+
that hands the pure data work (parsing, the arrays geometry is made from) to a worker with `work()` from
|
|
268
|
+
lamp-game.js and makes only the three.js objects from what comes back:
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
const city = live.keep('city', function* () {
|
|
272
|
+
const group = new THREE.Group();
|
|
273
|
+
for (const block of MAP.blocks) { group.add(buildBlock(block)); yield; }
|
|
274
|
+
return { group };
|
|
275
|
+
}, { from: ['js/map-data.js'], background: true });
|
|
276
|
+
|
|
277
|
+
const ground = live.keep('ground', async () => {
|
|
278
|
+
const { positions, normals } = await work('js/ground-worker.js', { size: MAP.size }); // posted back with their buffers as transfer
|
|
279
|
+
return { group: groundMesh(positions, normals) };
|
|
280
|
+
}, { from: ['js/elevation.js'], background: true });
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Data the person asked to come live from the network (today's weather, road closures, a feed) is fetched inside the
|
|
284
|
+
build of the part made from it, and declared in its `from` when a file stands in for it offline, never awaited on its
|
|
285
|
+
own in the module that starts the game: a part keeps what it fetched when the code runs again, while a fetch outside
|
|
286
|
+
every part is waited for again at each change, with the game standing still. The log after each run says how long
|
|
287
|
+
the game's own start took outside its kept parts.
|
|
288
|
+
|
|
289
|
+
The first build, as the game starts, is built whole. A part built from one being built (its `inputs`) is built
|
|
290
|
+
again from the new one once that's in, so parts that must change together are one part. Keep a part's three.js
|
|
291
|
+
objects in the value it returns (one object, or a plain object of them, as `{ group }`), so Lamp can compile them
|
|
292
|
+
ahead and let go of the old ones. Make a part's materials once, in a kept part of their own
|
|
293
|
+
(`live.keep('cityMaterials', () => makeCityMaterials())`), and build only its geometry in the background: a
|
|
294
|
+
material made anew is a shader to compile, which holds the frames on screen while it compiles (about a third of a
|
|
295
|
+
second each in WebKit), and the old part goes without taking the materials the new one still uses.
|
|
296
|
+
|
|
297
|
+
After a run, the look says which parts were built again, how long each took, which are still being built in the
|
|
298
|
+
background, how long the game stood still, and what of the change nothing read again, which shows only after
|
|
299
|
+
Reload. A look shows the person's open game as it is: a change built into a part that was kept isn't in it until
|
|
300
|
+
that part is built again.
|
|
301
|
+
|
|
302
|
+
A big 3D world on three.js's `WebGPURenderer` keeps its scene and lights the same way, as its camera is. For a new one of
|
|
303
|
+
them it works out how to draw every object again, which holds a big world still for a second at each change. Empty
|
|
304
|
+
the kept scene at each start (`scene.clear()`), then add back the kept lights and each part's group, so what the
|
|
305
|
+
last run added doesn't stay.
|
|
306
|
+
- **The HUD and menus are made at each start**, from the page's HTML or built in code, and their elements found
|
|
307
|
+
there (in init, or the function that starts the game), never once at a module's top level: the page they find is
|
|
308
|
+
the one the new HTML put back.
|
|
309
|
+
- **What changes as the person plays is a class the game makes an object of** (a vehicle and its tuning, the
|
|
310
|
+
player's moves, missions, enemies, the HUD's code, the camera, a shader's settings), its state in the object and
|
|
311
|
+
the module ending with `hot(import.meta).accept()`, so most changes are swapped:
|
|
312
|
+
|
|
313
|
+
```js
|
|
314
|
+
import { hot } from '../lamp-game.js';
|
|
315
|
+
const CAR = { topSpeed: 36, acceleration: 4.5 }; // tuning, read where it's used
|
|
316
|
+
export class Car {
|
|
317
|
+
constructor(scene) { this.mesh = buildCar(); scene.add(this.mesh); this.speed = 0; }
|
|
318
|
+
update(dt, pad) { this.speed = Math.min(CAR.topSpeed, this.speed + pad.rt * CAR.acceleration * dt); … }
|
|
319
|
+
}
|
|
320
|
+
hot(import.meta).accept();
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Export every class a module defines and the game calls (one kept to itself keeps its old methods), read tuning
|
|
324
|
+
where it's used rather than copying it into fields in the constructor, and keep state in the objects, not in
|
|
325
|
+
variables at the module's top. An exported plain object (`export const TUNING = {…}`) takes the values a change
|
|
326
|
+
changed and keeps the rest. What a constructor built once stays as built through a swap: give
|
|
327
|
+
`accept((next, { changed }) => …)` the rebuild, or have it return false to run the code again.
|
|
328
|
+
**What's at a module's top level outlives it.** The page keeps every version of a module for as long as it's open,
|
|
329
|
+
with whatever its variables point at, so a list of objects or a memo at a module's top level holds the old run's
|
|
330
|
+
world, and each run of the code gets slower. Release what the module gathered in `hot(import.meta).dispose(…)`, and
|
|
331
|
+
have the run or the part that owns a system drop it where it's registered (the game's `dispose` for what a run made,
|
|
332
|
+
a part's own `dispose` for what it keeps, which stays registered while the part is kept). A kept renderer doesn't
|
|
333
|
+
manage what a run builds around it: every render pipeline, pass and effect made in a run gets an explicit teardown in
|
|
334
|
+
the game's `dispose`, the pipeline first and the scene pass it reads last, each step safe if an earlier one throws,
|
|
335
|
+
and never `renderer.dispose()`. A build hands on only the data a later consumer needs: one closure kept at a module's
|
|
336
|
+
top level holds everything the function that made it gathered. A reusable generated texture needs an explicit kept
|
|
337
|
+
owner and what invalidates it (a `keep` with `from`, or the kept object it's made from); a transient one needs
|
|
338
|
+
teardown, and not every texture at a module's top level belongs in `keep`. Keeping a compound object doesn't dispose
|
|
339
|
+
what's nested in it, so its `keep` takes a `dispose`, and a custom `dispose` spares what another owner still uses,
|
|
340
|
+
since it replaces the runtime's own. A big table that doesn't
|
|
341
|
+
change as it's played is built inside `keep`, with what it's read from in `from`, so a run reuses it; what changes
|
|
342
|
+
as it's played stays out of `keep`. Name the file's address outside the build (`const address = new URL('./x.bin',
|
|
343
|
+
import.meta.url)`): the runtime writes `import.meta` out differently each run, so a build that names it is built
|
|
344
|
+
again every time.
|
|
345
|
+
`hot(import.meta).dispose(data => …)` takes away what a version made at its top level, keeping in `data` what the
|
|
346
|
+
next version reads as `hot(import.meta).data`.
|
|
347
|
+
|
|
348
|
+
A stylesheet is swapped by itself. Where running again can't be done (a change to the import map or to a script that
|
|
349
|
+
isn't a module, modules that import each other in a circle) the change waits for the person's Reload, which opens the
|
|
350
|
+
page again from what's registered; so does new code that fails as it starts, before its first frame or in its first
|
|
351
|
+
second, at once. A game bundled from TypeScript is one
|
|
352
|
+
file, so its changes run it again, and what it keeps is built again with each change.
|
|
353
|
+
- `busy()` is true while a match, race or round is on: a change that runs the code again then waits for the next
|
|
354
|
+
pause, and the person can put it in at once with Reload. A swap goes in at once.
|
|
355
|
+
- On a phone, Android, a TV or the Xbox a change arrives when Lamp installs the game again, and the runtime puts what's
|
|
356
|
+
registered back then, once, as it does the last snapshot.
|
|
357
|
+
|
|
358
|
+
Swift: a change reopens the app; what it keeps is what it saved.
|
|
359
|
+
|
|
360
|
+
## Keeping every frame smooth
|
|
361
|
+
|
|
362
|
+
A frame has about 16 ms, and anything that runs during play takes from it, so a slow piece is a stutter:
|
|
363
|
+
|
|
364
|
+
- load each picture, model and sound once and reuse it; prepare a level before it starts;
|
|
365
|
+
- reuse what comes and goes (bullets, enemies, particles) rather than making new ones each time;
|
|
366
|
+
- allocate nothing per frame, and keep per-frame work to what moves;
|
|
367
|
+
- many copies of one thing are one draw (THREE.InstancedMesh, `LampScene.copies` in a Mac-only app).
|
|
368
|
+
|
|
369
|
+
The request's device line names the slowest device the game is played on and its budget; the log says how frames kept
|
|
370
|
+
to time. When frames are late, draw less.
|
|
371
|
+
|
|
372
|
+
## The look
|
|
373
|
+
|
|
374
|
+
Sprites, characters and backgrounds are art from `make_art` or one ready-made pack (the assets skill), all in one
|
|
375
|
+
style, on a transparent background where they move. Shapes and colors made in code, well lit, look better than
|
|
376
|
+
mismatched models. Score, pause and menus are large and easy to read, over the game (SwiftUI over a SpriteView; HTML
|
|
377
|
+
over the canvas in a page), and made for its world: the game-ui skill says how to choose the screens a game needs and
|
|
378
|
+
give them its theme.
|
|
379
|
+
|
|
380
|
+
After changing anything that moves, look_at_app with `motion` shows what changes frame to frame and catches flicker a
|
|
381
|
+
single picture hides.
|
|
382
|
+
|
|
383
|
+
## Playtesting
|
|
384
|
+
|
|
385
|
+
`use_app` plays the game in front of the person, so play it only when they ask you to try, play or test it; then play it
|
|
386
|
+
the way they would, since a game that only looks right isn't done. For a request to change it, build and look, and say
|
|
387
|
+
in your report what you didn't play rather than calling it checked. On Lamp's game runtime, `use_app` plays the game in its window on this Mac, the one the person has open, with Lamp's own controller (`stick`,
|
|
388
|
+
`button` and `wait`), in plain sight and from wherever the game is: a menu, a pause screen, the middle of a level. A
|
|
389
|
+
button or field the game's page shows (a menu, a mode switch, a name) is used with `click`, `double_click` or `type` by
|
|
390
|
+
its id from the screen as text; `key` isn't taken there, so what a key does in play is a `button` or a `stick`. A click
|
|
391
|
+
is only sent: the next picture and the log say whether the game took it. Read
|
|
392
|
+
the last picture first and get to what you mean to check; to begin again, look with `reopen` (which asks the person
|
|
393
|
+
first while they play). Play a whole round: start, learn the controls, score, get hit, lose, win, pause. Ask of each
|
|
394
|
+
stretch whether it's fun: is there always something to do, does each action answer, is it too easy or too hard, does
|
|
395
|
+
anything surprise. Fix what isn't, and play it again.
|
|
396
|
+
|
|
397
|
+
A fix goes into the open game as you save it (or with a look), so play on after one with `use_app`; nothing replays the
|
|
398
|
+
moves before it, and the game's random numbers differ each time, so play to the same place again rather than expecting
|
|
399
|
+
the same frames. The person playing takes the game back at once: then use_app is off until their next message.
|
|
400
|
+
|
|
401
|
+
A C++ game (played on the Xbox), SpriteKit in a Swift app and a page with a loop of its own take no controller from Lamp:
|
|
402
|
+
`use_app` there acts as that place takes it, where the person sees it, so it waits for them to ask. Without that, keep to
|
|
403
|
+
what `look_at_app` shows, and say what you didn't play rather than calling it checked.
|
|
404
|
+
|
|
405
|
+
## A game and the project's other apps
|
|
406
|
+
|
|
407
|
+
When the person wants an app to become a game ("actually, make it a game"), change its code in place: the same app,
|
|
408
|
+
now played. If they might want both (the app they use and a game beside it), ask once whether to keep the app as well
|
|
409
|
+
or replace it. Turning it into a game is a change to that app: `make_app_for` with its folder in `app` and `kind`
|
|
410
|
+
"game" (made as the table's defaults say unless the person names a make: web wherever Lamp has a host for a page),
|
|
411
|
+
keeping its folder and data, and its code changed into a
|
|
412
|
+
game. A game beside
|
|
413
|
+
the app is one more app, only when they say they want both and the game is of another kind than the app:
|
|
414
|
+
`make_app_for` with `another` and `kind` "game", in a folder of its own, once they chose that when you asked. Two apps
|
|
415
|
+
of one kind can't be in one project yet (the `more-apps` skill), and a game is never made web only to get around that. A
|
|
416
|
+
game that becomes an app again is the same in reverse.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-3d
|
|
3
|
+
description: For a web game at home on the Mac that's drawn in 3D (a world with depth, a camera that moves through or around it, models and light) - three.js on Lamp's game runtime, models, light and materials, and what costs the most. Choose it by how the game is drawn, not by the word 3D. Not for a flat game with depth effects. Things that move as bodies are game-physics.
|
|
4
|
+
sections: 3d-game#; 3d-game#A game on Lamp's runtime; 3d-game#Models, light and materials; 3d-game#What costs the most
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# A web game in 3D on the Mac
|
|
8
|
+
|
|
9
|
+
The web-game guide and game-feel hold for a game in 3D as for one in 2D; this is how it draws. Where it names Physics,
|
|
10
|
+
that's the game-physics skill.
|
|
11
|
+
|
|
12
|
+
{{sections}}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-art
|
|
3
|
+
description: For a web game at home on the Mac whose look is part of what's asked - a style the person named (pixel art, hand-drawn, neon, cozy), a game that's mostly its look, or drawn art beyond shapes - authored screens and titles, a theme carried into how screens are built, and drawing the art. Not for every game: the guide's How it looks and game-feel's feedback are the baseline.
|
|
4
|
+
sections: game-ui#Authored, not defaulted; game-ui#Theme in the composition; 2d-game#Drawing the art; 2d-game#Pixel art or smooth
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# A look that's this game's own
|
|
8
|
+
|
|
9
|
+
The web-game guide and game-feel hold; this is for when the look itself is asked for.
|
|
10
|
+
|
|
11
|
+
{{sections}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-feel
|
|
3
|
+
description: What makes a web game at home on the Mac good to play, beside the web-game guide's runtime rules - fun and feedback, sound, saves that never lose progress, a flow that starts and restarts cleanly, a finished look, and teaching in play. Playing it, checking it and judging it are the game-playtest skill's, when the person asks. Lamp hands it over with the guide when the game is made; open it in a later conversation before changing how the game plays, teaches or looks.
|
|
4
|
+
sections: game#Fun; game#Sound; game#Saves; game-ui#What every flow keeps; game-ui#A finished look; game-ui#Teaching and input; game-ui#Feedback and layout
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# What makes the game good to play
|
|
8
|
+
|
|
9
|
+
The web-game guide says how the game runs on Lamp's runtime; this says what makes it worth playing, and every game
|
|
10
|
+
needs it. Where the two touch the runtime (files, input, how sound loads), the guide holds. A section below that points
|
|
11
|
+
to the game or game-ui skill means the part that's here; open another skill only when the guide says the game needs it.
|
|
12
|
+
|
|
13
|
+
{{sections}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-levels
|
|
3
|
+
description: For a web game at home on the Mac with more than one round to it - levels, stages or worlds, unlocks and a level select, a menu that's a place to walk through, a story, a pause menu with options - choosing the flow before drawing the screens. Not for one round with a score: title, play and results are the guide's flow, and game-feel keeps what every flow needs.
|
|
4
|
+
sections: game-ui#A short brief; game-ui#Pick the flow first; game-ui#A menu that's a place, where it suits
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Levels and the screens between them
|
|
8
|
+
|
|
9
|
+
The web-game guide and game-feel hold; this is for a game whose rounds add up to more. Saves that keep each unlocked
|
|
10
|
+
level are game-feel's Saves.
|
|
11
|
+
|
|
12
|
+
{{sections}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-live
|
|
3
|
+
description: For a web game at home on the Mac that's open while you change it, when the change is structural - new or split modules, a world that streams in parts, what has to last moved or renamed, or a change that won't go in, needs Reload or loses the player's place. Not for a color, a number, text or a tweak to how something moves: those go in as they are, with the guide's rules for keeping the player's place.
|
|
4
|
+
sections: game#Changes while it's played
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Structural changes to a game that's open
|
|
8
|
+
|
|
9
|
+
The web-game guide's "Keeping the player's place" is what every change keeps; this is the whole of how changes go into
|
|
10
|
+
a running game, for the ones that move its structure.
|
|
11
|
+
|
|
12
|
+
{{sections}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-physics
|
|
3
|
+
description: For a web game at home on the Mac whose fun is things behaving as bodies - they fall, roll, stack, topple, bounce off each other, ride on wheels, swing on joints, or a board tilts under them - with Rapier in 3D, or Phaser's Matter in a flat game. Choose it by the mechanics, not the words: a car that drives on its wheels needs it, stars that fall to be caught don't. Not for steering, simple gravity or checking what touches what: the guide's setup does those.
|
|
4
|
+
sections: 3d-game#Physics
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Things that behave like things
|
|
8
|
+
|
|
9
|
+
The web-game guide and game-feel hold; this is the physics a game of bodies needs, with Rapier, which Lamp ships for a
|
|
10
|
+
game drawn in 3D. A flat game whose things must tumble, stack or swing on joints uses Phaser's Matter instead
|
|
11
|
+
(`physics: { default: 'matter' }` to `phaser()`), with the same reasons for when it's worth it.
|
|
12
|
+
|
|
13
|
+
{{sections}}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-playtest
|
|
3
|
+
description: For a web game at home on the Mac, only when the person asks to play it, test it, check that it works or judge how it looks - playing a round in its window, seeing the real opening, proving a flow and its screens, and one short critique. Open it then, and do only what was asked. Never for a request that only changes the game.
|
|
4
|
+
sections: game#Playtesting; game-ui#Check the real opening; game-ui#Proof; 3d-game#Checking it
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Playing and checking the game, when asked
|
|
8
|
+
|
|
9
|
+
Lamp builds this game and opens it at the end of every turn, and says whether its window drew. Playing it, looking at
|
|
10
|
+
it and judging it happen only when the person asks, and only as far as they asked:
|
|
11
|
+
|
|
12
|
+
- **Play it, test it, check it works:** one `use_app` round as the person would play it: start, steer both ways,
|
|
13
|
+
take a hit, wait out the round to the results, press A to restart. Fix what fails and play that part again.
|
|
14
|
+
- **How it looks:** one `look_at_app` (with `reopen` for the opening, `motion` for what moves), without playing a
|
|
15
|
+
round. It's the game's window as the person has it; how it fits a smaller window is checked by reading its layout
|
|
16
|
+
against the stage's (the web-game guide).
|
|
17
|
+
- **Check the code:** read it, without opening or playing the game.
|
|
18
|
+
- **A critique:** look at the opening, a moment of play and the results in the pictures you already have, against
|
|
19
|
+
what the person asked for. Name at most one thing a player would trip on or that reads as a template, and fix it,
|
|
20
|
+
or say nothing is worth changing. A screen that works isn't restyled for this.
|
|
21
|
+
|
|
22
|
+
A request to check once doesn't reach later changes: the next change is written and finished as the guide says. The
|
|
23
|
+
sections below hold for this game only inside what the person asked; where one says "before you finish", read "when
|
|
24
|
+
asked". Say what you didn't try.
|
|
25
|
+
|
|
26
|
+
{{sections}}
|