図形

Rect、Triangle、Circle、Line、Polyline は図形コンポーネントです。エンティティを生成するときに どれかひとつを渡すと、そのエンティティは破棄されるまで毎フレームその図形を描き続けます。

from pyxen import *

def start():
    world.spawn(x=110, y=90, shape=Rect(48, 32, fill=(0.4, 0.7, 1.0, 1.0)))
    world.spawn(x=210, y=90, shape=Circle(24, stroke=(1.0, 0.6, 0.3, 1.0), stroke_width=2))

図形は本物のエンティティなので、エンティティにできることはすべて使えます。entity.x と entity.y で動かし、 entity.rotation で回し、親子関係を作り、トゥイーンで animate し、レイヤーに置き、entity.visible で隠せます。


図形と draw のどちらを使うか

Pyxen は同じ 5 つのプリミティブを 2 通り用意しています。画面上の見た目は同じで、違うのは寿命だけです。 もう一方は draw を参照してください。

図形コンポーネントdraw
寿命エンティティを破棄するまで残る1 フレーム
位置エンティティの位置・回転・スケール渡したワールド座標
コスト完全なエンティティ(transform、レイヤー、コンポーネント記憶領域)フレームバッファ内のいくつかのクアッド
向いている用途船・壁・固定 UI などゲーム内の物体手続き的な図形、デバッグ表示、HUD のバー、軌跡

そのものがゲーム内の 存在 なら図形コンポーネントを、すでに自分で管理しているものを絵として描くだけなら draw を選んでください。


つまずきやすい 3 点

図形は生成時に決まり、あとから変更できません。 entity.shape は存在せず、読もうとすると ValueError: component schema does not exist が発生します。代入できる sprite や text とは異なります。 図形を変えたいときは、エンティティを破棄して作り直してください。

entity.color では図形を着色できません。 スプライトには効きますが、図形は自身の fill と stroke で 描画し、entity.color を無視します。色は図形そのものに指定してください。

輪郭の太さの引数名は 2 種類あります。 Rect、Triangle、Circle は stroke_width、Line と Polyline は width を取ります。意味は同じです。


色

色の引数はすべて、各成分が 0.0〜1.0 の (r, g, b, a) タプル、または Color を受け取ります。

Rect(40, 20, fill=(1, 0, 0, 1))        # 不透明な赤
Rect(40, 20, fill=(1, 0, 0, 0.35))     # 35% の赤

fill も stroke もない図形は何も描きません。 どちらも完全な透明から始まるため、Rect(40, 40) は 有効かつ目に見えないエンティティになります。ここで最もよくある落とし穴です。両方を渡せば、輪郭付きの 塗りつぶし図形になります。


型

Rect(width, height, fill=None, stroke=None, stroke_width=1, pivot=None)

長方形。

引数型説明
width、heightfloat大きさ(ピクセル)。
fillタプル内側の色。省略すると塗りません。
strokeタプル輪郭の色。省略すると描きません。
stroke_widthfloat輪郭の太さ。既定は 1。
pivotタプルエンティティの位置が指す点を、図形内のピクセルで指定します。既定は角。(width/2, height/2) で中央になります。

pivot を持つ図形は Rect だけで、回転の中心にもなります。

def start():
    world.spawn(x=110, y=90, shape=Rect(48, 32, fill=(0.4, 0.7, 1.0, 1.0)))
    # 自分の位置を中心にしているので、その場で回転します。
    world.spawn(name="spinner", x=210, y=90,
                shape=Rect(48, 32, stroke=(1.0, 0.6, 0.3, 1.0), stroke_width=2,
                           pivot=(24, 16)))

def update():
    world.get(name="spinner").rotation += 0.02

Triangle(x1, y1, x2, y2, x3, y3, fill=None, stroke=None, stroke_width=1)

エンティティの位置を基準とした 3 点を通る三角形。

引数型説明
x1、y1、x2、y2、x3、y3float3 つの頂点。エンティティからの相対位置。
fillタプル内側の色。省略すると塗りません。
strokeタプル輪郭の色。省略すると描きません。
stroke_widthfloat輪郭の太さ。
world.spawn(x=160, y=90, shape=Triangle(0, -20, 18, 14, -18, 14, fill=(1, 1, 0.3, 1)))

Circle(radius, fill=None, stroke=None, stroke_width=1, segments=12)

エンティティを中心とする円。

引数型説明
radiusfloat半径(ピクセル)。
fillタプル内側の色。省略すると塗りません。
strokeタプル輪郭の色。省略すると描きません。
stroke_widthfloat輪郭の太さ。
segmentsint曲線を近似する直線の分割数。既定は 12。

円は実際には多角形です。小さいサイズなら 12 分割で丸く見えます。大きな円では値を上げ、あえて多角形に 見せたいときは下げてください。segments=6 なら六角形になります。

world.spawn(x=110, y=90, shape=Circle(28, fill=(0.5, 1.0, 0.7, 1.0), segments=6))
world.spawn(x=210, y=90, shape=Circle(28, fill=(1.0, 0.5, 0.7, 1.0), segments=32))

Line(x1, y1, x2, y2, stroke=None, width=1)

エンティティを基準とした 2 点を結ぶ直線。

引数型説明
x1、y1float始点。エンティティからの相対位置。
x2、y2float終点。
strokeタプル線の色。
widthfloat線の太さ。stroke_width ではなく width である点に注意。
world.spawn(x=60, y=90, shape=Line(0, 0, 80, -40, stroke=(0.3, 1, 0.5, 1), width=2))

Polyline(points, stroke=None, width=1, closed=False, fill=None)

連続した線分の並び。

引数型説明
pointsタプルまたは FloatBuffer(x1, y1, x2, y2, …) という平坦な列。座標ペアのリストではありません。
strokeタプル線の色。
widthfloat線の太さ。stroke_width ではなく width である点に注意。
closedboolTrue にすると最後の点と最初の点を結びます。
fillタプル囲まれた領域を塗ります。closed=True と組み合わせると便利です。

平坦な並びなのは意図的です。FloatBuffer がすでにこの形をしているため、一度計算した経路を組み直さずに そのまま Polyline に渡せます。

world.spawn(x=250, y=90,
            shape=Polyline((0, 0, 30, -25, 60, 0), stroke=(1, 0.9, 0.2, 1), width=3))