Codeaを使ってiPadでアプリ開発（基礎）

# はじめに

1年以上前に、
[Codeaを使ってiPadでアプリ開発(概要)](http://qiita.com/tkyaji/items/137e0b563198017e135d)
という記事を書いたのですが、概要の紹介だけで終わっていました。

今回はもう少し詳しく、Codeaで開発する際の実際のコードを紹介したいと思います。
なお、Codeaのリファレンスはアプリ上で見られる他、以下のページで確認できます。
[Codea Reference](http://twolivesleft.com/Codea/Reference/index.html)


# setup

まずはHelloWorld。
Codeaは`Main`の`setup`という関数が最初に呼ばれます。

```lua:Main
function setup()
    print("Hello World!")
end
```
実行すると、「アウトプット」欄に`Hello World!`が出力されているはずです。


# draw

次に描画です。Codeaでは、`draw`関数が毎フレーム毎に呼び出されます。

```lua:Main
function draw()
    -- 黒で塗りつぶす
    background(0, 0, 0)
    
    -- ########## 線を引く ##########
    -- rgba
    stroke(255, 255, 0, 255)
    -- 線の太さ
    strokeWidth(5)
    -- 線の端のスタイル
    lineCapMode(ROUND)
    -- x=100,y=100 -> x=200,y=200 の位置に線を引く
    line(100, 100, 200, 200)
    
    
    -- ########## 円を描く ##########
    -- 円の縁の線をなしに
    noStroke()
    -- 円の塗りつぶしの色
    fill(0, 0, 255, 255)
    -- x=100,y=200, 直径=100 の円を描く
    ellipse(100, 200, 100)
    
    
    -- ########## 四角を描く ##########
    -- 四角の塗りつぶしの色
    fill(255, 0, 0, 255)
    -- x=100,y=300,width=50,height=100 の四角を描く
    rect(100, 300, 50, 60)
    
    
    -- ########## 文字を描く ##########
    -- 文字色
    fill(255, 255, 255, 255)
    -- 文字サイズ
    fontSize(40)
    -- フォント
    font("MarkerFelt-Wide")
    -- x=150,y=400 の位置に文字を描画
    text("Sample Text", 150, 400)
    
    
    -- ########## 画像を描画 ##########
    -- x=100,y=500 の位置に画像を描画
    sprite("Planet Cute:Character Boy", 100, 500)
end
```

実行結果
![codea_sample1.png](https://qiita-image-store.s3.amazonaws.com/0/19872/7d36f08b-12c1-1533-ba55-d1401c2f4ec0.png)


Codeaは円が綺麗に描けるのが、個人的には気に入っています。
最初に`background`や`rect`等で背景を塗りつぶさないと、一度描画したものが残り続けます。

`fill`や`stroke`等で設定した内容は、それ以降ずっと有効となったままです。
そのため、一時的に色やスタイルを変え、描画後に戻したい場合は`pushStyle`、`popStyle`で挟むと良いです。

```lua:main.lua
function draw()
    background(0, 0, 0)

    pushStyle()
    fill(0, 0, 255, 255)
    rect(100, 100, 100)
    popStyle()
end
```

# Touch

タッチイベントは、`Main`の`touched`という関数で受け取ります。

```lua:main.lua
function touched(touch)
    if touch.state == BEGAN then
        print("BEGAN : " .. touch.x .. ", " .. touch.y)
    elseif touch.state == MOVING then
        print("MOVING : " .. touch.x .. ", " .. touch.y)
    elseif touch.state == ENDED then
        print("ENDED : " .. touch.x .. ", " .. touch.y)
    end
end
```

引数の`touch`オブジェクトの中身は以下を参照してください
http://twolivesleft.com/Codea/Reference/Touch.html#touch

`state`の値は、タッチ開始が`BEGAN`、ドラッグ中が`MOVING`、離すと`ENDED`となります。
そのため、タッチ1回だけの取得であれば、`touch.stage == ENDED`の場合のみ処理を実行すれば良いかと思います。


# アニメーション

Codeaでオブジェクトを動かしたい場合、基本的な考え方は、`draw`でずらしながら描画するという方法です。

```lua:Main
function setup()
   x = 100
end

function draw()
    background(0, 0, 0)

    fill(0, 0, 255, 255)
    ellipse(x, 100, 100)
    
    -- x = 100 -> 300 まで移動
    x = x + DeltaTime * 100
    if x > 300 then
        x = 300
    end
end
```

実行結果
![codea.gif](https://qiita-image-store.s3.amazonaws.com/0/19872/35f4601e-22b6-eb4a-83e7-cdc5f54b37b2.gif)

しかしこれを毎回実装するのは面倒です。
そこで`tween`関数を使います。tweenを使うと、指定時間でオブジェクトの値を変化させる処理を
簡単に書くことができます。
上記と同じような処理を`tween`で書き直すと、以下のようになります。

```lua:Main
function setup()
   obj = {x = 100, y = 100}
   -- 2秒かけて、objのxを300まで変化させる
   tween(2, obj, {x = 300})
end

function draw()
    background(0, 0, 0)

    fill(0, 0, 255, 255)
    ellipse(obj.x, obj.y, 100)
end
```

tweenではeasingを指定することもできます。

```lua:Main

function setup()
   obj = {x = 100, y = 300}
   tween(2, obj, {y = 100}, tween.easing.bounceOut)
end

function draw()
    background(0, 0, 0)

    fill(0, 0, 255, 255)
    ellipse(obj.x, obj.y, 100)
end
```

実行結果
![codea2.gif](https://qiita-image-store.s3.amazonaws.com/0/19872/80b4534e-784d-1fe7-e710-54c173f77de2.gif)

easingは結構種類があります。
http://twolivesleft.com/Codea/Reference/Animation.html#3


さらに`loop`を指定することで、アニメーションを繰り返し実行することができます。
loopには、`tween.loop.forever`、`tween.loop.pingpong` を指定することができ、
pingpong は以下のように行ったり来たりを繰り返します。

```lua:Main
function setup()
   obj = {x = 100, y = 300}
   tween_id = tween(0.5, obj, {y = 100}, {easing=tween.easing.cubicInOut, loop=tween.loop.pingpong})
end

function draw()
    background(0, 0, 0)

    fill(0, 0, 255, 255)
    ellipse(obj.x, obj.y, 100)
end
```

![codea3.gif](https://qiita-image-store.s3.amazonaws.com/0/19872/786078b7-98c5-8b6d-4227-74e62f8b72ac.gif)


tweenでは、さらにアニメーション完了時のコールバックを指定できます。

```:lua:Main
   tween(0.5, obj, {y = 100}, tween.easing.liner, function()
       print("complete.")
   end)
```

# Class

Codeaのアプリ上では、「新規クラスを作成」というボタンがあり、Classを作成して処理を分割することができます。
「新規クラスを作成」を実行すると、以下のような雛形が生成されます。

```lua:TestClass
TestClass = class()

function TestClass:init(x)
    -- you can accept and set parameters here
    self.x = x
end

function TestClass:draw()
    -- Codea does not automatically call this method
end

function TestClass:touched(touch)
    -- Codea does not automatically call this method
end
```

このクラスはCodea独特のもので、以下のような特徴があります。

* 作ったクラスは自動で`require`される
* クラス名() でインスタンスを生成できる （例：TestClass() ）
* initはコンストラクタ相当のもので、引数はインスタンス生成時に指定する
* 雛形で生成される`draw`、`touched`は勝手に呼ばれないので、Mainから呼び出す処理を書く

クラスの例

```lua
-- Main
function setup()
    test = TestClass(100, 100)
end

function draw()
    background(0, 0, 0)
    test:draw()
end

function touched(touch)
    test:touched(touch)
end


-- TestClass
TestClass = class()

function TestClass:init(x, y)
    self.x = x
    self.y = y
    self.tween_id = tween(0.5, self, {y = 300}, {easing=tween.easing.linear, loop=tween.loop.pingpong})
end

function TestClass:draw()
    pushStyle()
    fill(0, 0, 255, 255)
    ellipse(self.x, self.y, 100)
    popStyle()
end

function TestClass:touched(touch)
    if touch.state == ENDED and self.tween_id then
        tween.stop(self.tween_id)
        self.tween_id = nil
    end
end
```

なお、class(親クラス) とすることで、クラスを継承することができます。

```lua
-- TestClass2
TestClass2 = class(TestClass)
```

##補足

> 説明上、「クラス」「継承」と記載していますが、Luaにクラスは存在せず、実態はただのLuaのテーブルです。
当然クラスの継承というものもありません。
Codeaでは`class()`関数で特別なテーブルを生成しており、それにより、上記のような
オブジェクト指向的な書き方ができるようになっています。


# 物理エンジン（Physics）

Codeaでは物理エンジンを使うこともできます。物理エンジンはBox2Dを使っています。

```lua:Main
-- Main
function setup()
    physics.gravity(0, -100)  -- 重力
    
    -- ボール
    ball = physics.body(CIRCLE, 50)
    ball.x = 200
    ball.y = 400
    ball.gravityScale = 10  -- 重力10倍
    ball.restitution = 0.7  -- 反発係数
    
    -- 床
    flr = physics.body(EDGE, vec2(100, 100), vec2(300, 100))
    flr.w = 10
end

function draw()
    background(0, 0, 0)

    -- ボール描画
    pushStyle()
    fill(0, 0, 255, 255)
    ellipse(ball.x, ball.y, ball.radius * 2)
    
    -- 床描画
    pushStyle()
    stroke(255, 255, 255, 255)
    strokeWidth(flr.w)
    local p = flr.points
    line(p[1].x, p[1].y - 5, p[2].x, p[2].y - flr.w * 0.5)
    popStyle()
end
```

実行結果
![codea4.gif](https://qiita-image-store.s3.amazonaws.com/0/19872/b72658dc-af6e-5317-1a59-209a2cfffe8f.gif)


`Physics`はリファレンス等を見ても情報が少なく、使う方がわかりづらいのですが、
物理エンジンはBox2Dのため、Box2Dの使い方を調べればだいたいわかります。


# おわりに

Codeaでゲームを開発する際の、基本的なAPIを紹介してみました。
他にもストレージやネットワーク、サウンド等、色々と便利なAPIがあるため、
興味がある方は[リファレンス](http://twolivesleft.com/Codea/Reference/index.html)を一通り見てみると良いと思います。

最後に、Codeaで簡単な数字パズル的なゲームを作ってリリースしてみたので紹介しておきます。
[Chain Numbers](https://itunes.apple.com/jp/app/chain-numbers/id1032932022?mt=8)


以上