Difference between revisions of "Tutorial:Callback Functions (日本語)"

(Wrote Callback-Functions tutorial in japanese.)
 
m
(16 intermediate revisions by 5 users not shown)
Line 1: Line 1:
愛の[[:Category:Callbacks|コールバック(カテゴリは英語です)]]関数は次式で[[love.run]]様々なタスクを実行し、すべてオプションですします。と呼ばれていしかし、フル機能のゲームの経験は、おそらくほとんどすべての利用するでしょうので、それが何であるかを知るのが賢明です。
+
LÖVE において[[:Category:Callbacks (日本語)|コールバック]]関数は全てオプションであり各種作業を実行するために [[love.run (日本語)|love.run]] から呼び出されます。とはいえ、恐らく完全な機能のあるゲーム体験ではほぼ全てを利用するため、それらがなにかを熟知するのは賢明です。
  
コールバックは、プログラミングに新規または長期でそうでなければなじみのない人のため、ある意味で逆方向に動作する関数です。のような通常の関数の中で[[love.graphics.draw]]または数学。床には、あなたが、愛やLuaが何かを呼び出します。コールバックは、他の一方で、関数であり、特定の時間帯では、コードと愛呼び出します。これは、簡単にあなたのコードが組織的かつ最適に保つようになります。ゲームは最初の(他のコールバックの前)に開始されたとき「love.load」は一度だけ呼び出されますので、例えば、それはゲームコンテンツをロードするコードを置くのに良い場所だと、それ以外のものを準備します。
+
プログラミング未経験または用語に見覚えがない方々への説明として、コールバックとはある意味で逆方向に動作する受け身のような関数です。一方、 [[love.graphics.draw (日本語)|love.graphics.draw]] または Lua の <code>math.floor</code> といった攻めに相当する一般的な関数では、それを呼び出すと LÖVE または Lua が呼び出した関数の処理を行います。他方ではコールバックは開発者が処理内容を記述する関数であり、ある条件を満たすと LÖVE が自動的に呼び出します。または、コールバックの考え方の一つとして、描画、更新、キー入力などイベント発生ごとに呼びだされる独立した受動的なメインルーチンが複数あると考えても良いかもしれません。
  
==[[love.load]]==
+
コールバックにより品質の悪いコードが書きづらくなり、コードの組織化と最適化の維持を容易することができます。例えば、 <code>love.load</code> はゲームが最初に開始された時に一度だけ呼び出されるため (他の全てのコールバックの前に)、ゲーム・コンテンツの読み込みおよびその他何らかの準備を行うコードを置くには適している場所です。
 +
 
 +
 
 +
== [[love.load (日本語)|love.load]] ==
 
<source lang="lua">
 
<source lang="lua">
 
function love.load()
 
function love.load()
 
   image = love.graphics.newImage("cake.jpg")
 
   image = love.graphics.newImage("cake.jpg")
   local f = love.graphics.newFont(12)
+
   love.graphics.setNewFont(12)
  love.graphics.setFont(f)
+
   love.graphics.setColor(0,0,0)
   love.graphics.setColor(0,0,0,255)
 
 
   love.graphics.setBackgroundColor(255,255,255)
 
   love.graphics.setBackgroundColor(255,255,255)
 
end
 
end
 
</source>
 
</source>
この関数は、ゲームが開始されたときに、一度だけ呼ばれ、あなたは、リソースをロードする変数を初期化し、特定の設定をする場所、通常はされます。これらすべてのものは同様に他の場所で行われますが、ここでそれらを行うと、多くのシステムリソースを節約し、彼らは一度だけ行われることを意味することができます。
+
この関数はゲーム開始時に一度だけ呼び出されます。通常はリソースの読み込み、変数の初期化および特定の設定を行うために使用する場所です。それらはすべて <code>love.load</code> 以外でもできますが、ここで一度だけ行うとシステム・リソースの大幅な節約になります。
  
==[[love.update]]==
+
== [[love.update (日本語)|love.update]] ==
 
<source lang="lua">
 
<source lang="lua">
 
function love.update(dt)
 
function love.update(dt)
 
   if love.keyboard.isDown("up") then
 
   if love.keyboard.isDown("up") then
       num = num + 100 * dt -- これは、毎秒100で「num」をインクリメントしたい
+
       num = num + 100 * dt -- これは num を 1 秒ごとに 100 加算します。
 
   end
 
   end
 
end
 
end
 
</source>
 
