図形
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、height | float | 大きさ(ピクセル)。 |
fill | タプル | 内側の色。省略すると塗りません。 |
stroke | タプル | 輪郭の色。省略すると描きません。 |
stroke_width | float | 輪郭の太さ。既定は 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、y3 | float | 3 つの頂点。エンティティからの相対位置。 |
fill | タプル | 内側の色。省略すると塗りません。 |
stroke | タプル | 輪郭の色。省略すると描きません。 |
stroke_width | float | 輪郭の太さ。 |
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)
エンティティを中心とする円。
| 引数 | 型 | 説明 |
|---|---|---|
radius | float | 半径(ピクセル)。 |
fill | タプル | 内側の色。省略すると塗りません。 |
stroke | タプル | 輪郭の色。省略すると描きません。 |
stroke_width | float | 輪郭の太さ。 |
segments | int | 曲線を近似する直線の分割数。既定は 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、y1 | float | 始点。エンティティからの相対位置。 |
x2、y2 | float | 終点。 |
stroke | タプル | 線の色。 |
width | float | 線の太さ。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 | タプル | 線の色。 |
width | float | 線の太さ。stroke_width ではなく width である点に注意。 |
closed | bool | True にすると最後の点と最初の点を結びます。 |
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))