mieki256's diary



2019/12/23(月) [n年前の日記]

#1 [love2d] love2dで多関節というか蛇モドキを書いてみたり

せっかく love2d をまた触り始めたので、ちょっと何か書いてみようかと。多関節、というか蛇モドキのソレを書いてみたり。

動作確認環境は、Windows10 x64 1909 + love2d 11.3。

こんな感じになった。

ソース。 :

ソースは以下。

_conf.lua
function love.conf(t)
  t.version = "11.3" -- love2d version
  t.window.title = "Snake - love2d"
  t.window.vsync = 1
  t.window.width = 1280
  t.window.height = 720

  -- t.window.fullscreen = true
  -- t.window.fullscreentype = "exclusive"
end

_main.lua
-- Snake on love2d

function love.load()
  love.graphics.setDefaultFilter("nearest", "nearest")

  img = love.graphics.newImage("circle01_96x96_32col.png")

  x = love.graphics.getWidth() / 2
  y = love.graphics.getHeight() / 2

  pos_buf = {}
  for i = 1, 128 do
    pos_buf[i] = {x, y}
  end
  idx = #pos_buf
end

function love.update(dt)
  -- move head
  mx, my = love.mouse.getPosition()
  local dx = (mx - x) * 0.1
  local dy = (my - y) * 0.1
  x = x + dx
  y = y + dy

  -- Updated index to record head position
  idx = idx - 1
  if idx <= 0 then
    idx = #pos_buf
  end

  -- record head position
  pos_buf[idx] = {x, y}
end

function love.draw()
  -- fill window background
  love.graphics.clear(0.4, 0.7, 0.8, 1.0)

  -- draw snake
  local ox, oy = img:getWidth() / 2, img:getHeight() / 2
  love.graphics.setColor(1.0, 1.0, 1.0, 1.0)

  for i = 16, 0, -1 do
    local n = ((idx + i * 4) % #pos_buf) + 1
    local px = pos_buf[n][1]
    local py = pos_buf[n][2]
    love.graphics.draw(img, px, py, 0, 1.0, 1.0, ox, oy)
  end

  -- draw FPS txet
  love.graphics.print("FPS: " .. tostring(love.timer.getFPS()), 2, 2)
end

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

動作に必要な画像は以下。自作した画像なので、CC0 / Public Domain ってことで。

_circle01_96x96_32col.png

上記の3つのファイル、conf.lua、main.lua、circle01_96x96_32col.png を、任意のフォルダに置いて、「love フォルダ名」で実行できる。

解説。 :

やってることは簡単。頭の座標を毎フレーム、バッファに記録し続けて、体の部分は、バッファから座標値を取り出して描画してるだけ。

頭の座標を記録するバッファ
┌─────┐
│  x, y    │
├─────┤
│  x, y    │ ← 頭の座標を記録
├─────┤
│  x, y    │
├─────┤
│  x, y    │ ← 体1の座標
├─────┤
│  x, y    │
├─────┤
│  x, y    │ ← 体2の座標
├─────┤
     ...
├─────┤
│  x, y    │ ← 体nの座標
├─────┤
│  x, y    │
├─────┤
│  x, y    │
└─────┘

後は、頭だけをイイ感じに動かしてやれば、その動きに体が追従してくれるわけで。

上記のソースでは、頭はマウスカーソルを追いかけるようにしてみたり。love2d でマウスカーソルの座標を取得したい場合、以下のように書けばいい。
  mx, my = love.mouse.getPosition()
mx, my に、マウスカーソル座標 x, y が入る。

余談。大昔に関わった某ゲームに出てくる、蛇みたいな敵(2種類)は、この処理で動かしていました。頭は、sin,cos で動かした記憶が…。たしかそのはず…。

課題。 :

この処理はフレームレートが安定していることを前提にして書いてるし、手元の Windows環境では約60FPSで動いちゃってるので、それらしく見えてはいるけれど。

love2d で更新処理を担当する love.update(dt) が、dt に前フレームからの経過時間が入る仕様であることを考えると、場合によっては可変フレームレートで動く場面もありそうだなと。そうなると、おそらくおかしな見た目になりそうな予感。

さて、可変フレームレートにも対応させようとした場合、どう書けばいいのだろう…。

以上です。

過去ログ表示

Prev - 2019/12 - 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 31

カテゴリで表示

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


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

Powered by hns-2.19.6, HyperNikkiSystem Project