</source>
この関数は、連続して呼び出され、あなたの数学のほとんどが行われている場所はおそらくなります。'dt'[[love.timer.getDelta|デルタ時間]]の略で、この関数は(通常は0.025714のような小さな値である)と呼ばれた最後の時間からの経過秒量です。
+
この関数は継続的に呼び出されます。よって、恐らくほとんどのあなたの計算を済ませる場所になります。 'dt' は"[[love.timer.getDelta (日本語)|デルタ・タイム]]の意味でありこの関数が以前に呼び出された時からの経過時間を秒数にて表しています (通常は 0.025714 のような小さな値です)。
  
==[[love.draw]]==
+
== [[love.draw (日本語)|love.draw]] ==
 
<source lang="lua">
 
<source lang="lua">
 
function love.draw()
 
function love.draw()
Line 32: Line 34:
 
end
 
end
 
</source>
 
</source>
<code>[[love.draw]]</code>すべての描画が発生するところです(これは既に十分に明らかにされなかった場合)とを呼び出す場合は、<code>[[love.graphics.draw]]</code>と、この関数の外でそれが起こっていないのいずれかが持っている任意の効果。この関数は、連続しているので、関数の末尾に「font/color/mode/etc」変更した場合、それは関数の先頭で物事に影響を与えることに留意してくださいと呼ばれています。たとえば、次のように
+
<code>[[love.draw (日本語)|love.draw]]</code> は全ての描画処理を集中的に行うための場所であり(まだ十分にそれが明白ではないならば)、この関数の外部で <code>[[love.graphics.draw (日本語)|love.graphics.draw]]</code> 族の関数を呼び出した場合は効果は一切ありません。この関数についても継続的に呼び出されるため、関数の終わりでフォント・配色・モード(方式)などを変更する場合に関数の始まりのものに影響することに留意してください。例えば:
 +
 
<source lang="lua">
 
<source lang="lua">
 
function love.load()
 
function love.load()
Line 45: Line 48:
 
</source>
 
</source>
  
''もっとすぐに来る。''
+
== [[love.mousepressed (日本語)|love.mousepressed]] ==
 +
{{newin (日本語)|[[0.10.0]]|100|type=異形}}
 +
<source lang="lua">
 +
function love.mousepressed(x, y, button, istouch)
 +
  if button == 1 then
 +
      imgx = x -- クリックされた場所へ画像を移動します。
 +
      imgy = y
 +
  end
 +
end
 +
</source>
 +
この関数はマウスのボタンが押されてボタンおよび押された場所の座標を受信する場合は常に呼び出されます。 button は押された任意のボタンの索引です。この関数は <code>[[love.mousereleased (日本語)|love.mousereleased]]</code> との併用でも非常に上手く動作します。
 +
 
 +
== [[love.mousereleased (日本語)|love.mousereleased]] ==
 +
{{newin (日本語)|[[0.10.0]]|100|type=異形}}
 +
<source lang="lua">
 +
function love.mousereleased(x, y, button, istouch)
 +
  if button == 1 then
 +
      fireSlingshot(x,y) -- この全くもって素晴らしいカスタム関数は他の所へ定義されます。
 +
  end
 +
end
 +
</source>
 +
この関数はマウスのボタンが離されてボタンおよび離された場所の座標を受信する場合は常に呼び出されます。この関数は <code>[[love.mousepressed (日本語)|love.mousepressed]]</code> と併用または独立して扱うこともできますが、それはいかなるの方法であっても接続されていません。
 +
 
 +
==[[love.keypressed (日本語)|love.keypressed]]==
 +
<source lang="lua">
 +
function love.keypressed(key)
 +
  if key == 'b' then
 +
      text = "The B key was pressed."
 +
  elseif key == 'a' then
 +
      a_down = true
 +
  end
 +
end
 +
</source>
 +
この関数はキーボードのキーが押されて押されたキーを受信する場合は常に呼び出されます。key は [[KeyConstant (日本語)|定数]] のいずれかです。この関数は <code>[[love.keyreleased (日本語)|love.keyreleased]]</code> との併用で非常に上手く動作します。
 +
 
 +
== [[love.keyreleased (日本語)|love.keyreleased]] ==
 +
<source lang="lua">
 +
function love.keyreleased(key)
 +
  if key == 'b' then
 +
      text = "The B key was released."
 +
  elseif key == 'a' then
 +
      a_down = false
 +
  end
 +
end
 +
</source>
 +
