mieki256's diary



2017/11/24(金) [n年前の日記]

#1 [lua][love2d] love2dで敵をたくさん出してみる

Luaでクラスを作る方法が分かってきたので love2d で実験。雑魚的相当のオブジェクトをたくさん出せそうかテスト。

こんな感じに。

enemys_test01_ss.gif

以下の環境で動かしてみたけれど、どちらも同じように動作した。

画像とソース。 :

使用画像は以下。License : CC0 / Public Domain ってことで。

_bg_640x480_02.png
_enemy02.png

ソースは以下。

_conf.lua
function love.conf(t)
  t.window.title = "Enemys Test01"
  t.window.width = 1280
  t.window.height = 720
  t.window.vsync = true
  -- t.window.fullscreen = true
  -- t.window.fullscreentype = "exclusive"
end

_main.lua
function love.load()
  -- init

  -- set filter
  love.graphics.setDefaultFilter("nearest", "nearest")

  scr_w = 640
  scr_h = 480
  canvas = love.graphics.newCanvas(scr_w, scr_h)

  -- get window width and height
  wdw_w, wdw_h = love.graphics.getDimensions()
  scr_scale = math.min((wdw_w / scr_w), (wdw_h / scr_h))
  scr_ofsx = (wdw_w - (scr_w * scr_scale)) / 2
  scr_ofsy = (wdw_h - (scr_h * scr_scale)) / 2

  -- load image
  bgimg = love.graphics.newImage("bg_640x480_02.png")
  enemy_img = love.graphics.newImage("enemy02.png")

  -- define enemy class
  Enemy = {}
  Enemy.new = function(x, y, dx, dy, xw, ang, angspd, img)
    local obj = {}
    obj.activate = true
    obj.x = x
    obj.y = y
    obj.dx = dx
    obj.dy = dy
    obj.bx = x
    obj.by = y
    obj.xw = xw
    obj.angle = ang
    obj.angspd = angspd
    obj.img = img
    obj.img_w = img:getWidth()
    obj.img_h = img:getHeight()
    setmetatable(obj, {__index = Enemy})
    return obj
  end

  Enemy.update = function(self, dt)
    if not self.activate then return end

    self.bx = self.bx + self.dx * dt
    self.y = self.y + self.dy * dt
    self.x = self.bx + self.xw * math.sin(math.rad(self.angle))
    self.angle = (self.angle + self.angspd * dt) % 360.0
    if self.y - self.img_h > scr_h then self.activate = false end
  end

  Enemy.draw = function(self)
    if not self.activate then return end

    local x = self.x - self.img_w / 2
    local y = self.y - self.img_h / 2
    local ang = math.rad(self.angle)
    local scale = 1.0
    local ox = self.img_w / 2
    local oy = self.img_h / 2
    love.graphics.draw(self.img, x, y, ang, scale, scale, ox, oy)
  end

  -- work
  enemys = {}
  born_timer = 0.0
  math.randomseed(0)

  -- framerate steady
  min_dt = 1 / 60
  next_time = love.timer.getTime()
end

function love.update(dt)
  -- update
  next_time = next_time + min_dt
  if dt > 1.0 then return end

  born_timer = born_timer + dt
  if born_timer >= 0.3 then
    -- enemy born
    born_timer = born_timer - 0.3
    x = math.random(scr_w)
    y = -32
    dx = 0
    dy = 40 + math.random(80)
    xw = 50
    ang = math.random(360)
    angspd = 240
    obj = Enemy.new(x, y, dx, dy, xw, ang, angspd, enemy_img)
    table.insert(enemys, obj)
  end

  -- move enemys
  for i, spr in ipairs(enemys) do
    spr:update(dt)
  end

  -- remove enemy
  local elen = #enemys
  for i=elen,1,-1 do
    if not enemys[i].activate then
      table.remove(enemys, i)
    end
  end
end

function love.draw()
  -- set canvas
  love.graphics.setCanvas(canvas)

  -- draw BG
  love.graphics.setColor(255, 255, 255)
  love.graphics.draw(bgimg, 0, 0)

  -- draw objects
  love.graphics.setColor(255, 255, 255)
  for i, spr in ipairs(enemys) do
    spr:draw()
  end

  -- unset canvas
  love.graphics.setCanvas()

  -- draw canvas to window
  love.graphics.setColor(255, 255, 255)
  love.graphics.draw(canvas, scr_ofsx, scr_ofsy, 0, scr_scale, scr_scale)

  love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10)
  love.graphics.print("env: "..tostring(love.system.getOS()), 10, 40)
  love.graphics.print("enemys: "..tostring(#enemys), 10, 60)

  if love.system.getOS() == "Windows" then
    -- wait
    local cur_time = love.timer.getTime()
    if next_time <= cur_time then
      next_time = cur_time
    else
      love.timer.sleep(next_time - cur_time)
    end
  end
end

function love.keypressed(key, isrepeat)
  -- ESC to exit
  if key == "escape" then
    love.event.quit()
  end
end

画像とソースをテキトーな名前のフォルダに入れて、love フォルダ名、で実行。

少し解説。 :

上記のソースでは、Enemy というクラスを作って処理をしてる。以下の3つのメソッドを用意した。
  • クラス生成用メソッド Enemy.new
  • 座標更新処理用メソッド Enemy.update
  • 描画処理用メソッド Enemy.draw

Luaでクラスを作る際の書き方については、以下の解説ページが参考になった。

_Luaでオブジェクト指向(1)―基本はコロン記法とメタテーブル - Minecraftとタートルと僕
_blog/luaoo.md at master - kengonakajima/blog

色んな書き方があるっぽいけど…。
  • hoge.new の中で他のメソッドも書くやり方だと、インスタンスを作るたびにメソッドが別領域に作られてメモリの無駄遣いになる。
  • かといって setmetatable を使うと、メソッドは同じ領域を使うからメモリの面では助かるけど、メソッド名の検索が一々入るから処理速度は遅くなる。
さて、どっちがいいのだろうなと…。

以上、1 日分です。

過去ログ表示

Prev - 2017/11 - Next
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project