diff --git a/toybox/Sandbox/1/scripts/scene.cs b/toybox/Sandbox/1/scripts/scene.cs index eadcc3bac..1d46b4a46 100644 --- a/toybox/Sandbox/1/scripts/scene.cs +++ b/toybox/Sandbox/1/scripts/scene.cs @@ -154,11 +154,24 @@ function setCustomScene( %scene ) setSceneToWindow(); } -function SceneWindow::onExtentChange(%this) +//----------------------------------------------------------------------------- +// Match the camera's horizontal extent to the current window aspect ratio, +// keeping the camera height fixed. This fires on every live window resize, and +// is also re-applied after a toy loads/resets (see loadToy / RestartToyOverlay) -- +// toys set a fixed camera size in their reset(), which bakes in a specific +// aspect, so without re-applying this the scene stretches when the toy is +// reloaded/restarted on a window that has since been resized to another shape. +//----------------------------------------------------------------------------- +function SceneWindow::updateCameraAspect(%this) { %extent = Canvas.extent; %aspect = %extent.x / %extent.y; - %cam = SandboxWindow.getCameraSize(); + %cam = %this.getCameraSize(); %cam.x = %cam.y * %aspect; %this.setCameraSize(%cam); } + +function SceneWindow::onExtentChange(%this) +{ + %this.updateCameraAspect(); +} diff --git a/toybox/Sandbox/1/scripts/toolbox.cs b/toybox/Sandbox/1/scripts/toolbox.cs index 2527a8e87..83e68d122 100644 --- a/toybox/Sandbox/1/scripts/toolbox.cs +++ b/toybox/Sandbox/1/scripts/toolbox.cs @@ -290,6 +290,10 @@ function toggleToolbox(%make) // Reset the toy. if ( Sandbox.ActiveToy.ScopeSet.isMethod("reset") ) Sandbox.ActiveToy.ScopeSet.reset(); + + // reset() re-applies the toy's fixed-aspect camera size, so re-fit it to the + // current window (otherwise restarting on a resized window stretches the scene). + SandboxWindow.updateCameraAspect(); } //----------------------------------------------------------------------------- diff --git a/toybox/Sandbox/1/scripts/toys.cs b/toybox/Sandbox/1/scripts/toys.cs index b27ac53a9..403ae32c6 100644 --- a/toybox/Sandbox/1/scripts/toys.cs +++ b/toybox/Sandbox/1/scripts/toys.cs @@ -88,7 +88,12 @@ function loadToy( %moduleDefinition ) %moduleDefinition.ScopeSet.add( SandboxScene ); // Add toy scope-set as a listener. - SandboxWindow.addInputListener( %moduleDefinition.ScopeSet ); + SandboxWindow.addInputListener( %moduleDefinition.ScopeSet ); + + // The toy just set its own (fixed-aspect) camera size during load. Re-fit it + // to the current window so the scene isn't stretched when the toy is loaded + // into a window that's been resized away from the toy's intended ratio. + SandboxWindow.updateCameraAspect(); } //----------------------------------------------------------------------------- diff --git a/toybox/TruckToy/1/assets/animations/Impact_ExplosionAnimation.asset.taml b/toybox/TruckToy/1/assets/animations/Impact_ExplosionAnimation.asset.taml new file mode 100644 index 000000000..a081e69ab --- /dev/null +++ b/toybox/TruckToy/1/assets/animations/Impact_ExplosionAnimation.asset.taml @@ -0,0 +1,6 @@ + diff --git a/toybox/TruckToy/1/assets/animations/Projectile_FireballAnim.asset.taml b/toybox/TruckToy/1/assets/animations/Projectile_FireballAnim.asset.taml new file mode 100644 index 000000000..b7ba5f661 --- /dev/null +++ b/toybox/TruckToy/1/assets/animations/Projectile_FireballAnim.asset.taml @@ -0,0 +1,6 @@ + diff --git a/toybox/TruckToy/1/assets/animations/Projectile_Meteor_StrikeAnimation.asset.taml b/toybox/TruckToy/1/assets/animations/Projectile_Meteor_StrikeAnimation.asset.taml new file mode 100644 index 000000000..93dacce5c --- /dev/null +++ b/toybox/TruckToy/1/assets/animations/Projectile_Meteor_StrikeAnimation.asset.taml @@ -0,0 +1,5 @@ + diff --git a/toybox/TruckToy/1/assets/images/Impact_Explosion.png b/toybox/TruckToy/1/assets/images/Impact_Explosion.png new file mode 100644 index 000000000..613971fcf Binary files /dev/null and b/toybox/TruckToy/1/assets/images/Impact_Explosion.png differ diff --git a/toybox/TruckToy/1/assets/images/Impact_ExplosionSprite.asset.taml b/toybox/TruckToy/1/assets/images/Impact_ExplosionSprite.asset.taml new file mode 100644 index 000000000..0949bdeeb --- /dev/null +++ b/toybox/TruckToy/1/assets/images/Impact_ExplosionSprite.asset.taml @@ -0,0 +1,7 @@ + diff --git a/toybox/TruckToy/1/assets/images/Projectile_Fireball.png b/toybox/TruckToy/1/assets/images/Projectile_Fireball.png new file mode 100644 index 000000000..50f3d9591 Binary files /dev/null and b/toybox/TruckToy/1/assets/images/Projectile_Fireball.png differ diff --git a/toybox/TruckToy/1/assets/images/Projectile_FireballImage.asset.taml b/toybox/TruckToy/1/assets/images/Projectile_FireballImage.asset.taml new file mode 100644 index 000000000..b7f5c9209 --- /dev/null +++ b/toybox/TruckToy/1/assets/images/Projectile_FireballImage.asset.taml @@ -0,0 +1,7 @@ + diff --git a/toybox/TruckToy/1/assets/images/Projectile_Meteor_Strike.png b/toybox/TruckToy/1/assets/images/Projectile_Meteor_Strike.png new file mode 100644 index 000000000..7dda9109d Binary files /dev/null and b/toybox/TruckToy/1/assets/images/Projectile_Meteor_Strike.png differ diff --git a/toybox/TruckToy/1/assets/images/Projectile_Meteor_StrikeSprite.asset.taml b/toybox/TruckToy/1/assets/images/Projectile_Meteor_StrikeSprite.asset.taml new file mode 100644 index 000000000..3adefc0cb --- /dev/null +++ b/toybox/TruckToy/1/assets/images/Projectile_Meteor_StrikeSprite.asset.taml @@ -0,0 +1,7 @@ + diff --git a/toybox/TruckToy/1/assets/images/background_0.asset.taml b/toybox/TruckToy/1/assets/images/background_0.asset.taml new file mode 100644 index 000000000..bdb81279a --- /dev/null +++ b/toybox/TruckToy/1/assets/images/background_0.asset.taml @@ -0,0 +1,3 @@ + diff --git a/toybox/TruckToy/1/assets/images/background_0.png b/toybox/TruckToy/1/assets/images/background_0.png new file mode 100644 index 000000000..305857a21 Binary files /dev/null and b/toybox/TruckToy/1/assets/images/background_0.png differ diff --git a/toybox/TruckToy/1/assets/images/background_1.asset.taml b/toybox/TruckToy/1/assets/images/background_1.asset.taml new file mode 100644 index 000000000..a8ed407ac --- /dev/null +++ b/toybox/TruckToy/1/assets/images/background_1.asset.taml @@ -0,0 +1,3 @@ + diff --git a/toybox/TruckToy/1/assets/images/background_1.png b/toybox/TruckToy/1/assets/images/background_1.png new file mode 100644 index 000000000..0eec8e464 Binary files /dev/null and b/toybox/TruckToy/1/assets/images/background_1.png differ diff --git a/toybox/TruckToy/1/assets/images/background_2.asset.taml b/toybox/TruckToy/1/assets/images/background_2.asset.taml new file mode 100644 index 000000000..27b46746d --- /dev/null +++ b/toybox/TruckToy/1/assets/images/background_2.asset.taml @@ -0,0 +1,3 @@ + diff --git a/toybox/TruckToy/1/assets/images/background_2.png b/toybox/TruckToy/1/assets/images/background_2.png new file mode 100644 index 000000000..e398fc6c8 Binary files /dev/null and b/toybox/TruckToy/1/assets/images/background_2.png differ diff --git a/toybox/TruckToy/1/assets/images/background_day.asset.taml b/toybox/TruckToy/1/assets/images/background_day.asset.taml deleted file mode 100644 index d596ffdbb..000000000 --- a/toybox/TruckToy/1/assets/images/background_day.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/background_day.png b/toybox/TruckToy/1/assets/images/background_day.png deleted file mode 100644 index 317a08077..000000000 Binary files a/toybox/TruckToy/1/assets/images/background_day.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/background_night.asset.taml b/toybox/TruckToy/1/assets/images/background_night.asset.taml deleted file mode 100644 index 1ee0d2b18..000000000 --- a/toybox/TruckToy/1/assets/images/background_night.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/background_night.png b/toybox/TruckToy/1/assets/images/background_night.png deleted file mode 100644 index 119bbba01..000000000 Binary files a/toybox/TruckToy/1/assets/images/background_night.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/background_nightStars.asset.taml b/toybox/TruckToy/1/assets/images/background_nightStars.asset.taml deleted file mode 100644 index 4d7530913..000000000 --- a/toybox/TruckToy/1/assets/images/background_nightStars.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/background_nightStars.png b/toybox/TruckToy/1/assets/images/background_nightStars.png deleted file mode 100644 index 5bf3d37ab..000000000 Binary files a/toybox/TruckToy/1/assets/images/background_nightStars.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/brickPile.png b/toybox/TruckToy/1/assets/images/brickPile.png index efd20831d..6c01e9b40 100644 Binary files a/toybox/TruckToy/1/assets/images/brickPile.png and b/toybox/TruckToy/1/assets/images/brickPile.png differ diff --git a/toybox/TruckToy/1/assets/images/brickWall_01.png b/toybox/TruckToy/1/assets/images/brickWall_01.png index 69bc5805d..0d8c257f5 100644 Binary files a/toybox/TruckToy/1/assets/images/brickWall_01.png and b/toybox/TruckToy/1/assets/images/brickWall_01.png differ diff --git a/toybox/TruckToy/1/assets/images/brickWall_02.png b/toybox/TruckToy/1/assets/images/brickWall_02.png index 64c40d14b..628a56e9f 100644 Binary files a/toybox/TruckToy/1/assets/images/brickWall_02.png and b/toybox/TruckToy/1/assets/images/brickWall_02.png differ diff --git a/toybox/TruckToy/1/assets/images/brokenCementWall.png b/toybox/TruckToy/1/assets/images/brokenCementWall.png index efec214ef..c99ad394e 100644 Binary files a/toybox/TruckToy/1/assets/images/brokenCementWall.png and b/toybox/TruckToy/1/assets/images/brokenCementWall.png differ diff --git a/toybox/TruckToy/1/assets/images/foregroundWall_01.png b/toybox/TruckToy/1/assets/images/foregroundWall_01.png index e58f252a0..d1b73ef3f 100644 Binary files a/toybox/TruckToy/1/assets/images/foregroundWall_01.png and b/toybox/TruckToy/1/assets/images/foregroundWall_01.png differ diff --git a/toybox/TruckToy/1/assets/images/foregroundWall_02.png b/toybox/TruckToy/1/assets/images/foregroundWall_02.png index 57b12442d..08b66ac45 100644 Binary files a/toybox/TruckToy/1/assets/images/foregroundWall_02.png and b/toybox/TruckToy/1/assets/images/foregroundWall_02.png differ diff --git a/toybox/TruckToy/1/assets/images/industrialBuildings.asset.taml b/toybox/TruckToy/1/assets/images/industrialBuildings.asset.taml deleted file mode 100644 index eb4554991..000000000 --- a/toybox/TruckToy/1/assets/images/industrialBuildings.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/industrialBuildings.png b/toybox/TruckToy/1/assets/images/industrialBuildings.png deleted file mode 100644 index cf6489930..000000000 Binary files a/toybox/TruckToy/1/assets/images/industrialBuildings.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/industrial_01.png b/toybox/TruckToy/1/assets/images/industrial_01.png deleted file mode 100644 index d5c5d15c5..000000000 Binary files a/toybox/TruckToy/1/assets/images/industrial_01.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/industrial_02.asset.taml b/toybox/TruckToy/1/assets/images/industrial_02.asset.taml deleted file mode 100644 index 4949b7a73..000000000 --- a/toybox/TruckToy/1/assets/images/industrial_02.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/industrial_02.png b/toybox/TruckToy/1/assets/images/industrial_02.png deleted file mode 100644 index 312ab77ef..000000000 Binary files a/toybox/TruckToy/1/assets/images/industrial_02.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/industrial_lowOpacity.asset.taml b/toybox/TruckToy/1/assets/images/industrial_lowOpacity.asset.taml deleted file mode 100644 index c34d48d2c..000000000 --- a/toybox/TruckToy/1/assets/images/industrial_lowOpacity.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/industrial_lowOpacity.png b/toybox/TruckToy/1/assets/images/industrial_lowOpacity.png deleted file mode 100644 index 0006891aa..000000000 Binary files a/toybox/TruckToy/1/assets/images/industrial_lowOpacity.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/motorPile.asset.taml b/toybox/TruckToy/1/assets/images/motorPile.asset.taml deleted file mode 100644 index b2102c9d6..000000000 --- a/toybox/TruckToy/1/assets/images/motorPile.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/motorPile.png b/toybox/TruckToy/1/assets/images/motorPile.png deleted file mode 100644 index 9830f8223..000000000 Binary files a/toybox/TruckToy/1/assets/images/motorPile.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/pileORocks.asset.taml b/toybox/TruckToy/1/assets/images/pileORocks.asset.taml deleted file mode 100644 index 0940811c7..000000000 --- a/toybox/TruckToy/1/assets/images/pileORocks.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/pileORocks.png b/toybox/TruckToy/1/assets/images/pileORocks.png deleted file mode 100644 index 60b4c6b21..000000000 Binary files a/toybox/TruckToy/1/assets/images/pileORocks.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/planetFloor.asset.taml b/toybox/TruckToy/1/assets/images/planetFloor.asset.taml new file mode 100644 index 000000000..3a9ab4aeb --- /dev/null +++ b/toybox/TruckToy/1/assets/images/planetFloor.asset.taml @@ -0,0 +1,3 @@ + diff --git a/toybox/TruckToy/1/assets/images/planetFloor.png b/toybox/TruckToy/1/assets/images/planetFloor.png new file mode 100644 index 000000000..84a82c259 Binary files /dev/null and b/toybox/TruckToy/1/assets/images/planetFloor.png differ diff --git a/toybox/TruckToy/1/assets/images/plank_01.png b/toybox/TruckToy/1/assets/images/plank_01.png index ed4282245..743033d05 100644 Binary files a/toybox/TruckToy/1/assets/images/plank_01.png and b/toybox/TruckToy/1/assets/images/plank_01.png differ diff --git a/toybox/TruckToy/1/assets/images/plank_02.png b/toybox/TruckToy/1/assets/images/plank_02.png index cb84619a2..099fe101e 100644 Binary files a/toybox/TruckToy/1/assets/images/plank_02.png and b/toybox/TruckToy/1/assets/images/plank_02.png differ diff --git a/toybox/TruckToy/1/assets/images/plank_03.png b/toybox/TruckToy/1/assets/images/plank_03.png index 6eb3953e1..d40b955cd 100644 Binary files a/toybox/TruckToy/1/assets/images/plank_03.png and b/toybox/TruckToy/1/assets/images/plank_03.png differ diff --git a/toybox/TruckToy/1/assets/images/tires.asset.taml b/toybox/TruckToy/1/assets/images/tires.asset.taml deleted file mode 100644 index 23ac3f47d..000000000 --- a/toybox/TruckToy/1/assets/images/tires.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/tires.png b/toybox/TruckToy/1/assets/images/tires.png deleted file mode 100644 index 13fcce905..000000000 Binary files a/toybox/TruckToy/1/assets/images/tires.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/images/torqueBrick.asset.taml b/toybox/TruckToy/1/assets/images/torqueBrick.asset.taml new file mode 100644 index 000000000..ac5b8494c --- /dev/null +++ b/toybox/TruckToy/1/assets/images/torqueBrick.asset.taml @@ -0,0 +1,7 @@ + diff --git a/toybox/TruckToy/1/assets/images/torqueBrick.png b/toybox/TruckToy/1/assets/images/torqueBrick.png new file mode 100644 index 000000000..d88d7118d Binary files /dev/null and b/toybox/TruckToy/1/assets/images/torqueBrick.png differ diff --git a/toybox/TruckToy/1/assets/images/torqueBridge.asset.taml b/toybox/TruckToy/1/assets/images/torqueBridge.asset.taml new file mode 100644 index 000000000..e89a05bc5 --- /dev/null +++ b/toybox/TruckToy/1/assets/images/torqueBridge.asset.taml @@ -0,0 +1,3 @@ + diff --git a/toybox/TruckToy/1/assets/images/torqueBridge.png b/toybox/TruckToy/1/assets/images/torqueBridge.png new file mode 100644 index 000000000..dbb0e1a81 Binary files /dev/null and b/toybox/TruckToy/1/assets/images/torqueBridge.png differ diff --git a/toybox/TruckToy/1/assets/images/truckBody.png b/toybox/TruckToy/1/assets/images/truckBody.png index 2bd8f56a8..41134a0cf 100644 Binary files a/toybox/TruckToy/1/assets/images/truckBody.png and b/toybox/TruckToy/1/assets/images/truckBody.png differ diff --git a/toybox/TruckToy/1/assets/images/truckTire.asset.taml b/toybox/TruckToy/1/assets/images/truckTire.asset.taml new file mode 100644 index 000000000..a7569eda2 --- /dev/null +++ b/toybox/TruckToy/1/assets/images/truckTire.asset.taml @@ -0,0 +1,3 @@ + diff --git a/toybox/TruckToy/1/assets/images/truckTire.png b/toybox/TruckToy/1/assets/images/truckTire.png new file mode 100644 index 000000000..5ab04fb2e Binary files /dev/null and b/toybox/TruckToy/1/assets/images/truckTire.png differ diff --git a/toybox/TruckToy/1/assets/images/woodPile.png b/toybox/TruckToy/1/assets/images/woodPile.png index f65e42ac8..6697cc0ce 100644 Binary files a/toybox/TruckToy/1/assets/images/woodPile.png and b/toybox/TruckToy/1/assets/images/woodPile.png differ diff --git a/toybox/TruckToy/1/assets/images/wreckedBuilding.png b/toybox/TruckToy/1/assets/images/wreckedBuilding.png index 766b2aaec..468ba4b97 100644 Binary files a/toybox/TruckToy/1/assets/images/wreckedBuilding.png and b/toybox/TruckToy/1/assets/images/wreckedBuilding.png differ diff --git a/toybox/TruckToy/1/assets/images/wreckedCar_01.png b/toybox/TruckToy/1/assets/images/wreckedCar_01.png index fe21ba978..c3f8fafe0 100644 Binary files a/toybox/TruckToy/1/assets/images/wreckedCar_01.png and b/toybox/TruckToy/1/assets/images/wreckedCar_01.png differ diff --git a/toybox/TruckToy/1/assets/images/wreckedCar_02.png b/toybox/TruckToy/1/assets/images/wreckedCar_02.png index b1aaf4001..8cf06754f 100644 Binary files a/toybox/TruckToy/1/assets/images/wreckedCar_02.png and b/toybox/TruckToy/1/assets/images/wreckedCar_02.png differ diff --git a/toybox/TruckToy/1/assets/images/wreckedCar_03.png b/toybox/TruckToy/1/assets/images/wreckedCar_03.png index 39b2023bf..10002cc65 100644 Binary files a/toybox/TruckToy/1/assets/images/wreckedCar_03.png and b/toybox/TruckToy/1/assets/images/wreckedCar_03.png differ diff --git a/toybox/TruckToy/1/assets/images/wreckedCar_hood.asset.taml b/toybox/TruckToy/1/assets/images/wreckedCar_hood.asset.taml deleted file mode 100644 index d7651c880..000000000 --- a/toybox/TruckToy/1/assets/images/wreckedCar_hood.asset.taml +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/toybox/TruckToy/1/assets/images/wreckedCar_hood.png b/toybox/TruckToy/1/assets/images/wreckedCar_hood.png deleted file mode 100644 index 1398d651e..000000000 Binary files a/toybox/TruckToy/1/assets/images/wreckedCar_hood.png and /dev/null differ diff --git a/toybox/TruckToy/1/assets/particles/bonfire.asset.taml b/toybox/TruckToy/1/assets/particles/bonfire.asset.taml new file mode 100644 index 000000000..93bc10f0d --- /dev/null +++ b/toybox/TruckToy/1/assets/particles/bonfire.asset.taml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/toybox/TruckToy/1/assets/particles/explosion.asset.taml b/toybox/TruckToy/1/assets/particles/explosion.asset.taml new file mode 100644 index 000000000..0e6536678 --- /dev/null +++ b/toybox/TruckToy/1/assets/particles/explosion.asset.taml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/toybox/TruckToy/1/main.cs b/toybox/TruckToy/1/main.cs index 72cbd7060..61f3abf9f 100644 --- a/toybox/TruckToy/1/main.cs +++ b/toybox/TruckToy/1/main.cs @@ -22,6 +22,9 @@ function TruckToy::create( %this ) { + // Load the parallax background system (createBackground, layers, per-tick update). + exec("./scripts/background.cs"); + TruckToy.ObstacleFriction = 1.5; TruckToy.CameraWidth = 20; TruckToy.CameraHeight = 15; @@ -37,7 +40,7 @@ TruckToy.ProjectileDomain = 16; TruckToy.ForegroundDomain = 10; - TruckToy.WheelSpeed = 400; + TruckToy.WheelSpeed = 500; TruckToy.WheelFriction = 1; TruckToy.FrontWheelDensity = 6; TruckToy.RearWheelDensity = 3; @@ -46,7 +49,7 @@ TruckToy.ProjectileRate = 3000; TruckToy.ExplosionScale = 1; - TruckToy.RotateCamera = true; + TruckToy.RotateCamera = false; // Add the custom controls. addNumericOption( "Wheel Speed", 100, 1000, 50, "setWheelSpeed", TruckToy.WheelSpeed, false, "Sets the rotational speed of the wheel when it is put into drive." ); @@ -70,6 +73,9 @@ function TruckToy::destroy( %this ) { + // Stop the per-frame parallax update. + SandboxScene.RenderCallback = false; + // Deactivate the package. deactivatePackage( TruckToyPackage ); } @@ -109,7 +115,7 @@ %this.createBonfire( -91.5, TruckToy.FloorLevel + 0.5, 1, TruckToy.BackgroundDomain-1 ); // Building with chains. - %this.createForegroundWall( 2, -99, -5 ); + %this.createForegroundWall( 2, -97, -5 ); %this.createForegroundWall( 1, -75.5, -6.5 ); %this.createBrokenCementWall( -78, -1.5 ); %this.createWreckedBuilding( -71.5, -1 ); @@ -137,7 +143,7 @@ %this.createPlank( 1, -20.5, TruckToy.FloorLevel + 1.5, -90, true ); %this.createPlank( 3, -19, TruckToy.FloorLevel + 4, 0, true ); %this.createPlank( 1, -16.5, TruckToy.FloorLevel + 1.5, -90, true ); - %this.createForegroundBrickWall( 2, -19, -6 ); + %this.createForegroundBrickWall( 2, -15, -6 ); %this.createBonfire( -46.5, TruckToy.FloorLevel, 3, TruckToy.BackgroundDomain-1 ); %this.createBonfire( -18.7, TruckToy.FloorLevel + 1, 2, TruckToy.BackgroundDomain-1 ); @@ -154,7 +160,7 @@ %this.createPyramid( 2, TruckToy.FloorLevel + 0.25, 19, true ); %this.createForegroundWall( 1, 9, -6 ); %this.createPyramid( 2+21, TruckToy.FloorLevel + 0.25, 13, true ); - %this.createForegroundBrickWall( 1, 9, -7 ); + %this.createForegroundBrickWall( 1, 23, -6.5 ); %this.createBonfire( 21, TruckToy.FloorLevel, 3, TruckToy.BackgroundDomain-1 ); @@ -178,61 +184,50 @@ %truckStartY = 3; %this.createTruck( %truckStartX, %truckStartY ); + // Pre-build the projectile and explosion pools so none are allocated mid-play. + %this.createProjectilePool(); + %this.createExplosionPool(); + // Start the timer. TruckToy.startTimer( "createProjectile", TruckToy.ProjectileRate ); } // ----------------------------------------------------------------------------- - -function TruckToy::createBackground(%this) -{ - // Atmosphere - %obj = new Sprite(); - %obj.setBodyType( "static" ); - %obj.setImage( "ToyAssets:highlightBackground" ); - %obj.BlendColor = DarkGray; - %obj.setSize( TruckToy.WorldWidth * (TruckToy.CameraWidth*2), 75 ); - %obj.setSceneLayer( TruckToy.BackdropDomain ); - %obj.setSceneGroup( TruckToy.BackdropDomain ); - %obj.setCollisionSuppress(); - %obj.setAwake( false ); - %obj.setActive( false ); - SandboxScene.add( %obj ); - - - // Industrial Background - %obj = new Scroller(); - %obj.setBodyType( "static" ); - %obj.setImage( "TruckToy:industrial_02" ); - %obj.setPosition( 0, -1 ); - %obj.setSize( TruckToy.WorldWidth, 8 ); - %obj.setRepeatX( TruckToy.WorldWidth / 8 ); - %obj.setSceneLayer( TruckToy.BackgroundDomain); - %obj.setSceneGroup( TruckToy.BackgroundDomain); - %obj.setCollisionSuppress(); - %obj.setAwake( false ); - %obj.setActive( false ); - SandboxScene.add( %obj ); -} - +// createBackground and the parallax layer system live in scripts/background.cs. // ----------------------------------------------------------------------------- function TruckToy::createFloor(%this) { - // Ground + // Ground. + // planetFloor.png is 1233x163, but only the bottom 148px is solid ground; + // the top 15px is empty. We size/position the image and the collision edge + // so the *solid* surface sits exactly on FloorLevel (the empty strip just + // hangs transparently above it). + %imageW = 1233; + %imageH = 163; + %solidH = 148; + + // Make the solid band ~3 world-units thick (matching the old floor), then + // derive the full image height and where the solid surface falls locally. + %solidThickness = 3; + %floorHeight = %solidThickness * (%imageH / %solidH); // full image height (~3.30) + %emptyTop = %floorHeight * ((%imageH - %solidH) / %imageH); // empty strip height (~0.30) + %solidTop = (%floorHeight / 2) - %emptyTop; // local Y of solid surface (~1.35) + %tileWidth = %floorHeight * (%imageW / %imageH); // unstretched tile width (~25) + %obj = new Scroller(); %obj.setBodyType( "static" ); - %obj.setImage( "ToyAssets:woodGround" ); - %obj.setSize( TruckToy.WorldWidth, 3 ); - %obj.setPosition( 0, TruckToy.FloorLevel - (%obj.getSizeY()/2) ); - %obj.setRepeatX( TruckToy.WorldWidth / 12 ); + %obj.setImage( "TruckToy:planetFloor" ); + %obj.setSize( TruckToy.WorldWidth, %floorHeight ); + %obj.setPosition( 0, TruckToy.FloorLevel - %solidTop ); + %obj.setRepeatX( TruckToy.WorldWidth / %tileWidth ); %obj.setSceneLayer( TruckToy.ObstacleDomain ); %obj.setSceneGroup( TruckToy.GroundDomain ); %obj.setDefaultFriction( TruckToy.ObstacleFriction ); %obj.setCollisionGroups( none ); - %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, 1.5, TruckToy.WorldWidth/2, 1.5 ); - %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, 3, TruckToy.WorldWidth/-2, 50 ); - %obj.createEdgeCollisionShape( TruckToy.WorldWidth/2, 3, TruckToy.WorldWidth/2, 50 ); + %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, %solidTop, TruckToy.WorldWidth/2, %solidTop ); + %obj.createEdgeCollisionShape( TruckToy.WorldWidth/-2, %solidTop, TruckToy.WorldWidth/-2, 50 ); + %obj.createEdgeCollisionShape( TruckToy.WorldWidth/2, %solidTop, TruckToy.WorldWidth/2, 50 ); %obj.CollisionCallback = true; %obj.setAwake( false ); SandboxScene.add( %obj ); @@ -282,7 +277,7 @@ { for ( %n = 0; %n < %brickCount; %n++ ) { - %this.createBrick( getRandom(1,5), %posX, %posY + (%n*0.5), %static ); + %this.createBrick( getRandom(0,15), %posX, %posY + (%n*0.5), %static ); } } @@ -303,7 +298,7 @@ %stackY = %posY + ( %stack * 0.5 ); for ( %stackIndex = 0; %stackIndex < %stackIndexCount; %stackIndex++ ) { - %this.createBrick( getRandom(1, 5), %stackX + %stackIndex, %stackY, %static ); + %this.createBrick( getRandom(0, 15), %stackX + %stackIndex, %stackY, %static ); } } } @@ -319,7 +314,7 @@ %rootObj = new Sprite(); %rootObj.setBodyType( "static" ); - %rootObj.setImage( "ToyAssets:cable" ); + %rootObj.setImage( "TruckToy:torqueBridge" ); %rootObj.setPosition( %posX, %posY ); %rootObj.setSize( %linkWidth, %linkHeight ); %rootObj.setSceneLayer( TruckToy.BackgroundDomain-3 ); @@ -333,7 +328,7 @@ { %obj = new Sprite(); - %obj.setImage( "ToyAssets:cable" ); + %obj.setImage( "TruckToy:torqueBridge" ); %obj.setPosition( %posX + (%n*%linkWidth), %posY ); %obj.setSize( %linkWidth, %linkHeight ); %obj.setSceneLayer( TruckToy.BackgroundDomain-3 ); @@ -471,6 +466,8 @@ %obj.setActive( false ); SandboxScene.add( %obj ); + TruckToy.registerParallaxObject( %obj, 1.35 ); + return %obj; } @@ -500,6 +497,9 @@ %obj.setActive( false ); SandboxScene.add( %obj ); + // Foreground depth: scroll a bit faster than the world so they read as close. + TruckToy.registerParallaxObject( %obj, 1.22 ); + return %obj; } @@ -507,17 +507,18 @@ function TruckToy::createBrick( %this, %brickNumber, %posX, %posY, %static ) { - if ( %brickNumber < 1 || %brickNumber > 5 ) + if ( %brickNumber < 0 || %brickNumber > 15 ) { echo( "Invalid brick no of" SPC %brickNumber ); return; } - %image = "ToyAssets:brick_0" @ %brickNumber; + %image = "TruckToy:torqueBrick"; %obj = new Sprite(); if ( %static ) %obj.setBodyType( "static" ); %obj.setImage( %image ); + %obj.setImageFrame(%brickNumber); %obj.setPosition( %posX, %posY ); %obj.setSize( 1, 0.5 ); %obj.setSceneLayer( TruckToy.ObstacleDomain ); @@ -539,7 +540,7 @@ %obj.setBodyType( "static" ); %obj.setImage( "TruckToy:brickPile" ); %obj.setPosition( %posX, %posY ); - %obj.setSize( 4, 1 ); + %obj.setSize( 2, 1 ); %obj.setSceneLayer( TruckToy.BackgroundDomain-3 ); %obj.setSceneGroup( TruckToy.BackgroundDomain); %obj.setCollisionSuppress(); @@ -637,7 +638,7 @@ %particlePlayer.SetPosition( %x, %y ); %particlePlayer.SceneLayer = %layer; %particlePlayer.ParticleInterpolation = true; - %particlePlayer.Particle = "ToyAssets:bonfire"; + %particlePlayer.Particle = "TruckToy:bonfire"; %particlePlayer.SizeScale = %scale; %particlePlayer.CameraIdleDistance = TruckToy.CameraWidth * 0.8; SandboxScene.add( %particlePlayer ); @@ -647,45 +648,140 @@ // ----------------------------------------------------------------------------- +function TruckToy::createProjectilePool(%this) +{ + // Pre-build a fixed pool of projectiles so none are created mid-play + // (a 'new Sprite()' during play causes a visible hitch). Each one is fully + // configured once here, then parked invisible + inactive until needed. + // + // Worst case airborne = ceil(Lifetime 2.5s / fastest spawn 0.1s) = 25, + // plus headroom -> 32. The fastest spawn (100ms) is the Projectile Rate + // slider minimum registered in create(). + TruckToy.ProjectileLifetime = 2.5; + TruckToy.ProjectilePoolSize = 32; + TruckToy.ProjectilePoolIndex = 0; + + for ( %i = 0; %i < TruckToy.ProjectilePoolSize; %i++ ) + { + %projectile = new Sprite() { class = "TruckProjectile"; }; + %projectile.Animation = "TruckToy:Projectile_FireballAnim"; + %projectile.setSceneLayer( TruckToy.BackgroundDomain-2 ); + %projectile.setSceneGroup( TruckToy.ProjectileDomain ); + %projectile.FlipY = true; + %projectile.createCircleCollisionShape( 0.2 ); + %projectile.setCollisionGroups( TruckToy.GroundDomain ); + %projectile.CollisionCallback = true; + + // Park it: no render, no physics, won't fall. + %projectile.setVisible( false ); + %projectile.setActive( false ); + + SandboxScene.add( %projectile ); + TruckToy.ProjectilePool[%i] = %projectile; + } +} + +// ----------------------------------------------------------------------------- + +function TruckToy::createExplosionPool(%this) +{ + // Pre-build a fixed pool of impact explosions. A ParticlePlayer is heavier + // to spin up than a Sprite (it binds the asset and builds emitter/particle + // pools), so creating one per impact is the main remaining hitch. We build + // them once and replay them instead. + // + // Uses TruckToy:explosion, a local copy of ToyAssets:ImpactExplosion with + // LifeMode="STOP" instead of "KILL" -- KILL would make each player + // safeDelete() itself after firing, which would empty the pool. + // + // Worst case airborne = ceil(Lifetime 1s / fastest spawn 0.1s) = 10, + // plus headroom -> 16. + TruckToy.ExplosionPoolSize = 16; + TruckToy.ExplosionPoolIndex = 0; + + for ( %i = 0; %i < TruckToy.ExplosionPoolSize; %i++ ) + { + %explosion = new ParticlePlayer(); + %explosion.BodyType = static; + %explosion.Size = 10; + %explosion.SceneLayer = TruckToy.BackgroundDomain-1; + %explosion.ParticleInterpolation = true; + %explosion.Particle = "TruckToy:explosion"; + SandboxScene.add( %explosion ); + + // Adding to the scene auto-plays the player, so stop it immediately + // (no wait, no kill) to park it ready for reuse. + %explosion.stop( false, false ); + + TruckToy.ExplosionPool[%i] = %explosion; + } +} + +// ----------------------------------------------------------------------------- + function TruckToy::createProjectile(%this) { // Fetch the truck position. %truckPositionX = TruckToy.TruckBody.Position.x; - %projectile = new Sprite() { class = "TruckProjectile"; }; - %projectile.Animation = "ToyAssets:Projectile_FireballAnim"; + // Take the next projectile from the pool (ring buffer). + %projectile = TruckToy.ProjectilePool[TruckToy.ProjectilePoolIndex]; + TruckToy.ProjectilePoolIndex = (TruckToy.ProjectilePoolIndex + 1) % TruckToy.ProjectilePoolSize; + + // Cancel any pending recycle left over from this sprite's previous use. + if ( isEventPending( %projectile.RecycleEvent ) ) + cancel( %projectile.RecycleEvent ); + + // Reset physics state and reposition. %projectile.setPosition( getRandom( %truckPositionX - (TruckToy.CameraWidth * 0.2), %truckPositionX + (TruckToy.CameraWidth * 0.5) ), 12 ); - %projectile.setSceneLayer( TruckToy.BackgroundDomain-2 ); - %projectile.setSceneGroup( TruckToy.ProjectileDomain ); - %projectile.FlipY = true; + %projectile.setLinearVelocity( 0, 0 ); + %projectile.setAngularVelocity( 0 ); + %projectile.setAngle( 0 ); %projectile.Size = getRandom(0.5, 2); - %projectile.Lifetime = 2.5; - %projectile.createCircleCollisionShape( 0.2 ); - %projectile.setCollisionGroups( TruckToy.GroundDomain ); - %projectile.CollisionCallback = true; - SandboxScene.add( %projectile ); + + // Wake it up and (re)start the fireball animation. + %projectile.setActive( true ); + %projectile.setVisible( true ); + %projectile.setAwake( true ); + %projectile.playAnimation( "TruckToy:Projectile_FireballAnim" ); + + // Recycle it if it misses everything (mirrors the old 2.5s Lifetime). + %projectile.RecycleEvent = %projectile.schedule( TruckToy.ProjectileLifetime * 1000, "recycle" ); +} + +// ----------------------------------------------------------------------------- + +function TruckProjectile::recycle(%this) +{ + // Return the projectile to the pool: stop its pending recycle timer (if + // any), kill its momentum, then park it invisible + inactive for reuse. + if ( isEventPending( %this.RecycleEvent ) ) + cancel( %this.RecycleEvent ); + %this.RecycleEvent = ""; + + %this.setLinearVelocity( 0, 0 ); + %this.setAngularVelocity( 0 ); + %this.setActive( false ); + %this.setVisible( false ); } // ----------------------------------------------------------------------------- function TruckProjectile::onCollision(%this, %object, %collisionDetails) { - // Create an impact explosion at the projectiles position. - %particlePlayer = new ParticlePlayer(); - %particlePlayer.BodyType = Static; - %particlePlayer.Position = %this.Position; - %particlePlayer.Size = 10; - %particlePlayer.SceneLayer = TruckToy.BackgroundDomain-1; - %particlePlayer.ParticleInterpolation = true; - %particlePlayer.Particle = "ToyAssets:ImpactExplosion"; - %particlePlayer.SizeScale = getRandom(TruckToy.ExplosionScale, TruckToy.ExplosionScale * 1.5); - SandboxScene.add( %particlePlayer ); + // Replay an impact explosion from the pool at the projectile's position + // (ring buffer) -- no allocation during play. + %explosion = TruckToy.ExplosionPool[TruckToy.ExplosionPoolIndex]; + TruckToy.ExplosionPoolIndex = (TruckToy.ExplosionPoolIndex + 1) % TruckToy.ExplosionPoolSize; + %explosion.setPosition( %this.Position ); + %explosion.SizeScale = getRandom(TruckToy.ExplosionScale, TruckToy.ExplosionScale * 1.5); + %explosion.play( true ); // Start the camera shaking. SandboxWindow.startCameraShake( 10 + (3 * TruckToy.ExplosionScale), 1 ); - // Delete the projectile. - %this.safeDelete(); + // Return the projectile to the pool (instead of deleting it). + %this.recycle(); } // ----------------------------------------------------------------------------- @@ -729,7 +825,7 @@ // Rear tire. %tireRear = new Sprite(); %tireRear.setPosition( %posX-1.4, %posY-1.0 ); - %tireRear.setImage( "ToyAssets:tires" ); + %tireRear.setImage( "TruckToy:truckTire" ); %tireRear.setSize( 1.7, 1.7 ); %tireRear.setSceneLayer( TruckToy.TruckDomain-1 ); %tireRear.setSceneGroup( TruckToy.ObstacleDomain ); @@ -743,7 +839,7 @@ // Front tire. %tireFront = new Sprite(); %tireFront.setPosition( %posX+1.7, %posY-1.0 ); - %tireFront.setImage( "ToyAssets:tires" ); + %tireFront.setImage( "TruckToy:truckTire" ); %tireFront.setSize( 1.7, 1.7 ); %tireFront.setSceneLayer( TruckToy.TruckDomain-1 ); %tireFront.setSceneGroup( TruckToy.ObstacleDomain ); diff --git a/toybox/TruckToy/1/scripts/background.cs b/toybox/TruckToy/1/scripts/background.cs new file mode 100644 index 000000000..111b96d99 --- /dev/null +++ b/toybox/TruckToy/1/scripts/background.cs @@ -0,0 +1,198 @@ +//----------------------------------------------------------------------------- +// TruckToy parallax background. +// +// A small, data-driven parallax system. Each layer is a Scroller plus a parallax +// "factor": 0 = pinned to the screen (a far backdrop), 1 = moves with the world +// (foreground speed), values in between scroll proportionally. +// +// Every render frame each layer is cover-fit to the camera's visible size +// (getCameraArea extent) and centred on the post-view-limit render position +// (getCameraRenderPosition). The texture is then scrolled by centerX * factor, +// so the parallax is camera-driven: it stops when the truck stops. We update per +// render frame (RenderCallback) rather than per physics tick so the layers track +// the interpolated camera smoothly instead of "ticking" between ticks. +// +// To add a layer: drop in art that tiles seamlessly left<->right (a factor-0 +// layer needn't tile) and add one createParallaxLayer() call below, far -> near. +//----------------------------------------------------------------------------- + +function TruckToy::createBackground( %this ) +{ + // Rebuild the registries from scratch (reset() clears the scene, so the old + // Scroller objects / decorations are already gone). + %this.ParallaxCount = 0; + %this.ParallaxObjCount = 0; + + // Layers, ordered far -> near. %aspect must match the art's width:height so + // the fit-to-height sizing doesn't distort it (1024x512 -> 2.0, 1536x512 -> 3.0). + // Nearer layers use a higher factor and a lower scene layer (drawn in front). + // image factor aspect yOffFrac repeatX sceneLayer + %this.createParallaxLayer( "TruckToy:background_0", 0.05, 2.0, 0.0, 1, TruckToy.BackdropDomain ); + %this.createParallaxLayer( "TruckToy:background_1", 0.12, 2.0, 0.0, 1, TruckToy.BackdropDomain - 1 ); + + // Ground band sitting on/above the floor, looping seamlessly in X. It's drawn + // BEHIND the floor, so anything below FloorLevel is hidden; bottomY slides it + // up/down, worldHeight sets its thickness. (Image 1232x130 -> aspect 9.48.) + // image factor worldHeight bottomY aspect sceneLayer + %this.createGroundLayer( "TruckToy:background_2", 0.30, 3.25, TruckToy.FloorLevel - 0.5, 9.48, TruckToy.BackdropDomain - 2 ); + + // Drive the layers every render frame via SandboxScene::onSceneRender (below). + // RenderCallback (a Scene field, not a method) fires per rendered frame, so the + // layers track the interpolated camera; UpdateCallback (per physics tick) made + // the sky "tick" back into place between ticks. + SandboxScene.RenderCallback = true; + %this.updateParallax(); +} + +//----------------------------------------------------------------------------- + +// %aspect = image width/height; width is derived from it when fitting the +// image to the screen height, so a wrong value distorts the art. +// %yOffFrac = vertical offset as a fraction of view height (0 = centred). +function TruckToy::createParallaxLayer( %this, %image, %factor, %aspect, %yOffFrac, %repeatX, %sceneLayer ) +{ + %layer = new Scroller(); + %layer.setBodyType( "static" ); + %layer.setImage( %image ); + %layer.setRepeatX( %repeatX ); + %layer.setSceneLayer( %sceneLayer ); + %layer.setSceneGroup( TruckToy.BackdropDomain ); + %layer.setCollisionSuppress(); + SandboxScene.add( %layer ); + + // Register in the parallax table (sizing/positioning happens in updateParallax). + %i = %this.ParallaxCount; + %this.ParallaxLayer[%i] = %layer; + %this.ParallaxFactor[%i] = %factor; + %this.ParallaxAspect[%i] = %aspect; + %this.ParallaxYOffset[%i] = %yOffFrac; + %this.ParallaxMode[%i] = "screen"; + %this.ParallaxCount = %i + 1; + + return %layer; +} + +//----------------------------------------------------------------------------- + +// A world-anchored, horizontally-tiling band (e.g. distant terrain near the +// floor). Unlike the screen-fit layers it has an explicit world height and a +// fixed world Y, and loops seamlessly in X -- so the art MUST tile left<->right. +// %worldHeight = band height in world units; %bottomY = world Y of its bottom. +function TruckToy::createGroundLayer( %this, %image, %factor, %worldHeight, %bottomY, %aspect, %sceneLayer ) +{ + %layer = new Scroller(); + %layer.setBodyType( "static" ); + %layer.setImage( %image ); + %layer.setSceneLayer( %sceneLayer ); + %layer.setSceneGroup( TruckToy.BackdropDomain ); + %layer.setCollisionSuppress(); + SandboxScene.add( %layer ); + + // Register as a ground-mode layer (sizing/positioning happens in updateParallax). + %i = %this.ParallaxCount; + %this.ParallaxLayer[%i] = %layer; + %this.ParallaxFactor[%i] = %factor; + %this.ParallaxAspect[%i] = %aspect; + %this.ParallaxMode[%i] = "ground"; + %this.ParallaxHeight[%i] = %worldHeight; + %this.ParallaxBottomY[%i] = %bottomY; + %this.ParallaxCount = %i + 1; + + return %layer; +} + +//----------------------------------------------------------------------------- + +// Make an already-placed object parallax. Its current X is captured as the +// anchor; each frame it renders at f*anchorX + (1-f)*cameraX. f = 1 leaves it +// world-fixed (no change), f < 1 drifts slower (reads further back), f > 1 moves +// faster (reads closer). Only X is touched, so it still bobs with the world in Y. +// Call this AFTER the object is positioned (end of a create* function, or right +// after the create* call in reset()). +function TruckToy::registerParallaxObject( %this, %obj, %factor ) +{ + %i = %this.ParallaxObjCount; + %this.ParallaxObj[%i] = %obj; + %this.ParallaxObjAnchorX[%i] = getWord( %obj.getPosition(), 0 ); + %this.ParallaxObjFactor[%i] = %factor; + %this.ParallaxObjCount = %i + 1; + + return %obj; +} + +//----------------------------------------------------------------------------- + +function TruckToy::updateParallax( %this ) +{ + // View size comes from the camera area's extent (correct regardless of + // clamping). Screen-fit layers use the height; ground bands use the width. + %area = SandboxWindow.getCameraArea(); + %viewW = getWord( %area, 2 ) - getWord( %area, 0 ); + %viewH = getWord( %area, 3 ) - getWord( %area, 1 ); + + // The CENTRE must come from the render position: getCameraArea reports the + // area BEFORE the view limit is applied, so it diverges from what's actually + // drawn near the world edges. getCameraRenderPosition is post-limit (and + // there is no getCameraRenderArea, hence the split). + %render = SandboxWindow.getCameraRenderPosition(); + %centerX = getWord( %render, 0 ); + %centerY = getWord( %render, 1 ); + + for ( %i = 0; %i < %this.ParallaxCount; %i++ ) + { + %layer = %this.ParallaxLayer[%i]; + if ( !isObject( %layer ) ) + continue; + + if ( %this.ParallaxMode[%i] $= "ground" ) + { + // World-anchored band: explicit world height at a fixed world Y, tiled + // and looping seamlessly in X. Follows the camera in X (so it always + // covers the view) but stays put in Y -- so it bobs with the world like + // the floor, while the texture scroll gives the horizontal parallax. + %h = %this.ParallaxHeight[%i]; + %boxW = %viewW * 1.10; // cover the view width + %tileW = %h * %this.ParallaxAspect[%i]; // one tile at native aspect + %layer.setSize( %boxW, %h ); + %layer.setRepeatX( %boxW / %tileW ); // tile across the box, no distortion + %layer.setPosition( %centerX, %this.ParallaxBottomY[%i] + (%h * 0.5) ); + %layer.setScrollPositionX( %centerX * %this.ParallaxFactor[%i] ); + } + else + { + // Screen-fit backdrop: full image height maps top-to-bottom, pinned to + // the screen vertically; slight overscan (~2% off top & bottom) hides + // camera shake / the 1-frame render lag. Width follows the image aspect + // so it's not distorted -- draw the art wider than the screen for scroll + // room (tile via repeatX if the edges are seamless). + %h = %viewH * 1.04; + %w = %h * %this.ParallaxAspect[%i]; + %layer.setSize( %w, %h ); + %layer.setPosition( %centerX, %centerY + ( %this.ParallaxYOffset[%i] * %viewH ) ); + %layer.setScrollPositionX( %centerX * %this.ParallaxFactor[%i] ); + } + } + + // Parallax the registered decoration objects: render each at + // f*anchorX + (1-f)*cameraX (the layer model, applied to X only -- Y is left + // alone so they still bob with the world). + for ( %j = 0; %j < %this.ParallaxObjCount; %j++ ) + { + %obj = %this.ParallaxObj[%j]; + if ( !isObject( %obj ) ) + continue; + + %f = %this.ParallaxObjFactor[%j]; + %obj.setPositionX( (%f * %this.ParallaxObjAnchorX[%j]) + ((1 - %f) * %centerX) ); + } +} + +//----------------------------------------------------------------------------- + +// Per-frame scene hook. The scene fires this when RenderCallback is enabled +// (set in createBackground). Guarded so it's harmless if another toy is loaded. +function SandboxScene::onSceneRender( %this ) +{ + if ( isObject( TruckToy ) && TruckToy.ParallaxCount > 0 ) + TruckToy.updateParallax(); +}