この関数はキーボードのキーが離されて離されたキーを受信する場合は常に呼び出されます。この関数は <code>[[love.keypressed (日本語)|love.keypressed]]</code> との併用または独立して扱うこともできますが、それはいかなるの方法であっても接続されません。
 +
 
 +
== [[love.focus (日本語)|love.focus]] ==
 +
<source lang="lua">
 +
function love.focus(f)
 +
  if not f then
 +
    print("LOST FOCUS")
 +
  else
 +
    print("GAINED FOCUS")
 +
  end
 +
end
 +
</source>
 +
この関数は利用者が LÖVE のウィンドウおよびその外をクリックしたときに呼び出されます。例えば、ウィンドウ表示のゲームで遊んでいるときに、利用者がインターネット・ブラウザーをクリックした場合に、それがゲームへ通知されゲームは自動的に一時停止することができます。
 +
<source lang="lua">
 +
function love.focus(f) gameIsPaused = not f end
  
'''それらは、コールバック関数とその基本的な使い方があります。'''
+
function love.update(dt)
 +
if gameIsPaused then return end
 +
 
 +
-- ここへあなたの love.update のコードを記載してください。
 +
end
 +
</source>
 +
 
 +
== [[love.quit (日本語)|love.quit]] ==
 +
<source lang="lua">
 +
function love.quit()
 +
  print("Thanks for playing! Come back soon!")
 +
end
 +
</source>
 +
この関数はウィンドウの閉じるボタン(大抵は×)が利用者によりクリックされたときに呼び出されます。例えば、遊技者がゲームを終了したいと決めたとき、閉じるボタンをクリックできます。その後、閉じる前に、そのゲームの状態を保存することができます。
 +
 
 +
それらはコールバック関数およびそれらの基本的な使用方法です。
 +
 
 +
== まとめ ==
 +
* <code>love.load</code> は起動直後の初期化処理に使用します。
 +
* <code>love.update</code> は座標やスコアなどゲームの内部処理や各種情報の更新するために使用します。
 +
* <code>love.draw</code> はグラフィックス描画処理で使用します。 LOVE にはオブジェクトの描画順序を決める Z (奥行・重なり)軸関連の関数がないため [[Tutorial:Drawing Order (日本語)]] を使用します。
 +
* <code>love.mousepressed</code> はマウスボタンが押されたときの処理を行います。
 +
* <code>love.mousereleased</code> はマウスボタンが離されたされた処理を行います。
 +
……
 +
 
 +
タイトル、ステージ、レベルといったゲーム全体のシーン、画面およびオブジェクトの挙動処理の切り替えにはゲームステート (State)を使用します。コールバック以外に、これらを理解することが LOVE のプログラミングセオリーや基本構造を理解する早道です。
 +
 
 +
ゲームステートの用例
 +
<source lang="Lua">
 +
GamesSates = { Opening = 0, Title = 1, Scoreboard = 2, Option = 3, Gameover = 4, Credit = 5,
 +
Stage 1 = 100, Stage2 = 200, Stage = 300, Stage4 = 400, Stage5 = 500, Stage6 = 600,
 +
Boss1 = ...
 +
}
 +
 
 +
 
 +
state = GamesSates.Opening
 +
 
 +
function love.draw()
 +
 
 +
if state = GamesSates.Opening then
 +
drawOpening()
 +
elseif state = GamesSates.Title then
 +
drawTitle()
 +
....
 +
end
 +
 
 +
end
 +
 
 +
function love.keypressed(key)
 +
 
 +
if state = GamesSates.Opening then
 +
keypressdOpening()
 +
elseif state = GamesSates.Title then
 +
keypressdTitle()
 +
....
 +
end
 +
end
 +
 
 +
--
 +
-- つまり、コールバックごとにゲームステートを定義します。
 +
-- しかし、if~then~elseif~else~end では記述方法としては、あまり明瞭ではなく保守性はあまりよろしくありません。
 +
-- より簡潔かつ明瞭で美しい方法に関して、dofile/require、 メタテーブル(setmetatable)やクラスを使用するのがセオリーです。
 +
-- 慣れてきたら if 以外の方法を使用しましょう(ゲームステート管理用のライブラリを使うのも一手です)。
 +
</source>
 +
 
 +
 
 +
== 関連 ==
 +
