mcpField
G
graphics-and-shapes

graphics-and-shapes

github.com/phaserjs开发40.6k845 次安装10 周前更新
代码仓库

关于 graphics-and-shapes

面向 Phaser 4 开发者的图形与形状技能,说明如何用 Graphics 绘制图元,以及使用独立 Shape 游戏对象。内容对比两种方式,并涵盖样式、路径、变换和纹理生成。

主要功能

  1. 01Graphics 填充、描边与路径绘制
  2. 02圆角矩形、渐变及画布变换
  3. 03从 Graphics 生成纹理
  4. 04使用多种 Shape 几何对象
  5. 05Shape 样式与游戏对象组件

适用场景

  1. 01绘制动态路径或组合图形
  2. 02创建可交互或可加入物理系统的形状
  3. 03将绘图结果烘焙为纹理
  4. 04为界面制作简单几何元素

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/phaserjs/phaser --skill graphics-and-shapes

安装后在 Claude Code 中输入/graphics-and-shapes确认已加载。

详细介绍

Phaser 4 — 图形与形状

使用 Graphics 游戏对象绘制图元,并使用 Shape 游戏对象(Arc、Curve、Ellipse、Grid、IsoBox、IsoTriangle、Line、Polygon、Rectangle、Star、Triangle)。

相关技能:sprites-and-images.md、game-object-components.md


快速开始

// Draw a filled rectangle and stroked circle with Graphics
const gfx = this.add.graphics();

gfx.fillStyle(0x00aa00, 1);
gfx.fillRect(50, 50, 200, 100);

gfx.lineStyle(3, 0xff0000, 1);
gfx.strokeCircle(400, 150, 60);
// Same shapes as standalone Shape game objects
const rect = this.add.rectangle(150, 100, 200, 100, 0x00aa00);
const circle = this.add.circle(400, 150, 60);
circle.setStrokeStyle(3, 0xff0000);

核心概念 — Graphics 与 Shape 对象

Phaser 提供两种无需纹理即可渲染图元的方法。

Graphics 游戏对象

通过 this.add.graphics() 创建。它是一种命令式绘图表面 —— 你调用 fillRect、strokeCircle、beginPath/lineTo/strokePath 等方法,构建一个每帧都会重放的命令缓冲区。

  • 工厂方法:this.add.graphics(config?),其中 config 为 { x?, y?, lineStyle?, fillStyle? }。
  • 支持路径、弧线、渐变、圆角矩形、画布变换(translateCanvas、scaleCanvas、rotateCanvas)以及 save/restore。
  • 可以通过 generateTexture(key, width, height) 从绘制内容生成纹理。
  • 渲染开销较大,尤其是绘制复杂形状时。它使用自己的 WebGL 着色器。将多个 Graphics 对象归组,以尽量减少批次刷新。
  • 组件:AlphaSingle、BlendMode、Depth、Lighting、Mask、RenderNodes、Transform、Visible、ScrollFactor。
  • 不包含 Origin 或 GetBounds(位置通过选项或 setPosition 设置)。
Shape 游戏对象

各个独立的游戏对象(Arc、Rectangle、Star 等),继承自基础 Shape 类。每个对象使用预先计算好的路径数据渲染一个预定义的几何形状。

  • 通过专用工厂方法创建:this.add.rectangle(...)、this.add.circle(...) 等。
  • 功能完整的游戏对象:可以进行补间、缩放、添加到组/容器,以及启用输入/物理。
  • 通过 setFillStyle(color, alpha) 和 setStrokeStyle(lineWidth, color, alpha) 设置样式。
  • 与 Graphics 共享同一个 WebGL 批次,以实现高效渲染。
  • 不支持渐变、路径细节阈值或画布变换。
  • 组件:AlphaSingle、BlendMode、Depth、GetBounds、Lighting、Mask、Origin、RenderNodes、ScrollFactor、Transform、Visible。
  • 包含 Origin 和 GetBounds(与 Graphics 不同)。

何时使用哪一种:

  • 使用 Graphics 进行动态绘制、复杂路径、在一个对象上绘制多个形状、渐变或生成纹理。
  • 使用 Shape 对象 制作单个 UI 元素、简单指示器、启用物理的形状,或任何受益于游戏对象特性(origin、bounds、input)的场景。

常见模式

填充与描边样式(Graphics)
const gfx = this.add.graphics();

// Solid fill — call before any fill* method
gfx.fillStyle(0xff0000, 1);          // (color, alpha)

