(2018.1.28. 公開) (2018.8.26. 対象をバージョン 11 系列に変更)
画面に絵を出して動かせるようになったので、次はそれをキー入力でコントロールしてみる。前ページで書いたプログラムを改造して、四角が自動的に動くのではなく、矢印キーを押している間その方向に動かすようにする。
「現在あるキーが押されているかどうか」は、love.keyboard.isDown(キーの名前)
で判定できる。
if love.keyboard.isDown("right") then
-- 右矢印キーが押されている
elseif love.keyboard.isDown("left") then
-- 左矢印キーが押されている
elseif love.keyboard.isDown("up") then
-- 上矢印キーが押されている
elseif love.keyboard.isDown("down") then
-- 下矢印キーが押されている
end
この判定を love.update()
の中に入れればよい。移動速度を speed
という変数に入れておき、左右の矢印キーが押されたら x
座標を更新し、上下の矢印キーが押されたら y
座標を更新する。なお、LÖVE の座標系は、数学で一般的な xy 座標系とは異なり、「y 軸は下方向が正」であることに注意。
コーディング例。
-- サンプルプログラム 3-01 main.lua
-- 最初に1回だけ呼び出されるコールバック関数
function love.load()
width = love.graphics.getWidth() -- 現在の画面の横幅
height = love.graphics.getHeight() -- 現在の画面の高さ
love.graphics.setBackgroundColor(0, 0.24, 0) -- 背景を濃い緑色に
rsize = width / 25 -- 四角形のサイズ
x = 0 -- x 座標を0にする
y = 0 -- y 座標を0にする
speed = (width - rsize) / 3 -- 移動速度:1秒間に横幅の1/3
end
-- 定期的に呼び出されるコールバック関数
function love.update(dt)
local dx, dy, xx, yy -- これらの変数はこの関数の中でしか使わない
dx = 0
dy = 0
if love.keyboard.isDown("right") then -- 右矢印キーが押されている
dx = speed * dt
elseif love.keyboard.isDown("left") then -- 左矢印キーが押されている
dx = -speed * dt
elseif love.keyboard.isDown("up") then -- 上矢印キーが押されている
dy = -speed * dt
elseif love.keyboard.isDown("down") then -- 下矢印キーが押されている
dy = speed * dt
end
-- 新しい位置を計算する
xx = x + dx
yy = y + dy
-- 画面の中に収まっていれば x, y を新しい位置で置き換える
if xx >= 0 and xx < width - rsize then x = xx end
if yy >= 0 and yy < height - rsize then y = yy end
end
-- 画面を書き換えるコールバック関数
function love.draw()
love.graphics.setColor(1, 0.5, 0.5) -- 淡い赤色
love.graphics.rectangle("fill", x, y, rsize, rsize)
-- 塗りつぶした四角形を描く
end
2つの物体が衝突するのを判定するには、いろいろな方法が考えられる。一番単純なのは、x 座標の差・y 座標の差がともにある限界より小さくなった時に「衝突」と判定する方法(図1)。また、中心間の距離がある値より小さくなった時に「衝突」と判定する方法もある(図2)。物体が四角い場合は図1、丸い場合は図2の方が自然な判定になる。
「相手」キャラを円で表して、図1の方法で判定してみたのが、以下のコード。相手キャラは一定速度で動き、壁に当たったら跳ね返ることにした。
-- サンプルプログラム 3-02 main.lua
-- 最初に1回だけ呼び出されるコールバック関数
function love.load()
width = love.graphics.getWidth() -- 現在の画面の横幅
height = love.graphics.getHeight() -- 現在の画面の高さ
love.graphics.setBackgroundColor(0, 0.24, 0) -- 背景を濃い緑色に
rsize = width / 25 -- 四角形のサイズ
csize = width / 30 -- 相手キャラのサイズ
x = 0 -- x 座標を0にする
y = 0 -- y 座標を0にする
cx = width / 2 -- 相手キャラの x 座標を画面幅の1/2にする
cy = height / 2 -- 相手キャラの y 座標を画面高さの1/2にする
collide = 0 -- 衝突しているか
speed = (width - rsize) / 3 -- 移動速度:1秒間に横幅の1/3
cdx = speed * 0.5 -- 相手キャラの x 方向の移動速度
cdy = speed * 0.5 -- 相手キャラの y 方向の移動速度
end
-- 定期的に呼び出されるコールバック関数
function love.update(dt)
local dx, dy, xx, yy, w, dw -- これらの変数はこの関数の中でしか使わない
dx = 0
dy = 0
if love.keyboard.isDown("right") then -- 右矢印キーが押されている
dx = speed * dt
elseif love.keyboard.isDown("left") then -- 左矢印キーが押されている
dx = -speed * dt
elseif love.keyboard.isDown("up") then -- 上矢印キーが押されている
dy = -speed * dt
elseif love.keyboard.isDown("down") then -- 下矢印キーが押されている
dy = speed * dt
end
-- 新しい位置を計算する
xx = x + dx
yy = y + dy
-- 画面の中に収まっていれば x, y を新しい位置で置き換える
if xx >= 0 and xx < width - rsize then x = xx end
if yy >= 0 and yy < height - rsize then y = yy end
-- 相手キャラの位置を計算する
cx = cx + cdx * dt
cy = cy + cdy * dt
if cx < 0 or cx >= width - csize then
cdx = -cdx
cx = cx + 2 * cdx * dt
end
if cy < 0 or cy >= height - csize then
cdy = -cdy
cy = cy + 2 * cdy * dt
end
-- 衝突したか?
w = (rsize + csize) / 2
dw = (rsize - csize) / 2
collide = 0
if math.abs(x - cx + dw) < w and math.abs(y - cy + dw) < w then
collide = 1
end
end
-- 画面を書き換えるコールバック関数
function love.draw()
love.graphics.setColor(1, 0.5, 0.5) -- 淡い赤色
love.graphics.rectangle("fill", x, y, rsize, rsize)
-- 塗りつぶした四角形を描く
if collide == 0 then
love.graphics.setColor(0, 1, 1) -- 衝突したら濃い黄色
else
love.graphics.setColor(1, 1, 0) -- 衝突しなければ水色
end
love.graphics.circle("fill", cx + csize / 2, cy + csize / 2, csize / 2)
end
衝突判定のコードで、「x 座標の差が限界よりも小さくなったか」というのを math.abs(x - cx + dw) < w
で判定していることに注意。図1の「x 座標」は「物体の中心の x 座標」を意味している。「四角形の中心」の x 座標は x + rsize / 2
, 「円の中心」の x 座標は cx + csize / 2
なので、これらの差は (x + rsize / 2) - (cx + csize / 2)
となる。これを x - cx + (rsize - csize) / 2
と変形し、(rsize - csize) / 2
を dw
と置き換えて、さらに負の値である可能性を考慮して絶対値 math.abs()
をとると、上の式が得られる。
こんな風になりました。的が小さくてなかなか当たらない(苦笑)
目次