アットウィキロゴ

アフィン変換

Playdateにおけるアフィン変換(Affine Transformation)は、主に playdate.geometry.affineTransform クラスを通じて提供されます。
Unreal EngineのようなGPU主体の環境とは異なり、Playdateではソフトウェアレンダリングでこれらの計算を行うため、その仕組みとパフォーマンス上の特性を理解しておくことが重要です。


概要

1. アフィン変換行列の構造
Playdateの affineTransform は、2D空間における平行移動、回転、拡大縮小、シアー(せん断)を表現する 3x3の行列を扱います。
  • m11, m22: 拡大縮小(Scale)
  • m12, m21: 回転(Rotation)およびシアー(Shear)
  • tx, ty: 平行移動(Translation)
2. APIでの利用方法 (Lua)
基本的な使い方は、トランスフォームオブジェクトを作成し、それを画像(image)の描画時 (image: drawWithTransform()) に渡す形になります。
-- 変換オブジェクトの作成と操作
local geo = playdate.geometry
local af = geo.affineTransform.new() -- 単位行列で初期化
 
af:translate(20, 10)       -- 平行移動
af:rotate(45)              -- 45度回転
af:scale(2.0, 1.5)         -- 拡大縮小
af:shear(0.5, 0.0)         -- 水平シアー
 
-- 描画への適用
local gfx = playdate.graphics
local myImage = gfx.image.new("player")
 
function playdate.update()
    gfx.clear()
    -- 変換行列を適用して描画
    myImage:drawWithTransform(af, 100, 100)
end
 
3. 主なメソッドと機能
Playdateの affineTransform には、行列演算を抽象化した便利なメソッドが用意されています。
concat
複数の変換を合成(行列の乗算)します。
invert()
逆変換行列を計算します(スクリーン座標からワールド座標への変換などに使用)。
transformPoint(point)
特定の座標に変換を適用した結果を取得します。
transformRect(rect)
矩形範囲を変換した後のバウンディングボックスを取得します。

4. パフォーマンス上の重要事項
ここがPlaydate開発において最もトリッキーな部分です。
1. ソフトウェアレンダリングの負荷
drawWithTransform は非常に柔軟ですが、ピクセル単位での補完計算が発生するため、CPU負荷が極めて高いです。
多数のスプライトに適用すると、すぐに30fpsを維持できなくなります。
2. プリレンダリングの推奨
リアルタイムで変換する必要がない場合(例:斜めに傾いたキャラの歩きモーションなど)は、ビルド時や起動時に image:rotatedImage() や drawWithTransform を使って変換済みの画像を生成(キャッシュ)しておくのがセオリーです。
3. 1ビット特有のエイリアシング
回転やシアーをかけると、1ビットモノクロゆえにジャギー(階段状の縁)が目立ちやすくなります。
SDKの drawWithTransform には補完オプションがありますが、最終的にはディザリングと組み合わせて「綺麗に見える角度」を探る職人芸が求められます。

5. drawSampled:高速な代替手段
もし「Mode 7」のような疑似3Dや、背景全体のパース変換を行いたい場合は、affineTransform よりもplaydate.graphics.image.drawSampled() が適しています。
これは「1行(Row)ごとにサンプリング位置をずらして描画する」というハードウェアのDirty Rows特性を活かしたアプローチで、回転やパースがついた背景をフルスクリーンで描画する際にも驚くほど高速に動作します。

関連ページ

最終更新:2026年05月04日 08:42
添付ファイル