// Line style — call before any stroke* method
gfx.lineStyle(4, 0x00ff00, 1);       // (width, color, alpha)

// Gradient fill (WebGL only) — 4 corner colors
gfx.fillGradientStyle(
    0xff0000, 0x00ff00, 0x0000ff, 0xffff00,  // tl, tr, bl, br colors
    1, 1, 1, 1                                 // tl, tr, bl, br alphas
);
gfx.fillRect(0, 0, 300, 200);

// Gradient line style (WebGL only)
gfx.lineGradientStyle(2, 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 1);
绘制图元(Graphics)
const gfx = this.add.graphics();

// Rectangles
gfx.fillStyle(0x0000ff);
gfx.fillRect(x, y, width, height);
gfx.lineStyle(2, 0xffffff);
gfx.strokeRect(x, y, width, height);

// Circles
gfx.fillCircle(x, y, radius);
gfx.strokeCircle(x, y, radius);

// Ellipses
gfx.fillEllipse(x, y, width, height, smoothness);
gfx.strokeEllipse(x, y, width, height, smoothness);   // smoothness defaults to 32

// Triangles
gfx.fillTriangle(x0, y0, x1, y1, x2, y2);
gfx.strokeTriangle(x0, y0, x1, y1, x2, y2);

// Points (draws a small square)
gfx.fillPoint(x, y, size);                             // size defaults to 1

// Lines
gfx.lineBetween(x1, y1, x2, y2);
圆角矩形
const gfx = this.add.graphics();

// Uniform radius (default 20)
gfx.fillStyle(0x333333);
gfx.fillRoundedRect(50, 50, 300, 200, 16);
gfx.lineStyle(2, 0xffffff);
gfx.strokeRoundedRect(50, 50, 300, 200, 16);

// Per-corner radius
gfx.fillRoundedRect(50, 50, 300, 200, {
    tl: 20, tr: 20, bl: 0, br: 0
});

// Concave corners (negative values)
gfx.fillRoundedRect(50, 50, 300, 200, { tl: -10, tr: -10, bl: -10, br: -10 });
路径绘制
const gfx = this.add.graphics();

// Manual path
gfx.lineStyle(3, 0xffff00);
gfx.beginPath();
gfx.moveTo(100, 100);
gfx.lineTo(200, 50);
gfx.lineTo(300, 100);
gfx.lineTo(250, 200);
gfx.closePath();
gfx.strokePath();       // or gfx.stroke() — alias for strokePath

// Fill a path
gfx.fillStyle(0x00aaff);
gfx.beginPath();
gfx.moveTo(100, 100);
gfx.lineTo(200, 50);
gfx.lineTo(300, 100);
gfx.closePath();
gfx.fillPath();         // or gfx.fill() — alias for fillPath

// Arc within a path (angles in radians)
gfx.beginPath();
gfx.arc(200, 200, 80, 0, Math.PI / 2, false, 0);   // (x, y, radius, startAngle, endAngle, anticlockwise, overshoot)
gfx.strokePath();

// Pie slice
gfx.slice(200, 200, 80, 0, Math.PI / 3, false);     // auto begins/closes path
gfx.fillPath();

// Stroke/fill from point arrays
gfx.strokePoints(points, closeShape, closePath, endIndex);
gfx.fillPoints(points, closeShape, closePath, endIndex);
Geom 形状辅助方法

Graphics 提供了便捷方法,可直接接受 Phaser.Geom 对象:

const circle = new Phaser.Geom.Circle(200, 200, 50);
const rect = new Phaser.Geom.Rectangle(50, 50, 100, 80);

gfx.fillCircleShape(circle);
gfx.strokeCircleShape(circle);
gfx.fillRectShape(rect);
gfx.strokeRectShape(rect);
gfx.fillTriangleShape(triangle);
gfx.strokeTriangleShape(triangle);
gfx.strokeLineShape(line);
gfx.fillEllipseShape(ellipse, smoothness);
gfx.strokeEllipseShape(ellipse, smoothness);
画布变换(Graphics)
const gfx = this.add.graphics();

gfx.save();
gfx.translateCanvas(100, 100);
gfx.rotateCanvas(0.5);           // radians
gfx.scaleCanvas(2, 2);
gfx.fillStyle(0xff0000);
gfx.fillRect(0, 0, 50, 50);     // draws at translated/rotated/scaled position
gfx.restore();
从 Graphics 生成纹理
const gfx = this.add.graphics();
gfx.fillStyle(0xff0000);
gfx.fillCircle(32, 32, 32);
gfx.generateTexture('redCircle', 64, 64);
gfx.destroy();

