playdate.geometry.affineTransform
playdate.geometry.affineTransform は、2D のアフィン変換行列を表す型です。
→
アフィン変換
概要
playdate.geometry.affineTransform は、2D の
アフィン変換行列を表す型です。
用途としては主に次です。
- 平行移動
- 回転
- 拡大縮小
- skew(せん断)
- 複数変換の合成
- point / polygon / lineSegment / rect への変換適用
内部表現は典型的な 2D アフィン変換の 6 要素:
- m11
- m12
- m21
- m22
- tx
- ty
を持つ形式です。
これは通常、2D 点 (x, y) を
- x' = m11*x + m21*y + tx
- y' = m12*x + m22*y + ty
のように変換するタイプの行列です。
また、公開プロパティは基本的にないため、affineTransform は、中身を直接いじる型というより、メソッド経由で操作する型 と見てよいです。
コンストラクタ
new()
単位変換(identity transform)を返します
- 戻り値
- 意味
- 何も変換しない変換です。
- 回転なし
- 拡大縮小なし
- skew なし
- 平行移動なし
- 実質的なイメージ
- 用途
- まず空の変換を作ってから、あとで translate や rotate などを積み上げる基本形です。
-- アフィン変換を生成.
local t = playdate.geometry.affineTransform.new()
new(m11, m12, m21, m22, tx, ty)
6 要素を明示して新しいアフィン変換を作ります。
- 引数
- m11: number
- m12: number
- m21: number
- m22: number
- tx: number
- ty: number
- 戻り値
- 意味
- 行列成分を直接指定して変換を構築します。
- 注意
- identity が欲しいだけなら引数なし版を使う前提です。
- 用途
- 普通は translate/rotate/scale を使うほうが安全です。
- この 6 要素版は、
- 既知の変換行列をそのまま作りたい
- 自前計算した行列を流し込みたい
- とき向けです。
演算子 / メタメソッド
__mul が 3 つ定義されています。Lua 的には *演算子に対応します。
affineTransform:__mul(p)
変換を point に適用し、新しい point を返します。
- 引数
- 戻り値
- 意味
- transform * point という形で使えるものです。
- 役割
- transformPoint() の「新しい値を返す版」に近い使い勝手です。
- 元の point を直接書き換えるのではなく、結果の point を得る用途だと考えるのが自然です。
local t = playdate.geometry.affineTransform.new()
t:translate(100, 20)
local p = playdate.geometry.point.new(10, 5)
-- 位置行列を p=(10, 5) で変換.
local p2 = t * p
affineTransform:__mul(t)
変換同士を掛け合わせた、新しい変換を返します。
- 引数
- 戻り値
- 意味
- transform1 * transform2 により、複数変換を合成します。
- 重要
- 行列演算は可換ではありません。
- つまり、
- は一般に別結果です。
- 実務上の意味
- たとえば
- は結果が変わります。
affineTransform:__mul(v)
変換を vector2D に適用し、新しい vector2D を返します。
- 引数
- 戻り値
- 意味
- transform * vector に相当します。
- point との違い
- point は位置なので通常 tx, ty の影響を受けますが、vector は「方向・差分」として扱われることが多く、平行移動成分の扱いは点と意味合いが異なります。
変換の合成・複製・初期化
affineTransform:concat(af)
呼び出し元を破壊的に変更し、別の変換 af を連結します。
- 引数
- 戻り値
- 意味
- 現在の変換に追加で別の変換を合成します。
- 説明の要点
- 呼び出し元を mutate する
- 複数の変換を 1 つにまとめるためのもの
- 順序は重要
- 行列演算は非可換
- *演算子との違い
- t1 * t2 は新しい transform を返す
- t1:concat(t2) は t1 自体を書き換える
local t = playdate.geometry.affineTransform.new()
t:translate(50, 0)
t:concat(otherTransform)
affineTransform:copy()
変換のコピーを返します。
- 戻り値
- 意味
- 元を壊さずに分岐したいときに使います。
local base = playdate.geometry.affineTransform.new()
base:translate(20, 30)
local rotated = base:copy()
rotated:rotate(45)
affineTransform:invert()
呼び出し元を逆変換行列に書き換えます。
- 戻り値
- 意味
- ある変換の「逆操作」を行うための変換にします。
- 説明の要点
- (x, y) を変換して (x', y') になったなら
- その逆行列を (x', y') にかけると (x, y) に戻せる
- 用途
- 変換後座標から元座標に戻す
- ローカル座標系とワールド座標系を往復する
- ヒット判定時に逆変換で元形状に戻して考える
- 注意
- 数学的には逆行列を持たないケースがあります。
- たとえば scale で 0 倍したような行列は逆にできません。stub はその失敗時挙動までは書いていません。
affineTransform:reset()
呼び出し元を単位変換に戻します。
- 戻り値
- 意味
- 今まで積んだ
- translate
- rotate
- scale
- skew
- を全部リセットして、「何もしない変換」に戻します。
回転系
回転は rotate と rotatedBy があり、それぞれ point 指定版と x,y 指定版があります。
affineTransform:rotate(angle, point)
呼び出し元に回転を追加します。破壊的変更です。
- 引数
- angle: number
- point?: _Point
- 戻り値
- 意味
- 角度 angle 度だけ回転を適用します。
- 重要
- 正の値: clockwise
- 負の値: counterclockwise
- となっています。
- これは一般的な数学座標系の「正で反時計回り」と逆なので、Playdate の座標系前提の仕様として意識したほうがよいです。
- pivot
- point を指定すると、その点を中心に回転します。
- 未指定なら (0, 0) 周りです。
affineTransform:rotate(angle, x, y)
中心を point ではなく数値座標で指定して回転します。
- 引数
- angle: number
- x?: integer
- y?: integer
- 戻り値
- 意味
- (x, y) を中心に回転します。
- 未指定なら (0, 0) です。
affineTransform:rotatedBy(angle, point)
元の transform を壊さず、回転を追加した新しい transform を返します。
- 引数
- angle: number
- point?: _Point
- 戻り値
- 意味
- rotate() の非破壊版です。
local t2 = t1:rotatedBy(90)
affineTransform:rotatedBy(angle, x, y)
x,y 指定して回転を行った新しい transform を返します。
- 引数
- angle: number
- x?: integer
- y?: integer
- 戻り値
拡大縮小系
affineTransform:scale(sx, sy)
呼び出し元に拡大縮小を追加します。破壊的変更です。
- 引数
- 戻り値
- 意味
- sx で x 軸方向の倍率
- sy で y 軸方向の倍率
- 省略時
- sy を省略すると、sx を両軸に使います。
- つまり一様スケールです。
t:scale(2) -- x,y ともに 2 倍
t:scale(2, 0.5) -- x は 2 倍、y は 0.5 倍
affineTransform:scaledBy(sx, sy)
元を壊さず、スケール追加済みの新しい transform を返します。
- 引数
- 戻り値
- 意味
- scale() の非破壊版です。
skew(せん断)系
affineTransform:skew(sx, sy)
呼び出し元に skew 変換を追加します。破壊的変更です。
- 引数
- 戻り値
- 意味
- sx: x 軸方向の skew 量
- sy: y 軸方向の skew 量
- 単位
- degrees です。
- 補足
- skew は、長方形を平行四辺形のように傾ける変換です。
- 回転と違い、形の角度関係がそのまま保たれないことがあります。
affineTransform:skewedBy(sx, sy)
元を壊さず、skew を追加した新しい transform を返します。
- 引数
- 戻り値
- 意味
- skew() の非破壊版です。
平行移動系
affineTransform:translate(dx, dy)
呼び出し元に平行移動を追加します。破壊的変更です。
- 引数
- 戻り値
- 意味
affineTransform:translatedBy(dx, dy)
元を壊さず、平行移動追加済みの新しい transform を返します。
- 引数
- 戻り値
ジオメトリへの適用(破壊的変更版)
これらは対象オブジェクト自体を書き換えます。
affineTransform:transformAABB(r)
axis aligned bounding box である rect r に変換を適用し、その rect を変更します。
- 引数
- 戻り値
- 意味
- AABB は「軸に平行な境界ボックス」です。
- 回転後の図形そのものではなく、回転後図形を包む軸平行矩形 を扱う文脈で使われる名前です。
- 注意
- 回転をかけると、もとの rect と全く同じ意味の矩形にはなりません。
- 「回転した四角形」そのものではなく、「それを囲う軸平行矩形」として結果を見る必要があります。
affineTransform:transformLineSegment(ls)
line segment に変換を適用し、その line segment を変更します。
- 引数
- 戻り値
affineTransform:transformPoint(p)
point に変換を適用し、その point を変更します。
- 引数
- 戻り値
- 用途
- point をその場で更新したいときに使います。
affineTransform:transformPolygon(p)
- polygon に変換を適用し、その polygon を変更します。
- 引数
- 戻り値
affineTransform:transformXY(x, y)
座標 (x, y) に変換を適用し、変換後の x, y を数値 2 つで返します。
- 引数
- 戻り値
- 意味
- point オブジェクトを作らずに、その場で数値だけ変換したいときに便利です。
- 利点
- point 生成が不要
- 軽く使いやすい
- 一時座標の計算向き
local x2, y2 = t:transformXY(10, 20)
ジオメトリへの適用(非破壊版)
これらは元を変更せず、新しいオブジェクトを返します。
affineTransform:transformedAABB(r)
rect r を変換した結果を、新しい rect として返します。
- 引数
- 戻り値
- 意味
- transformAABB() の非破壊版です。
affineTransform:transformedLineSegment(ls)
line segment を変換した新しい line segment を返します。
- 引数
- 戻り値
affineTransform:transformedPoint(p)
point を変換した新しい point を返します。
- 引数
- 戻り値
affineTransform:transformedPolygon(p)
polygon を変換した新しい polygon を返します。
- 引数
- 戻り値
資料
破壊的版と非破壊版の整理
affineTransform ではかなり一貫しています。
- transform を変更する系
- concat
- invert
- reset
- rotate
- scale
- skew
- translate
- 変換対象を変更する系
- transformAABB
- transformLineSegment
- transformPoint
- transformPolygon
- 新しい transform を返す系
- copy
- rotatedBy
- scaledBy
- skewedBy
- translatedBy
- __mul(t) の変換同士合成
- 新しい図形を返す系
- transformedAABB
- transformedLineSegment
- transformedPoint
- transformedPolygon
- __mul(p)
- __mul(v)
API 設計上の読みどころ
affineTransform の設計はかなり明快で、次の思想があります。
- 1. 破壊的と非破壊的が分かれている
- たとえば回転なら
- rotate(...) → 呼び出し元を書き換える
- rotatedBy(...) → 新しい transform を返す
- 図形への適用も
- transformPoint(p) → p を書き換える
- transformedPoint(p) → 新しい point を返す
- で対になっています。
- これはかなり使いやすいです。
- 2. 演算子 * でも扱える
- __mul (operator*) が実装されているので、
- transform * point
- transform * vector
- transform1 * transform2
- ができるので、数式的に書きやすいです。
- 3. pivot 回転に対応している
- rotate(angle, point) / rotate(angle, x, y) があるため、
- がやれます。
- これはスプライト中心回転や UI パーツ回転で便利です。
- 4. AABB を明示的に区別している
- transformAABB / transformedAABB という名前になっていて、
- 単に rect を transform するというより、軸平行 bounding box として扱う API であることが明確です。
典型的な使い方
-- 1. 基本変換を積む
local geom = playdate.geometry
local t = geom.affineTransform.new()
t:translate(100, 50)
t:rotate(30)
t:scale(2)
これは 1 つの transform に複数操作を蓄積している形です。
-- 2. point に適用
local p = geom.point.new(10, 20)
local p2 = t:transformedPoint(p)
元の p を残したいならこれです。
なら p 自体が更新されます。
-- 3. 数値だけ変換
local x2, y2 = t:transformXY(10, 20)
point を作らなくてよいので軽量です。
-- 4. 元を残しつつ変換を分岐
local base = geom.affineTransform.new()
base:translate(100, 100)
local a = base:rotatedBy(15)
local b = base:rotatedBy(-15)
-- 5. 逆変換
local inv = t:copy()
inv:invert()
local original = inv:transformedPoint(p2)
変換後座標から元座標へ戻す用途です。
注意点
- 1. 回転の正方向
- affineTransformでは
- 正: clockwise
- 負: counterclockwise
- です。
- 数学や他ライブラリと感覚が逆なことがあるので注意です。
- 2. 変換順序が重要
- 行列計算の特性上、translate→rotate と rotate→translate は別物です。
- 3. transformAABB は「回転した四角形そのもの」ではない
- 名前の通り AABB です。
- 回転した結果の外接軸平行矩形を扱う理解が必要です。
- 4. プロパティを直接読む前提ではない
- affineTransformは内部成分を直接使うより、メソッドと *演算子で扱う前提の型です。
関連ページ
最終更新:2026年04月22日 08:20