From d18fe85e973c9a30de8760f5405efd645a1cc3f7 Mon Sep 17 00:00:00 2001 From: Frank Force Date: Sun, 4 Aug 2024 16:54:32 -0500 Subject: [PATCH] improve platformer example - use sprite atlas - fix weapon recoil - code cleanup --- .../{gameTileData.tmx => gameLevelData.tmx} | 4 ++-- .../{gameTileData.tsx => gameLevelData.tsx} | 0 examples/platformer/game.js | 17 ++++++++++++++- examples/platformer/gameCharacter.js | 12 ++++++----- examples/platformer/gameEffects.js | 15 ------------- examples/platformer/gameLevel.js | 19 +++++++++++------ .../{gameTileData.js => gameLevelData.js} | 4 ++-- examples/platformer/gameObjects.js | 20 +++++++++--------- examples/platformer/index.html | 2 +- examples/platformer/tiles.png | Bin 537 -> 6415 bytes 10 files changed, 50 insertions(+), 43 deletions(-) rename examples/platformer/data/{gameTileData.tmx => gameLevelData.tmx} (99%) rename examples/platformer/data/{gameTileData.tsx => gameLevelData.tsx} (100%) rename examples/platformer/{gameTileData.js => gameLevelData.js} (99%) diff --git a/examples/platformer/data/gameTileData.tmx b/examples/platformer/data/gameLevelData.tmx similarity index 99% rename from examples/platformer/data/gameTileData.tmx rename to examples/platformer/data/gameLevelData.tmx index 6e84530c..51c9ebdb 100644 --- a/examples/platformer/data/gameTileData.tmx +++ b/examples/platformer/data/gameLevelData.tmx @@ -1,9 +1,9 @@ - + - + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/examples/platformer/data/gameTileData.tsx b/examples/platformer/data/gameLevelData.tsx similarity index 100% rename from examples/platformer/data/gameTileData.tsx rename to examples/platformer/data/gameLevelData.tsx diff --git a/examples/platformer/game.js b/examples/platformer/game.js index 9fa2a689..a0f36bde 100644 --- a/examples/platformer/game.js +++ b/examples/platformer/game.js @@ -11,11 +11,26 @@ // show the LittleJS splash screen setShowSplashScreen(true); -let score, deaths; +let spriteAtlas, score, deaths; /////////////////////////////////////////////////////////////////////////////// function gameInit() { + // create a table of all sprites + spriteAtlas = + { + // large tiles + 'circle': tile(0), + 'crate': tile(2), + 'player': tile(3), + 'enemy': tile(5), + 'coin': tile(6), + + // small t + 'gun': tile(2,8), + 'grenade':tile(3,8), + }; + // enable touch gamepad on touch devices touchGamepadEnable = true; diff --git a/examples/platformer/gameCharacter.js b/examples/platformer/gameCharacter.js index fa913521..7211a816 100644 --- a/examples/platformer/gameCharacter.js +++ b/examples/platformer/gameCharacter.js @@ -210,15 +210,17 @@ class Character extends GameObject // update mirror if (moveInput.x && !this.dodgeTimer.active()) this.mirror = moveInput.x < 0; - - // set tile to use - const tile = this.isDead() ? 3 : - this.climbingLadder || this.groundTimer.active() ? 3 + 2*this.walkCyclePercent|0 : 4; - this.tileInfo.pos.x = tile * 16; } render() { + // update animation + const animationFrame = this.isDead() ? 0 : + this.climbingLadder || this.groundTimer.active() ? + 2*this.walkCyclePercent|0 : 1; + const playerTile = spriteAtlas['player']; + this.tileInfo.pos.x = playerTile.pos.x + playerTile.size.x*animationFrame; + let bodyPos = this.pos; if (!this.isDead()) { diff --git a/examples/platformer/gameEffects.js b/examples/platformer/gameEffects.js index be8c72dc..d6b1c334 100644 --- a/examples/platformer/gameEffects.js +++ b/examples/platformer/gameEffects.js @@ -255,19 +255,4 @@ class ParallaxLayer extends EngineObject // draw the parallax layer onto the main canvas mainContext.drawImage(this.canvas, pos.x, pos.y, scale.x, scale.y); } -} - -/////////////////////////////////////////////////////////////////////////////// -// background decoration - -let sky; - -function initBackground() -{ - // create sky object with gradient and stars - sky = new Sky; - - // create parallax layers - for (let i=3; i--;) - new ParallaxLayer(i); } \ No newline at end of file diff --git a/examples/platformer/gameLevel.js b/examples/platformer/gameLevel.js index 46f1374c..5adb834f 100644 --- a/examples/platformer/gameLevel.js +++ b/examples/platformer/gameLevel.js @@ -8,12 +8,12 @@ 'use strict'; -const tileType_ladder = -1; -const tileType_empty = 0; -const tileType_solid = 1; -const tileType_breakable = 2; +const tileType_ladder = -1; +const tileType_empty = 0; +const tileType_solid = 1; +const tileType_breakable = 2; -let player, playerStartPos, tileData, tileLayers, foregroundLayerIndex; +let player, playerStartPos, tileData, tileLayers, foregroundLayerIndex, sky; let levelSize, levelColor, levelBackgroundColor, levelOutlineColor, warmup; const setTileData = (pos, layer, data)=> @@ -27,9 +27,14 @@ function buildLevel() levelColor = randColor(hsl(0,0,.2), hsl(0,0,.8)); levelBackgroundColor = levelColor.mutate().scale(.4,1); levelOutlineColor = levelColor.mutate().add(hsl(0,0,.4)).clamp(); - loadLevel(); - initBackground(); + + // create sky object with gradient and stars + sky = new Sky; + + // create parallax layers + for (let i=3; i--;) + new ParallaxLayer(i); // apply decoration to all level tiles const pos = vec2(); diff --git a/examples/platformer/gameTileData.js b/examples/platformer/gameLevelData.js similarity index 99% rename from examples/platformer/gameTileData.js rename to examples/platformer/gameLevelData.js index 125fae5c..b5ba3a55 100644 --- a/examples/platformer/gameTileData.js +++ b/examples/platformer/gameLevelData.js @@ -7,7 +7,7 @@ } if(typeof module === 'object' && module && module.exports) { module.exports = data; - }})("gameTileData", + }})("gameLevelData", { "compressionlevel":-1, "height":64, "infinite":false, @@ -172,7 +172,7 @@ "tilesets":[ { "firstgid":1, - "source":"data\/gameTileData.tsx" + "source":"data\/gameLevelData.tsx" }], "tilewidth":16, "type":"map", diff --git a/examples/platformer/gameObjects.js b/examples/platformer/gameObjects.js index aa5d46cc..7619b7ac 100644 --- a/examples/platformer/gameObjects.js +++ b/examples/platformer/gameObjects.js @@ -66,7 +66,7 @@ class Crate extends GameObject { constructor(pos) { - super(pos, vec2(1), tile(2), (randInt(4))*PI/2); + super(pos, vec2(1), spriteAtlas['crate'], (randInt(4))*PI/2); this.color = hsl(rand(),1,.8); this.health = 5; @@ -92,7 +92,7 @@ class Coin extends EngineObject { constructor(pos) { - super(pos, vec2(1), tile(6)); + super(pos, vec2(1), spriteAtlas['coin']); this.color = hsl(.15,1,.5); } @@ -127,7 +127,7 @@ class Enemy extends GameObject { constructor(pos) { - super(pos, vec2(.9,.9), tile(5)); + super(pos, vec2(.9,.9), spriteAtlas['enemy']); this.drawSize = vec2(1); this.color = hsl(rand(), 1, .7); @@ -185,7 +185,7 @@ class Grenade extends GameObject { constructor(pos) { - super(pos, vec2(.2), tile(3,8)); + super(pos, vec2(.2), spriteAtlas['grenade']); this.beepTimer = new Timer(1); this.elasticity = .3; @@ -218,7 +218,7 @@ class Grenade extends GameObject // draw additive flash exploding setBlendMode(true); const flash = Math.cos(this.getAliveTime()*2*PI); - drawTile(this.pos, vec2(2), tile(0, 16), hsl(0,1,.5,.2-.2*flash)); + drawTile(this.pos, vec2(2), spriteAtlas['circle'], hsl(0,1,.5,.2-.2*flash)); setBlendMode(false); } } @@ -229,7 +229,7 @@ class Weapon extends EngineObject { constructor(pos, parent) { - super(pos, vec2(.6), tile(2,8)); + super(pos, vec2(.6), spriteAtlas['gun']); // weapon settings this.fireRate = 8; @@ -263,7 +263,7 @@ class Weapon extends EngineObject // update recoil if (this.recoilTimer.active()) - this.localAngle = lerp(this.recoilTimer.getPercent(), 0, this.localAngle); + this.localAngle = lerp(this.recoilTimer.getPercent(), this.localAngle, 0); this.mirror = this.parent.mirror; this.fireTimeBuffer += timeDelta; @@ -274,8 +274,8 @@ class Weapon extends EngineObject { // create bullet sound_shoot.play(this.pos); - this.localAngle = -rand(.2,.15); - this.recoilTimer.set(.4); + this.localAngle = -rand(.2,.25); + this.recoilTimer.set(.1); const direction = vec2(this.bulletSpeed*this.getMirrorSign(), 0); const velocity = direction.rotate(rand(-1,1)*this.bulletSpread); new Bullet(this.pos, this.parent, velocity, this.damage); @@ -324,7 +324,7 @@ class Bullet extends EngineObject if (this.range < 0) { const emitter = new ParticleEmitter( - this.pos, 0, .2, .1, 50, PI, tile(0), // pos, angle, emit info, tileInfo + this.pos, 0, .2, .1, 50, PI, spriteAtlas['circle'], // pos, emit info, tileInfo rgb(1,1,.1), rgb(1,1,1), // colorStartA, colorStartB rgb(1,1,.1,0), rgb(1,1,1,0),// colorEndA, colorEndB .1, .5, .1, .05, 0, // particleTime, sizeStart, sizeEnd, speed, angleSpeed diff --git a/examples/platformer/index.html b/examples/platformer/index.html index f0f55b62..299fcb34 100644 --- a/examples/platformer/index.html +++ b/examples/platformer/index.html @@ -12,5 +12,5 @@ - + \ No newline at end of file diff --git a/examples/platformer/tiles.png b/examples/platformer/tiles.png index c8680b69da6c117c629f2e2f42581c5808e3460a..39ae7b4c14046b252efa63bcc85d137ce94b0ee4 100644 GIT binary patch literal 6415 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 i(HJI^;1~uM(Aq2MLlTtv%T)6K0000