// Now use as a regular texture
this.add.image(400, 300, 'redCircle');

注意:fillGradientStyle 不会出现在生成的纹理中(Canvas API 的限制)。

Shape 对象 — 填充与描边
// Shapes set fill via constructor or setFillStyle
const rect = this.add.rectangle(200, 150, 100, 80, 0xff0000, 1);

// Change fill later
rect.setFillStyle(0x00ff00, 0.8);

// Add stroke (not set by default)
rect.setStrokeStyle(3, 0xffffff, 1);  // (lineWidth, color, alpha)

// Remove fill or stroke
rect.setFillStyle();    // no args = isFilled becomes false
rect.setStrokeStyle();  // no args = isStroked becomes false

// Direct property access
rect.fillColor = 0x0000ff;
rect.fillAlpha = 0.5;
rect.strokeColor = 0xffffff;
rect.strokeAlpha = 1;
rect.lineWidth = 2;
rect.isFilled = true;
rect.isStroked = true;
rect.closePath = true;   // close stroke path (default true)

所有形状类型

工厂方法类参数(在 x、y 之后)填充描边说明
this.add.arc(x, y, radius, startAngle, endAngle, anticlockwise, fillColor, fillAlpha)Arcradius=128, startAngle=0, endAngle=360(度), anticlockwise=false是是角度以度为单位。默认绘制完整圆形。
this.add.circle(x, y, radius, fillColor, fillAlpha)Arcradius=128是是使用 0-360 角度的 Arc 别名。
this.add.curve(x, y, curve, fillColor, fillAlpha)CurvePhaser.Curves.Curve 对象是是具有 smoothness 属性 / setSmoothness()。
this.add.ellipse(x, y, width, height, fillColor, fillAlpha)Ellipsewidth=128, height=128是是宽高相等时渲染为圆形。具有 smoothness。
this.add.grid(x, y, width, height, cellWidth, cellHeight, fillColor, fillAlpha, outlineFillColor, outlineFillAlpha)Gridwidth=128, height=128, cellWidth=32, cellHeight=32是否具有用于棋盘格的 altFillColor/altFillAlpha。通过 outlineFillColor 绘制轮廓。
this.add.isobox(x, y, size, height, fillTop, fillLeft, fillRight)IsoBoxsize=48, height=32, fillTop=0xeeeeee, fillLeft=0x999999, fillRight=0xcccccc是否等距盒。showTop、showLeft、showRight、projection。
this.add.isotriangle(x, y, size, height, reversed, fillTop, fillLeft, fillRight)IsoTrianglesize=48, height=32, reversed=false是否等距棱锥。showTop、showLeft、showRight、projection、reversed。
this.add.line(x, y, x1, y1, x2, y2, strokeColor, strokeAlpha)Linex1=0, y1=0, x2=128, y2=0否是仅描边。构造函数接受描边颜色(而非填充)。
this.add.polygon(x, y, points, fillColor, fillAlpha)Polygonpoints(多种格式)是是点:Vec2 数组、[x,y,...] 对,或 [[x,y],...]。
this.add.rectangle(x, y, width, height, fillColor, fillAlpha)Rectanglewidth=128, height=128是是通过 width/height 属性更改尺寸。
this.add.star(x, y, points, innerRadius, outerRadius, fillColor, fillAlpha)Starpoints=5, innerRadius=32, outerRadius=64是是4 个角 = 菱形。角越多越尖锐。
this.add.triangle(x, y, x1, y1, x2, y2, x3, y3, fillColor, fillAlpha)Trianglex1=0,y1=128, x2=64,y2=0, x3=128,y3=128是是始终闭合。开放形状请使用 Polygon。

API 快速参考 — Graphics 方法

