【Defold】関数を使って処理をまとめる

# はじめに
この記事では、Defoldで使える**関数(function)**について紹介します。

# functionって何？
Defoldでスクリプトを作成すると、中身がこんな感じになっています。
![2021-05-03_08h12_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620977/c5ddd0df-147a-48c6-5a8c-5de37e96e931.png)
それぞれんおファンクションの意味は後半で説明します。

ファンクションは以下のようになっています。

```lua
function fun_name(a, b, c)
    -- 中身
end
```
**fun_name**っていうのは、ファンクションの名前です。分かりやすいものにしてください。
引数(ひきすう)と呼ばれる **a, b, c** の変数は使うもの何個でもOKです。また、どんな名前でもOKです。
これだけです。

ファンクションを実行すると、中身のプログラムが実行されます。
ファンクションを実行するには、**function init** などで、

```lua
fun_name(a, b, c)
```
と入力します。ファンクションの中で使う変数の指定を行います。
もし **b** が数字だったら b じゃなくて 15 とか入力しても大丈夫です。


# いつ使うの？？
ファンクションは基本的に処理をまとめるためにあります。

たとえば、マリオが死ぬときには、(想像の話で実際は知りませんが)

1. 残機を 1 減らす
2. ゲームオーバーの効果音を流す
3. プレイ中のステージの画面から、ステージ選択の画面に移動する

といったように、「マリオが死んだ」ときに行う 、一連の処理を、例えば **player_death()** と置きます。
何が便利かって言うと、同じ処理を何回も書かなくていいんです。

マリオの死因って、**"クリボーに当たった"、"穴に落ちた", "毒に触れた"** などなど様々な要因があるじゃないですか。
毒にあたったときにいちいち、「残機を減らして、ゲームオーバーの効果音をながして、、、」ってプログラムを書くのは大変ですし、抜けがあったりします。さらに、「死んだときにマリオが落ちていくアニメーションをつけよう！」と思ったときは、すべての死因に対して、追加しなければなりません。

それをね、「ファンクションを作って、死んだときに **player_death()** を実行する」というように管理すると、追加のときもファンクションを変えればいいし、ミスがあったらそこだけ直せばいいんです。

**「色んな所で同じ処理をするんだったら、1個書いて使いまわそう！」**という感じです。 

(余談)
まとまった処理に名前をつけたいときに、1回しか使わないファンクションを作ることもあります。

# 引数を使いたい
いままでは **player_death()** という引数(カッコの中の物たち)が無いファンクションを説明してきました。
これだとちょっと不便なんですよね。

例えばプレイヤーのHPを減らす関数を作ろうと思います。

```lua:HPを1減らす関数
function reduce_hp()
    hp = hp - 1
    --[[
        HPが減ったときに行うその他の処理
    ]]
end
```
これだとHPを2減らすときに、

```
reduce_hp()
reduce_hp()
```
と2回も打たなければいけません。モンハンみたいに57とかHPが減るときにはこの関数を**57回実行**しなければいけません。(非効率!)

減らしたいHP数を指定できるようにしたい！そういうときのための引数です。

```lua:一気に減らせるようにしたよ
function reduce_hp(i)
    hp = hp - i
    --[[
        HPが減ったときに行うその他の処理
    ]]
end
```
こうすると `reduce_hp(57)` を実行するとHPが57減ります。

引数の指定の仕方は、カッコ内に使いたい変数を書くだけです。
あとは使うときに、「1個目の引数は数字だ...」とか「2個目の引数はテーブルだ...」とかを気をつければ大丈夫です。
簡単ですね！

# 関数の結果を使いたい！
まずは用語です。関数の結果のことを、**「戻り値」「返り値」** と言います。言い方は2種類ありますが、同じ意味です。
僕は気分によって使い分けています。

いつ使うのかというと、例えば、長方形の面積を計算する関数を考えます。
まずは引数で縦幅(height)と横幅(width)を指定します。

```lua:長方形の面積を計算して表示するだけ
function rectangle_area(height, width)
    print(height * width)
end
```

これだとせっかく計算した面積を関数の外で使うことができません。
こういうときに**return**を使います。

```lua:戻り値を使う！
function init(self)
    print(rectangle_area(15, 20))
end

function rectangle_area(height, width)
    return height * width
end
```
これを実行すると 300 と出力されます。

この関数だとあんまり恩恵は得られませんが、もっと複雑な関数だと恩恵があります。
よくやる計算は関数にしとくと、あとから使い回せて便利です。
ds
# 最初からある関数たち
てことで、最初からある **init** とかの関数がいつ実行されるのかを説明します。

|関数名|実行タイミング|
|:-:|:-:|
|init|ゲームオブジェクトが生成されたとき|
|final|ゲームオブジェクトが削除されたとき
|update|オブジェクトが存在しているとき1フレームに1回
|on_message|メッセージを受け取ったとき
|on_input|キー入力されたとき
|on_reload|ホットリロードされたとき(そういう機能があります)

あとは軽く引数の紹介をしておきます。
(**self** はオブジェクトごとに変わりいろいろな値を使うことができますが、今回は省略します。)
## init(self)
## final(self)
## update(self, dt)
dt(number): デルタタイム
前回update関数が実行されてから経過した時間[秒] 60FPSなら 1/60です。
## on_message(self, message_id, message, sender)
メッセージは次回説明します。メールみたいなものです。
message_id(hash): メッセージのID、件名みたいなかんじ。
message(テーブル): メッセージの内容、本文みたいなかんじ。
sender(hash): 送り主のID、差出人です。
## on_input(self, action_id, action)
これは[前回](https://qiita.com/nonzu/items/924b36ea0d1a8c95834c)やりました。
action_id(hash): どのキーが入力されたか
action(テーブル): どんな感じで押されているか
## on_reload(self)
ホットリロードされたときに実行されます。
ホットリロードっていうのは、実行している間に、スクリプトを差し替えたりするための機能です。

# さいごに
今回は関数の説明をしてきました。
これからも、こんな感じでまったり紹介していきます。
更新間隔は長くなると思いますが気長に待機していただけると幸いです。
[目次](https://qiita.com/nonzu/items/73a39368855f3e1e0f28)