クラスを使う 4, 注目オブジェクトを矢印キーで動かす

-- 注目オブジェクトを矢印キーで動かす
-- 参考: 
-- 全体については http://compasstech.com.au/TNS_Authoring/Scripting/script_tut11.html ~ tut15.html
-- 下の move メソッドについては https://inspired-lua.org/index.php/2011/05/5-object-classes/

require "color"

W = platform.window:width()
H = platform.window:height()

TrackedObject = nil



Square = class()
function Square:init(x, y, sideLen, color)
   self.x           = x
   self.y           = y
   self.sideLen     = sideLen
   self.color       = color
   self.selected    = false
end
function Square:contains(x, y)
   return isInside(self.x, x, self.x + self.sideLen) and
          isInside(self.y, y, self.y + self.sideLen)
end
function Square:move(dx, dy)
   self.x = median(0, self.x + dx, W - self.sideLen) -- オブジェクトの描画始点を引数ぶんだけずらす。ただし画面の左右にオブジェクトが当たったらもう動かさない。
   self.y = median(0, self.y + dy, H - self.sideLen) -- オブジェクトの描画始点を引数ぶんだけずらす。ただし画面の上下にオブジェクトが当たったらもう動かさない。
end
function Square:paint(gc)
   gc:setColorRGB(self.color)
   gc:fillRect(self.x, self.y, self.sideLen, self.sideLen, self.color)
   if self.selected then
      gc:setColorRGB(color.black)
      gc:setPen("thick")
      gc:drawRect(self.x, self.y, self.sideLen, self.sideLen)
   end
end



Objects = {
   Square(10, 80, 50, 0xD90000),
   Square(70, 80, 50, 0xD96000),
   Square(130, 80, 50, 0xD98000),
   Square(190, 80, 50, 0xD9C000),
   Square(250, 80, 50, 0xD9FF00)
}


function on.arrowKey(key) -- 「注目オブジェクト」に何か入っていたら矢印キーで動かす。
   if TrackedObject then
      if     key == "up"    then TrackedObject:move( 0, -5)
      elseif key == "down"  then TrackedObject:move( 0,  5)
      elseif key == "left"  then TrackedObject:move(-5,  0)
      elseif key == "right" then TrackedObject:move( 5,  0)
      end
   end
end
function on.tabKey()
   if TrackedObject then
      TrackedObject.selected = false
   end
   for i = 1, #Objects do
      if Objects[i] == TrackedObject then
         TrackedObject = Objects[i+1]
         break
      end
   end
   if TrackedObject == nil then
       TrackedObject = Objects[1]
   end
   TrackedObject.selected = true
   platform.window:invalidate()
end
function on.backtabKey()
   if TrackedObject then
      TrackedObject.selected = false
   end
   for i = #Objects, 1, -1 do
      if Objects[i] == TrackedObject then
         TrackedObject = Objects[i-1]
         break
      end
   end
   if TrackedObject == nil then
       TrackedObject = Objects[#Objects]
   end
   TrackedObject.selected = true
   platform.window:invalidate()
end
function on.escapeKey()
   if TrackedObject then
      TrackedObject.selected = false
   end
   TrackedObject = nil
   platform.window:invalidate()
end
function on.paint(gc)
   for i = 1, #Objects do
      Objects[i]:paint(gc)
   end
end



-----------------------
-- general functions --
-----------------------
-- 中央値函数(下限値, 可変値, 上限値)
function median(lowerLimit, x, upperLimit) return math.max(lowerLimit, math.min(x, upperLimit)) end
-- 包含判定函数(下限値, 可変値, 上限値)
function isInside(lowerLimit, x, upperLimit) return lowerLimit <= x and x <= upperLimit end