样式方法
方法签名说明
fillStyle(color, alpha=1)为后续填充调用设置填充样式
lineStyle(lineWidth, color, alpha=1)为后续描边调用设置描边样式
fillGradientStyle(tl, tr, bl, br, aTL=1, aTR, aBL, aBR)仅 WebGL。4 个角颜色。
lineGradientStyle(lineWidth, tl, tr, bl, br, alpha=1)仅 WebGL。
setDefaultStyles(options)通过 { lineStyle: {width,color,alpha}, fillStyle: {color,alpha} } 设置
路径方法
方法签名说明
beginPath()开始新路径
moveTo(x, y)移动绘制位置
lineTo(x, y)绘制直线到指定位置
arc(x, y, radius, startAngle, endAngle, anticlockwise=false, overshoot=0)角度以弧度为单位
closePath()闭合当前路径
fillPath / fill()填充当前路径
strokePath / stroke()描边当前路径
slice(x, y, radius, startAngle, endAngle, anticlockwise=false, overshoot=0)饼图切片。自动开始/闭合路径。角度以弧度为单位。
形状绘制方法
方法签名
fillRect(x, y, width, height)
strokeRect(x, y, width, height)
fillRoundedRect(x, y, width, height, radius=20)
strokeRoundedRect(x, y, width, height, radius=20)
fillCircle(x, y, radius)
strokeCircle(x, y, radius)
fillEllipse(x, y, width, height, smoothness=32)
strokeEllipse(x, y, width, height, smoothness=32)
fillTriangle(x0, y0, x1, y1, x2, y2)
strokeTriangle(x0, y0, x1, y1, x2, y2)
fillPoint(x, y, size=1)
lineBetween(x1, y1, x2, y2)
strokePoints(points, closeShape=false, closePath=false, endIndex)
fillPoints(points, closeShape=false, closePath=false, endIndex)
Geom 形状方法
方法签名
fillRectShape(rect)
strokeRectShape(rect)
fillCircleShape(circle)
strokeCircleShape(circle)
fillTriangleShape(triangle)
strokeTriangleShape(triangle)
strokeLineShape(line)
fillEllipseShape(ellipse, smoothness=32)
strokeEllipseShape(ellipse, smoothness=32)
变换与状态方法
方法签名说明
translateCanvas(x, y)平移后续绘制
scaleCanvas(x, y)缩放后续绘制
rotateCanvas(radians)旋转后续绘制
save()将状态压入栈
restore()从栈中弹出状态
clear()清空命令缓冲区,重置为默认样式
generateTexture(key, width, height)烘焙为 Texture(Canvas API)
形状基类方法
方法签名说明
setFillStyle(color?, alpha=1)无参数 = 禁用填充
setStrokeStyle(lineWidth?, color?, alpha=1)无参数 = 禁用描边

注意事项

  1. Graphics 的 arc() 使用弧度;Shape 的 arc 工厂方法使用角度。 Graphics 的 arc 方法以弧度接收起始/结束角度。this.add.arc() 工厂方法则以角度(0-360)接收。混淆这两者是最常见的 bug。

  2. 在绘制之前设置样式。 fillStyle 和 lineStyle 必须在对应的填充/描边方法之前调用。它们不是追溯生效的。

  3. Graphics 没有 Origin 或 GetBounds。 与 Shape 对象不同,Graphics 不包含 Origin 或 GetBounds 组件。请改用 setPosition(x, y) 和 displayOriginX/displayOriginY。

  4. Shape 的 isFilled/isStroked 默认值。 使用 fillColor 参数创建的 Shape 其 isFilled = true。但 isStroked 默认为 false —— 你必须显式调用 setStrokeStyle()。

  5. Line shape 仅支持描边。 Line shape 不支持填充。其构造函数接收 strokeColor/strokeAlpha(而非 fillColor)。

  6. IsoBox/IsoTriangle 仅支持填充。 这些形状无法描边。Grid 通过其构造函数参数(outlineFillColor、outlineFillAlpha)支持轮廓描边。

  7. generateTexture 使用 Canvas API。 渐变填充(fillGradientStyle)不会出现在用 generateTexture 生成的纹理中。只有 Canvas 兼容的特性会被捕获。

  8. 性能:Graphics 开销较大。 每一帧都会重放命令缓冲区并重建几何体(WebGL 会将其分解为多边形)。对于静态形状,请调用 generateTexture 并将生成的纹理用作 Sprite。将 Graphics 对象分组在一起以尽量减少批处理中断。

  9. pathDetailThreshold(v4 新增)。 Graphics 有一个 pathDetailThreshold 属性(默认 -1,使用配置项 render.pathDetailThreshold)。低于此像素阈值的路径段会被合并,从而提升复杂形状在 WebGL 下的性能。该值以屏幕像素为单位进行评估,因此放大时细节会显现出来。

  10. 圆角矩形的半径可以是对象或数字。 传入 { tl, tr, bl, br } 可分别控制每个角。负值会创建凹角。省略时默认为 20。

  11. Shape 的 closePath 属性。 Shape 对象上的 closePath 属性(默认 true)控制描边路径是否自动闭合。对于开放的描边形状,请设置为 false。

  12. Shape 对象不支持 tint 方法。 与 Sprite 和 Image 不同,Shape 游戏对象没有 setTint() 或 tint 属性。请改用 setFillStyle(color, alpha) 和 setStrokeStyle(lineWidth, color, alpha)。

  13. 多边形在负坐标点下 getBounds() 不正确。 如果任何多边形点具有负坐标,getBounds() 会返回错误的值。请改用 Phaser.Geom.Polygon.GetAABB(polygon.geom) 并调整返回的 Rectangle 位置。


