2019/12/23(月) [n年前の日記]
#1 [love2d] love2dで多関節というか蛇モドキを書いてみたり
せっかく love2d をまた触り始めたので、ちょっと何か書いてみようかと。多関節、というか蛇モドキのソレを書いてみたり。
動作確認環境は、Windows10 x64 1909 + love2d 11.3。
こんな感じになった。
動作確認環境は、Windows10 x64 1909 + love2d 11.3。
こんな感じになった。
◎ ソース。 :
ソースは以下。
_conf.lua
_main.lua
動作に必要な画像は以下。自作した画像なので、CC0 / Public Domain ってことで。
_circle01_96x96_32col.png
上記の3つのファイル、conf.lua、main.lua、circle01_96x96_32col.png を、任意のフォルダに置いて、「love フォルダ名」で実行できる。
_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 フォルダ名」で実行できる。
◎ 解説。 :
やってることは簡単。頭の座標を毎フレーム、バッファに記録し続けて、体の部分は、バッファから座標値を取り出して描画してるだけ。
後は、頭だけをイイ感じに動かしてやれば、その動きに体が追従してくれるわけで。
上記のソースでは、頭はマウスカーソルを追いかけるようにしてみたり。love2d でマウスカーソルの座標を取得したい場合、以下のように書けばいい。
余談。大昔に関わった某ゲームに出てくる、蛇みたいな敵(2種類)は、この処理で動かしていました。頭は、sin,cos で動かした記憶が…。たしかそのはず…。
頭の座標を記録するバッファ
┌─────┐
│ 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 に前フレームからの経過時間が入る仕様であることを考えると、場合によっては可変フレームレートで動く場面もありそうだなと。そうなると、おそらくおかしな見た目になりそうな予感。
さて、可変フレームレートにも対応させようとした場合、どう書けばいいのだろう…。
love2d で更新処理を担当する love.update(dt) が、dt に前フレームからの経過時間が入る仕様であることを考えると、場合によっては可変フレームレートで動く場面もありそうだなと。そうなると、おそらくおかしな見た目になりそうな予感。
さて、可変フレームレートにも対応させようとした場合、どう書けばいいのだろう…。
[ ツッコむ ]
以上です。