« get me outta code hell

Action menu, not interactive - csb-game - Pixelly spin-off of the Command Synergy Battle system used in Final Fantasy XIII
summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2018-08-09 18:41:42 -0300
committerFlorrie <towerofnix@gmail.com>2018-08-09 18:41:42 -0300
commit2bccb6c55da3997483054e0bbea89d01841955fe (patch)
tree034abd3c0672856482bf3b6536edf8a8cb0db496
parentd1e06fa8dc626b6d5e848b9fea12665b12f3cac1 (diff)
Action menu, not interactive
-rw-r--r--index.js78
1 files changed, 77 insertions, 1 deletions
diff --git a/index.js b/index.js
index 00810ba..7f73c5d 100644
--- a/index.js
+++ b/index.js
@@ -74,9 +74,82 @@ class ATBBar {
   }
 }
 
+class ActionMenu {
+  constructor() {
+    this.canvas = document.createElement('canvas')
+
+    // State
+
+    this.options = [
+      ['Fire', 'Fira', 'Firaga'],
+      ['Blizz', 'Blizza', 'Blizzaga'],
+      ['Aero', 'Aerora', 'Aeroga'],
+      ['Zap', 'Zappa', 'Zappaga'],
+      ['Bio', 'Biora'],
+      ['Stun', 'Stunra', 'Stunga']
+    ]
+
+    this.currentOptionIndex = 3
+    this.uiLevel = 1 // 1-3 -- which of "fire", "fira", "firaga" is selected.
+
+    // Drawing
+
+    // Button height is 9, with a margin of 1 between each plus 1 at the top and bottom.
+    const visibleButtonCount = 3
+    this.canvas.height = 9 * visibleButtonCount + 1 * (visibleButtonCount - 1) + 2
+
+    // Should be the width of a 3-segment ATB bar.
+    this.canvas.width = 100
+  }
+
+  draw() {
+    const ctx = this.canvas.getContext('2d')
+    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
+
+    const startIndex = Math.max(0, this.currentOptionIndex - 1)
+    const endIndex = Math.min(this.options.length, startIndex + 3)
+
+    let y = 1
+    for (let i = startIndex; i < endIndex; i++) {
+      const maxLevel = this.options[i].length
+      const effectiveLevel = Math.min(maxLevel, this.uiLevel)
+      const text = this.options[i][effectiveLevel - 1]
+      const rectW = this.getRectW(effectiveLevel)
+      if (effectiveLevel < maxLevel) {
+        const ghostRectW = this.getRectW(maxLevel)
+        ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'
+        ctx.fillRect(1, y, ghostRectW, 9)
+        ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)'
+        ctx.strokeRect(1.5, y + 0.5, ghostRectW, 8)
+      }
+      if (i === this.currentOptionIndex) {
+        const mul = Math.sin(Date.now() / 200) * 0.125 + 0.875
+        ctx.fillStyle = `rgb(${mul * 255}, ${mul * 127}, 0)`
+      } else {
+        ctx.fillStyle = 'white'
+      }
+      ctx.fillRect(1, y, rectW, 9)
+      ctx.strokeStyle = 'black'
+      ctx.strokeRect(1.5, y + 0.5, rectW - 1, 8)
+      ctx.textAlign = 'center'
+      ctx.fillStyle = 'black'
+      ctx.font = '5px pixel-font'
+      ctx.fillText(text, 1 + Math.round(rectW / 2), y + 2 + 9 / 2)
+
+      y += 10
+    }
+  }
+
+  getRectW(level) {
+    return Math.floor((this.canvas.width - 2) / 3 * level)
+  }
+}
+
 const atbBar = new ATBBar()
 atbBar.queuedActions = [{label: 'Fire', size: 1}, {label: 'Fira', size: 2}, {label: 'Firaga', size: 3}]
 
+const actionMenu = new ActionMenu()
+
 let lastTime = Date.now()
 
 function drawLoop() {
@@ -86,11 +159,14 @@ function drawLoop() {
   atbBar.update(dt)
   atbBar.draw()
 
+  actionMenu.draw()
+
   const ctx = canvas.getContext('2d')
   ctx.clearRect(0, 0, canvas.width, canvas.height)
   ctx.fillStyle = '#EEE'
   ctx.fillRect(0, 0, canvas.width, canvas.height)
-  ctx.drawImage(atbBar.canvas, 20, canvas.height - 20 - atbBar.canvas.height)
+  ctx.drawImage(actionMenu.canvas, 20, canvas.height - 20 - actionMenu.canvas.height)
+  ctx.drawImage(atbBar.canvas, 20, canvas.height - 20 - actionMenu.canvas.height - 2 - atbBar.canvas.height)
 
   requestAnimationFrame(drawLoop)
 }