形状专属方法

Star
const star = this.add.star(400, 300, 5, 32, 64, 0xffff00);

star.setPoints(8);          // change number of points
star.setInnerRadius(20);    // change inner radius
star.setOuterRadius(80);    // change outer radius
Line(渐细)
const line = this.add.line(400, 300, 0, 0, 200, 100, 0xffffff);

// setLineWidth(startWidth, endWidth) — endWidth is WebGL only (tapering effect)
line.setLineWidth(4, 1);   // tapers from 4px to 1px (Canvas uses startWidth only)
Grid(交替颜色、描边、内边距)
const grid = this.add.grid(400, 300, 320, 240, 32, 32, 0x222222);

// Alternating cell color (checkerboard)
grid.setAltFillStyle(0x444444, 1);  // no args = disable alternating cells

// Grid uses setStrokeStyle for cell outlines (inherited from Shape)
grid.setStrokeStyle(1, 0x666666, 1);

// v4: control outside edge stroke
grid.strokeOutside = true;             // stroke the outer border
grid.strokeOutsideIncomplete = false;  // skip partial cells on right/bottom edges

// Cell padding (default 0.5) — gutter between cells is 2x this value
grid.cellPadding = 1;
IsoBox / IsoTriangle
const box = this.add.isobox(200, 200, 48, 32, 0xeeeeee, 0x999999, 0xcccccc);

box.setFaces(true, true, false);  // showTop, showLeft, showRight
box.setProjection(4);             // isometric projection value

const tri = this.add.isotriangle(400, 200, 48, 32, false, 0xeeeeee, 0x999999, 0xcccccc);

tri.setReversed(true);            // flip upside down
tri.setFaces(true, true, true);
tri.setProjection(4);

源文件映射

文件用途
src/gameobjects/graphics/Graphics.jsGraphics 类 — 所有绘制方法
src/gameobjects/graphics/GraphicsFactory.jsthis.add.graphics() 工厂
src/gameobjects/graphics/Commands.js命令缓冲区的内部命令常量
src/gameobjects/graphics/GraphicsRender.js渲染调度
src/gameobjects/shape/Shape.js基础 Shape 类(填充/描边/路径数据、setFillStyle、setStrokeStyle)
src/gameobjects/shape/arc/Arc.jsArc 形状(也用于圆)
src/gameobjects/shape/arc/ArcFactory.jsthis.add.arc() 和 this.add.circle() 工厂
src/gameobjects/shape/curve/Curve.jsCurve 形状
src/gameobjects/shape/curve/CurveFactory.jsthis.add.curve() 工厂
src/gameobjects/shape/ellipse/Ellipse.jsEllipse 形状
src/gameobjects/shape/ellipse/EllipseFactory.jsthis.add.ellipse() 工厂
src/gameobjects/shape/grid/Grid.jsGrid 形状
src/gameobjects/shape/grid/GridFactory.jsthis.add.grid() 工厂
src/gameobjects/shape/isobox/IsoBox.jsIsoBox 形状
src/gameobjects/shape/isobox/IsoBoxFactory.jsthis.add.isobox() 工厂
src/gameobjects/shape/isotriangle/IsoTriangle.jsIsoTriangle 形状
src/gameobjects/shape/isotriangle/IsoTriangleFactory.jsthis.add.isotriangle() 工厂
src/gameobjects/shape/line/Line.jsLine 形状
src/gameobjects/shape/line/LineFactory.jsthis.add.line() 工厂
src/gameobjects/shape/polygon/Polygon.jsPolygon 形状
src/gameobjects/shape/polygon/PolygonFactory.jsthis.add.polygon() 工厂
src/gameobjects/shape/rectangle/Rectangle.jsRectangle 形状
src/gameobjects/shape/rectangle/RectangleFactory.jsthis.add.rectangle() 工厂
src/gameobjects/shape/star/Star.jsStar 形状
src/gameobjects/shape/star/StarFactory.jsthis.add.star() 工厂
src/gameobjects/shape/triangle/Triangle.jsTriangle 形状
src/gameobjects/shape/triangle/TriangleFactory.jsthis.add.triangle() 工厂

评论

支持 Markdown