« get me outta code hell

Prototype XYZ - csb-game - Pixelly spin-off of the Command Synergy Battle system used in Final Fantasy XIII
summary refs log tree commit diff
path: root/index.js
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2018-08-23 15:32:54 -0300
committerFlorrie <towerofnix@gmail.com>2018-08-23 15:32:54 -0300
commit95630bb96d6b9ac709b6f2e6800fcbe8d312ed6e (patch)
tree4e80df8bf71d506daa40b16faa6d9acb673163a7 /index.js
parent6024c1014a727c5627ed0d0c5b919094361c6dfe (diff)
Prototype XYZ
Diffstat (limited to 'index.js')
-rw-r--r--index.js70
1 files changed, 51 insertions, 19 deletions
diff --git a/index.js b/index.js
index 693b5e3..8375346 100644
--- a/index.js
+++ b/index.js
@@ -47,8 +47,11 @@ const isHealingAction = action => {
 
 class Sprite {
   constructor() {
+    // X is left/right, Z is forwards/backwards, Y is up/down.
     this.x = 0
     this.y = 0
+    this.z = 0
+
     this.canvas = document.createElement('canvas')
     this.canvas.width = 1
     this.canvas.height = 1
@@ -919,33 +922,52 @@ class Battle {
       }
     }
 
-    ctx.save() // Begin camera-translated drawing
-    ctx.translate(Math.round(-camera.x), Math.round(-camera.y))
+    // ctx.translate(Math.round(-camera.x), Math.round(-camera.y))
+    const spriteData = []
     for (const sprite of [this.backdrop, ...this.getAllBattleCharacters(), ...this.animationEntities]) {
-      const x = Math.round(sprite.x - sprite.canvas.width / 2)
-      const y = Math.round(sprite.y - sprite.canvas.height / 2)
+      // const x = Math.round(sprite.x - sprite.canvas.width / 2)
+      // const y = Math.round(sprite.y - sprite.canvas.height / 2)
       sprite.draw()
-      ctx.drawImage(sprite.canvas, x, y)
 
+      const cameraOffsetX = sprite.x - camera.x
+      const cameraOffsetY = sprite.y - camera.y
+      const cameraOffsetZ = sprite.z - camera.z
+      const scaleRatio = camera.getScaleRatio(cameraOffsetZ)
+      const drawX = scaleRatio * cameraOffsetX
+      const drawY = scaleRatio * cameraOffsetY
+      const canvasOffsetDrawX = drawX - sprite.canvas.width / 2
+      const canvasOffsetDrawY = drawY - sprite.canvas.height / 2
+      spriteData.push({drawX, drawY, canvasOffsetDrawX, canvasOffsetDrawY, scaleRatio, sprite})
+    }
+    window.spriteData = spriteData
+
+    for (const { canvasOffsetDrawX, canvasOffsetDrawY, sprite: { canvas } } of spriteData) {
+      ctx.drawImage(canvas, Math.round(canvasOffsetDrawX), Math.round(canvasOffsetDrawY))
+    }
+
+    for (const { drawX, canvasOffsetDrawY, sprite } of spriteData) {
       const overlayHPBar = overlayHPBars.find(o => o.battleCharacter === sprite)
       if (overlayHPBar) {
-        overlayHPBar.x = sprite.x - camera.x
-        overlayHPBar.y = y - camera.y
+        overlayHPBar.x = drawX
+        overlayHPBar.y = canvasOffsetDrawY
       }
     }
 
-    for (const battleCharacter of this.getAllBattleCharacters()) {
-      if (battleCharacter.isExecutingAction) {
-        const sprite = battleCharacter
-        const { label } = battleCharacter.actionBeingExecuted
+    for (const { sprite, drawX, offsetDrawY } of spriteData) {
+      if (!(sprite instanceof BattleCharacter)) {
+        continue
+      }
+
+      if (sprite.isExecutingAction) {
+        const { label } = sprite.actionBeingExecuted
 
         ctx.font = '5px pixel-font'
         const width = ctx.measureText(label).width + 4
-        const x = Math.round(sprite.x - width / 2)
-        const y = Math.round(sprite.y - sprite.canvas.height / 2)
+        const x = Math.round(drawX - width / 2)
+        const y = Math.round(offsetDrawY)
 
         let textFillStyle
-        if (battleCharacter.team === this.playerCharacter.team) {
+        if (sprite.team === this.playerCharacter.team) {
           ctx.fillStyle = 'rgba(45, 128, 255, 0.3)'
           ctx.strokeStyle = 'rgb(30, 85, 170)'
         } else {
@@ -960,10 +982,9 @@ class Battle {
         ctx.fillText(label, x + 3, y + 7)
       }
     }
-    ctx.restore() // End camera-translated drawing
+    // ctx.restore() // End camera-translated drawing
 
     if (this.nearlyDeadAnim) {
-      // TODO: Gradient
       const height = Math.min(60, this.canvas.height / 4)
       const opacity = (1 - this.nearlyDeadAnim.time) * (0.35 + Math.sin(Date.now() / 300) / 5)
       const gradient = ctx.createLinearGradient(0, 0, 0, height)
@@ -1029,10 +1050,12 @@ class Battle {
     }
 
     for (const { x, y, battleCharacter } of overlayHPBars) {
+      const { drawX: spriteX, canvasOffsetDrawY: spriteY } = spriteData.find(o => o.sprite === battleCharacter)
+
       const hpBar = battleCharacter.hpBar
       hpBar.draw()
-      const drawX = Math.min(this.canvas.width - 10 - hpBar.canvas.width, Math.max(10 + hpBar.labelCanvas.width, Math.round(x - hpBar.canvas.width / 2)))
-      const drawY = Math.min(this.canvas.height - 20, Math.max(10, Math.round(y - hpBar.canvas.height)))
+      const drawX = Math.min(this.canvas.width - 10 - hpBar.canvas.width, Math.max(10 + hpBar.labelCanvas.width, Math.round(spriteX - hpBar.canvas.width / 2)))
+      const drawY = Math.min(this.canvas.height - 20, Math.max(10, Math.round(spriteY - hpBar.canvas.height)))
       ctx.drawImage(hpBar.canvas, drawX, drawY)
       ctx.drawImage(hpBar.labelCanvas, drawX - hpBar.labelCanvas.width - 2, drawY - 1)
     }
@@ -1223,6 +1246,7 @@ class Camera extends Sprite {
     this.spriteToFollow = null
     this.width = 200
     this.height = 200
+    this.focalLength = 300
   }
 
   update(dt) {
@@ -1253,6 +1277,10 @@ class Camera extends Sprite {
       y: sprite.y - this.height / 2
     }
   }
+
+  getScaleRatio(z) {
+    return this.focalLength / (this.focalLength + z)
+  }
 }
 
 class BattleCamera extends Camera {
@@ -1289,6 +1317,7 @@ class MagicProjectile {
   constructor(caster, target, action) {
     this.x = caster.x
     this.y = caster.y
+    this.z = caster.z
 
     this.target = target
     this.action = action
@@ -1302,10 +1331,12 @@ class MagicProjectile {
     // TODO: Good animation, make distance affect acceleration, not velocity
     const xvel = 5 * (this.target.x - this.x)
     const yvel = 5 * (this.target.y - this.y)
+    const zvel = 5 * (this.target.z - this.z)
     this.x += dt * xvel
     this.y += dt * yvel
+    this.z += dt * zvel
 
-    if (Math.abs(this.target.x - this.x) <= 5 && Math.abs(this.target.y - this.y) <= 5) {
+    if (Math.abs(this.target.x - this.x) <= 5 && Math.abs(this.target.y - this.y) <= 5 && Math.abs(this.target.z - this.z) <= 5) {
       if (this.action.target === 'enemy') {
         if (this.action.damage) this.target.takeDamage(this.action.damage)
         if (this.action.stun) this.target.addStunTime(this.action.stun || 0)
@@ -1319,6 +1350,7 @@ class MagicProjectile {
 
       this.target.xvel += 2 * xvel * this.target.knockbackMultiplier * actionKB
       this.target.yvel += 2 * yvel * this.target.knockbackMultiplier * actionKB
+      this.target.zvel += 2 * zvel * this.target.knockbackMultiplier * actionKB
 
       this.discarded = true
     }