* [http://wa3.i-3-i.info/word12295.html コールバック関数 (callback function)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典]
 +
 
 +
* ゲームステートに関して
 +
** [https://love2d.org/forums/viewtopic.php?t=83569 Separate state files - LÖVE]
 +
** [http://www.lancarse.co.jp/blog/?p=1039 FSMの実装方法とより良い使い方 – Lancarse Blog]
 +
** [http://lua-users.org/wiki/FiniteStateMachine lua-users wiki: Finite State Machine]
 +
** [https://www.reddit.com/r/love2d/comments/2893c2/game_states/ Game States : love2d - Reddit]
 +
** [http://aalvarez.me/blog/posts/an-introduction-to-game-states-in-love2d.html An Introduction to Game States in Love2D - Andres Alvarez]
 +
** [https://gamedev.stackexchange.com/questions/34982/game-state-management-game-menu-titlescreen-etc lua - Game state management (Game, Menu, Titlescreen, etc) - Game Development Stack Exchange]
  
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]
 
 
{{#set:LOVE Version=0.6.0}}
 
{{#set:LOVE Version=0.6.0}}
{{#set:Description=Callback Functions}}
+
{{#set:Description=コールバック関数。}}
  
== Other languages ==
+
== そのほかの言語 ==
 
{{i18n|Tutorial:Callback Functions}}
 
{{i18n|Tutorial:Callback Functions}}

Revision as of 17:09, 3 July 2019

LÖVE においてコールバック関数は全てオプションであり各種作業を実行するために love.run から呼び出されます。とはいえ、恐らく完全な機能のあるゲーム体験ではほぼ全てを利用するため、それらがなにかを熟知するのは賢明です。

プログラミング未経験または用語に見覚えがない方々への説明として、コールバックとはある意味で逆方向に動作する受け身のような関数です。一方、 love.graphics.draw または Lua の math.floor といった攻めに相当する一般的な関数では、それを呼び出すと LÖVE または Lua が呼び出した関数の処理を行います。他方ではコールバックは開発者が処理内容を記述する関数であり、ある条件を満たすと LÖVE が自動的に呼び出します。または、コールバックの考え方の一つとして、描画、更新、キー入力などイベント発生ごとに呼びだされる独立した受動的なメインルーチンが複数あると考えても良いかもしれません。

コールバックにより品質の悪いコードが書きづらくなり、コードの組織化と最適化の維持を容易することができます。例えば、 love.load はゲームが最初に開始された時に一度だけ呼び出されるため (他の全てのコールバックの前に)、ゲーム・コンテンツの読み込みおよびその他何らかの準備を行うコードを置くには適している場所です。


love.load

function love.load()
   image = love.graphics.newImage("cake.jpg")
   love.graphics.setNewFont(12)
   love.graphics.setColor(0,0,0)
   love.graphics.setBackgroundColor(255,255,255)
end

この関数はゲーム開始時に一度だけ呼び出されます。通常はリソースの読み込み、変数の初期化および特定の設定を行うために使用する場所です。それらはすべて love.load 以外でもできますが、ここで一度だけ行うとシステム・リソースの大幅な節約になります。

love.update

function love.update(dt)
   if love.keyboard.isDown("up") then
      num = num + 100 * dt -- これは num を 1 秒ごとに 100 加算します。
   end
end

この関数は継続的に呼び出されます。よって、恐らくほとんどのあなたの計算を済ませる場所になります。 'dt' は"デルタ・タイムの意味でありこの関数が以前に呼び出された時からの経過時間を秒数にて表しています (通常は 0.025714 のような小さな値です)。

love.draw

function love.draw()
   love.graphics.draw(image, imgx, imgy)
   love.graphics.print("Click and drag the cake around or use the arrow keys", 10, 10)
end

love.draw は全ての描画処理を集中的に行うための場所であり(まだ十分にそれが明白ではないならば)、この関数の外部で love.graphics.draw 族の関数を呼び出した場合は効果は一切ありません。この関数についても継続的に呼び出されるため、関数の終わりでフォント・配色・モード(方式)などを変更する場合に関数の始まりのものに影響することに留意してください。例えば:

function love.load()
   love.graphics.setColor(0,0,0)
end

function love.draw()
   love.graphics.print("This text is not black because of the line below", 100, 100)
   love.graphics.setColor(255,0,0)
   love.graphics.print("This text is red", 100, 200)
end

love.mousepressed

LÖVE 0.10.0 から使用可能
この異形は以前のバージョンでは非対応です。
function love.mousepressed(x, y, button, istouch)
   if button == 1 then
      imgx = x -- クリックされた場所へ画像を移動します。
      imgy = y
   end
end

この関数はマウスのボタンが押されてボタンおよび押された場所の座標を受信する場合は常に呼び出されます。 button は押された任意のボタンの索引です。この関数は love.mousereleased との併用でも非常に上手く動作します。

love.mousereleased

LÖVE 0.10.0 から使用可能
この異形は以前のバージョンでは非対応です。
function love.mousereleased(x, y, button, istouch)
   if button == 1 then
      fireSlingshot(x,y) -- この全くもって素晴らしいカスタム関数は他の所へ定義されます。
   end
end

この関数はマウスのボタンが離されてボタンおよび離された場所の座標を受信する場合は常に呼び出されます。この関数は love.mousepressed と併用または独立して扱うこともできますが、それはいかなるの方法であっても接続されていません。

love.keypressed

function love.keypressed(key)
   if key == 'b' then
      text = "The B key was pressed."
   elseif key == 'a' then
      a_down = true
   end
end

この関数はキーボードのキーが押されて押されたキーを受信する場合は常に呼び出されます。key は 定数 のいずれかです。この関数は love.keyreleased との併用で非常に上手く動作します。

love.keyreleased

function love.keyreleased(key)
   if key == 'b' then
      text = "The B key was released."
   elseif key == 'a' then
      a_down = false
   end
end

この関数はキーボードのキーが離されて離されたキーを受信する場合は常に呼び出されます。この関数は love.keypressed との併用または独立して扱うこともできますが、それはいかなるの方法であっても接続されません。

love.focus

function love.focus(f)
  if not f then
    print("LOST FOCUS")
  else
    print("GAINED FOCUS")
  end
end

この関数は利用者が LÖVE のウィンドウおよびその外をクリックしたときに呼び出されます。例えば、ウィンドウ表示のゲームで遊んでいるときに、利用者がインターネット・ブラウザーをクリックした場合に、それがゲームへ通知されゲームは自動的に一時停止することができます。

function love.focus(f) gameIsPaused = not f end

function love.update(dt)
	if gameIsPaused then return end

	-- ここへあなたの love.update のコードを記載してください。
end

love.quit

function love.quit()
  print("Thanks for playing! Come back soon!")
end

この関数はウィンドウの閉じるボタン(大抵は×)が利用者によりクリックされたときに呼び出されます。例えば、遊技者がゲームを終了したいと決めたとき、閉じるボタンをクリックできます。その後、閉じる前に、そのゲームの状態を保存することができます。

それらはコールバック関数およびそれらの基本的な使用方法です。

まとめ

  • love.load は起動直後の初期化処理に使用します。
  • love.update は座標やスコアなどゲームの内部処理や各種情報の更新するために使用します。
  • love.draw はグラフィックス描画処理で使用します。 LOVE にはオブジェクトの描画順序を決める Z (奥行・重なり)軸関連の関数がないため Tutorial:Drawing Order (日本語) を使用します。
  • love.mousepressed はマウスボタンが押されたときの処理を行います。
  • love.mousereleased はマウスボタンが離されたされた処理を行います。

……

タイトル、ステージ、レベルといったゲーム全体のシーン、画面およびオブジェクトの挙動処理の切り替えにはゲームステート (State)を使用します。コールバック以外に、これらを理解することが LOVE のプログラミングセオリーや基本構造を理解する早道です。

ゲームステートの用例

GamesSates = { Opening = 0, Title = 1, Scoreboard = 2, Option = 3, Gameover = 4, Credit = 5,
			Stage 1 = 100, Stage2 = 200, Stage = 300, Stage4 = 400, Stage5 = 500, Stage6 = 600,
			Boss1 = ...
}


state = GamesSates.Opening

function love.draw()

	if state = GamesSates.Opening then
		drawOpening()
	elseif state = GamesSates.Title then
		drawTitle()
	....
	end

end

function love.keypressed(key)

	if state = GamesSates.Opening then
		keypressdOpening()
	elseif state = GamesSates.Title then
		keypressdTitle()
	....
	end
end

-- 
-- つまり、コールバックごとにゲームステートを定義します。
-- しかし、if~then~elseif~else~end では記述方法としては、あまり明瞭ではなく保守性はあまりよろしくありません。
-- より簡潔かつ明瞭で美しい方法に関して、dofile/require、 メタテーブル(setmetatable)やクラスを使用するのがセオリーです。
-- 慣れてきたら if 以外の方法を使用しましょう(ゲームステート管理用のライブラリを使うのも一手です)。


関連


そのほかの言語