Phaser 游戏对象 #

游戏对象概述 #

游戏对象(Game Objects)是 Phaser 游戏中所有可见元素的基础。Phaser 提供了多种类型的游戏对象,每种都有特定的用途。

text
┌─────────────────────────────────────────────────────────────┐
│                    游戏对象继承关系                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Phaser.GameObjects.GameObject                              │
│  ├── Phaser.GameObjects.Image                               │
│  ├── Phaser.GameObjects.Sprite                              │
│  ├── Phaser.GameObjects.Text                                │
│  ├── Phaser.GameObjects.Container                           │
│  ├── Phaser.GameObjects.Graphics                            │
│  ├── Phaser.GameObjects.Shape                               │
│  │   ├── Rectangle                                          │
│  │   ├── Circle                                             │
│  │   ├── Ellipse                                            │
│  │   ├── Triangle                                           │
│  │   ├── Line                                               │
│  │   └── Polygon                                            │
│  ├── Phaser.GameObjects.TileSprite                          │
│  ├── Phaser.GameObjects.BitmapText                          │
│  ├── Phaser.GameObjects.Rope                                │
│  └── Phaser.GameObjects.Particles.ParticleEmitter           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

图像(Image) #

创建图像 #

javascript
const image = this.add.image(x, y, 'textureKey');

const image = this.add.image(400, 300, 'sky');

const image = this.add.image(400, 300, 'atlas', 'frameName');

图像属性 #

javascript
const image = this.add.image(400, 300, 'player');

image.x = 100;
image.y = 200;
image.setPosition(100, 200);

image.scaleX = 2;
image.scaleY = 2;
image.setScale(2, 2);

image.rotation = Math.PI / 4;
image.angle = 45;

image.alpha = 0.5;

image.visible = true;

image.setOrigin(0.5, 0.5);

image.depth = 10;

image.setFlipX(true);
image.setFlipY(true);

图像方法 #

javascript
const image = this.add.image(400, 300, 'player');

image.setTexture('newTexture');

image.setTexture('atlas', 'newFrame');

image.destroy();

const bounds = image.getBounds();

const center = image.getCenter();

const topLeft = image.getTopLeft();

精灵(Sprite) #

创建精灵 #

javascript
const sprite = this.add.sprite(x, y, 'textureKey');

const sprite = this.add.sprite(100, 100, 'player');

const sprite = this.physics.add.sprite(100, 100, 'player');

精灵与图像的区别 #

text
┌─────────────────────────────────────────────────────────────┐
│                    Image vs Sprite                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Image:                                                    │
│  ├── 更轻量级                                              │
│  ├── 不支持动画                                            │
│  ├── 适合静态图像                                          │
│  └── 性能更好                                              │
│                                                             │
│  Sprite:                                                   │
│  ├── 支持帧动画                                            │
│  ├── 可以播放动画                                          │
│  ├── 适合需要动画的游戏对象                                │
│  └── 稍重于 Image                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

精灵动画 #

javascript
preload() {
  this.load.spritesheet('dude', 'assets/dude.png', {
    frameWidth: 32,
    frameHeight: 48
  });
}

create() {
  this.anims.create({
    key: 'left',
    frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
    frameRate: 10,
    repeat: -1
  });
  
  this.anims.create({
    key: 'turn',
    frames: [ { key: 'dude', frame: 4 } ],
    frameRate: 20
  });
  
  this.anims.create({
    key: 'right',
    frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
    frameRate: 10,
    repeat: -1
  });
  
  const player = this.add.sprite(100, 100, 'dude');
  
  player.anims.play('left');
  
  player.anims.stop();
}

文本(Text) #

创建文本 #

javascript
const text = this.add.text(x, y, 'content', style);

const text = this.add.text(400, 300, 'Hello World', {
  fontSize: '32px',
  fill: '#ffffff'
});

const text = this.add.text(100, 100, 'Score: 0', {
  fontFamily: 'Arial',
  fontSize: '24px',
  fontStyle: 'bold',
  color: '#ffffff',
  backgroundColor: '#000000',
  padding: { x: 10, y: 5 }
});

文本样式 #

javascript
const style = {
  fontFamily: 'Arial',
  fontSize: '32px',
  fontStyle: 'bold italic',
  color: '#ffffff',
  backgroundColor: '#000000',
  stroke: '#ff0000',
  strokeThickness: 2,
  shadow: {
    offsetX: 2,
    offsetY: 2,
    color: '#000000',
    blur: 5,
    fill: true
  },
  align: 'center',
  padding: {
    left: 10,
    right: 10,
    top: 5,
    bottom: 5
  },
  lineSpacing: 10,
  wordWrap: {
    width: 300,
    useAdvancedWrap: true
  },
  maxLines: 5,
  fixedWidth: 200,
  fixedHeight: 100
};

const text = this.add.text(400, 300, 'Hello', style);

文本方法 #

javascript
const text = this.add.text(400, 300, 'Score: 0', { fontSize: '32px' });

text.setText('Score: 100');

text.setStyle({ color: '#ff0000' });

text.setFontSize('48px');

text.setFontFamily('Georgia');

text.setColor('#00ff00');

text.setBackgroundColor('#333333');

text.setShadow(2, 2, '#000000', 5, true, true);

text.setAlign('center');

text.setPadding(10, 10, 10, 10);

text.setWordWrapWidth(300, true);

const width = text.width;
const height = text.height;

多行文本 #

javascript
const text = this.add.text(100, 100, 'Line 1\nLine 2\nLine 3', {
  fontSize: '24px',
  align: 'center',
  lineSpacing: 10
});

const text = this.add.text(100, 100, '', {
  fontSize: '24px',
  wordWrap: { width: 200 }
});
text.setText('This is a very long text that will wrap automatically.');

图形(Graphics) #

创建图形 #

javascript
const graphics = this.add.graphics();

graphics.fillStyle(0xff0000, 1);
graphics.fillRect(100, 100, 200, 150);

graphics.lineStyle(2, 0x00ff00, 1);
graphics.strokeRect(100, 100, 200, 150);

graphics.fillStyle(0x0000ff, 0.5);
graphics.fillCircle(400, 300, 50);

graphics.lineStyle(3, 0xffff00, 1);
graphics.strokeCircle(400, 300, 50);

绘制方法 #

javascript
const graphics = this.add.graphics();

graphics.fillStyle(0xff0000, 1);
graphics.fillRect(x, y, width, height);

graphics.lineStyle(2, 0x00ff00, 1);
graphics.strokeRect(x, y, width, height);

graphics.fillStyle(0x0000ff, 1);
graphics.fillCircle(x, y, radius);

graphics.lineStyle(2, 0xffff00, 1);
graphics.strokeCircle(x, y, radius);

graphics.lineStyle(2, 0xff00ff, 1);
graphics.lineBetween(x1, y1, x2, y2);

graphics.beginPath();
graphics.moveTo(100, 100);
graphics.lineTo(200, 100);
graphics.lineTo(150, 50);
graphics.closePath();
graphics.strokePath();

graphics.fillStyle(0x00ffff, 1);
graphics.fillTriangle(x1, y1, x2, y2, x3, y3);

graphics.lineStyle(2, 0xff00ff, 1);
graphics.strokeTriangle(x1, y1, x2, y2, x3, y3);

graphics.fillStyle(0xffa500, 1);
graphics.fillRoundedRect(x, y, width, height, radius);

graphics.clear();

渐变填充 #

javascript
const graphics = this.add.graphics();

graphics.fillGradientStyle(0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 1);
graphics.fillRect(100, 100, 200, 150);

形状对象 #

矩形 #

javascript
const rect = this.add.rectangle(x, y, width, height, fillColor, fillAlpha);

const rect = this.add.rectangle(400, 300, 200, 100, 0xff0000);

rect.setStrokeStyle(2, 0x00ff00);

rect.setFillStyle(0x0000ff, 0.5);

圆形 #

javascript
const circle = this.add.circle(x, y, radius, fillColor, fillAlpha);

const circle = this.add.circle(400, 300, 50, 0x00ff00);

circle.setStrokeStyle(3, 0xff0000);

椭圆 #

javascript
const ellipse = this.add.ellipse(x, y, width, height, fillColor, fillAlpha);

const ellipse = this.add.ellipse(400, 300, 100, 50, 0x0000ff);

三角形 #

javascript
const triangle = this.add.triangle(x, y, x1, y1, x2, y2, x3, y3, fillColor, fillAlpha);

const triangle = this.add.triangle(400, 300, 0, 50, 50, -50, 100, 50, 0xffff00);

多边形 #

javascript
const polygon = this.add.polygon(x, y, points, fillColor, fillAlpha);

const polygon = this.add.polygon(400, 300, [0, 0, 50, 100, 100, 50, 50, -50], 0xff00ff);

线条 #

javascript
const line = this.add.line(x, y, x1, y1, x2, y2, strokeColor, strokeAlpha);

const line = this.add.line(400, 300, 0, 0, 100, 100, 0x00ffff);

容器(Container) #

创建容器 #

javascript
const container = this.add.container(x, y);

const container = this.add.container(400, 300);

const image = this.add.image(0, 0, 'player');
const text = this.add.text(0, 50, 'Player 1', { fontSize: '16px' });

container.add([image, text]);

container.add(image);

容器操作 #

javascript
const container = this.add.container(400, 300);

container.add(image);

container.addAt(text, 0);

container.remove(image);

container.removeAt(0);

container.removeAll();

container.moveUp(image);

container.moveDown(image);

container.moveTo(image, 2);

container.swap(image, text);

const first = container.first;
const last = container.last;
const count = container.length;

container.each((child) => {
  child.alpha = 0.5;
});

container.iterate('sprite', (child) => {
  child.setTint(0xff0000);
});

容器属性 #

javascript
const container = this.add.container(400, 300);

container.x = 100;
container.y = 200;

container.rotation = Math.PI / 4;

container.alpha = 0.8;

container.visible = true;

container.setScale(2, 2);

container.setSize(200, 150);

container.setAngle(45);

container.setDepth(10);

container.list.forEach(child => {
  console.log(child);
});

容器嵌套 #

javascript
const outerContainer = this.add.container(400, 300);
const innerContainer = this.add.container(0, 0);

const image = this.add.image(0, 0, 'player');
innerContainer.add(image);

outerContainer.add(innerContainer);

平铺精灵(TileSprite) #

创建平铺精灵 #

javascript
const tileSprite = this.add.tileSprite(x, y, width, height, textureKey);

const tileSprite = this.add.tileSprite(400, 300, 800, 600, 'ground');

平铺精灵滚动 #

javascript
const background = this.add.tileSprite(400, 300, 800, 600, 'sky');

update() {
  background.tilePositionX += 1;
  background.tilePositionY += 0.5;
}

background.setTilePosition(100, 50);

background.setTileScale(2, 2);

background.tileScaleX = 2;
background.tileScaleY = 2;

位图文本(BitmapText) #

创建位图文本 #

javascript
preload() {
  this.load.bitmapFont('font', 'assets/font.png', 'assets/font.xml');
}

create() {
  const text = this.add.bitmapText(x, y, 'font', 'content', size);
  
  const text = this.add.bitmapText(100, 100, 'font', 'Hello World', 32);
}

位图文本属性 #

javascript
const text = this.add.bitmapText(100, 100, 'font', 'Score: 0', 32);

text.setText('Score: 100');

text.setFontSize(48);

text.setLetterSpacing(2);

text.setAlign(1);

text.setTint(0xff0000);

text.setDropShadow(2, 2, 0x000000, 0.5);

渲染纹理(RenderTexture) #

创建渲染纹理 #

javascript
const rt = this.add.renderTexture(x, y, width, height);

const rt = this.add.renderTexture(0, 0, 800, 600);

渲染纹理操作 #

javascript
const rt = this.add.renderTexture(0, 0, 800, 600);

const image = this.add.image(0, 0, 'player').setVisible(false);

rt.draw(image, 100, 100);

rt.draw('player', 200, 200);

rt.clear();

rt.fill(0xff0000, 0.5);

rt.erase(image, 100, 100);

const texture = rt.saveTexture('savedTexture');

const snapshot = rt.snapshot();

游戏对象通用属性 #

变换属性 #

javascript
gameObject.x = 100;
gameObject.y = 200;
gameObject.setPosition(100, 200);

gameObject.scaleX = 2;
gameObject.scaleY = 2;
gameObject.setScale(2, 2);

gameObject.rotation = Math.PI / 4;
gameObject.angle = 45;

gameObject.setOrigin(0.5, 0.5);

显示属性 #

javascript
gameObject.alpha = 0.5;
gameObject.setAlpha(0.5);

gameObject.visible = true;
gameObject.setVisible(true);

gameObject.depth = 10;
gameObject.setDepth(10);

gameObject.setTint(0xff0000);
gameObject.setTint(0xff0000, 0x00ff00, 0x0000ff, 0xffff00);
gameObject.clearTint();

gameObject.setFlipX(true);
gameObject.setFlipY(true);

混合模式 #

javascript
gameObject.setBlendMode(Phaser.BlendModes.NORMAL);
gameObject.setBlendMode(Phaser.BlendModes.ADD);
gameObject.setBlendMode(Phaser.BlendModes.MULTIPLY);
gameObject.setBlendMode(Phaser.BlendModes.SCREEN);

游戏对象事件 #

交互事件 #

javascript
const sprite = this.add.sprite(400, 300, 'button').setInteractive();

sprite.on('pointerdown', (pointer) => {
  console.log('Clicked at', pointer.x, pointer.y);
});

sprite.on('pointerup', (pointer) => {
  console.log('Released');
});

sprite.on('pointerover', (pointer) => {
  sprite.setTint(0xcccccc);
});

sprite.on('pointerout', (pointer) => {
  sprite.clearTint();
});

sprite.on('pointermove', (pointer) => {
  console.log('Moving over sprite');
});

拖拽事件 #

javascript
const sprite = this.add.sprite(400, 300, 'draggable')
  .setInteractive({ draggable: true });

this.input.setDraggable(sprite);

this.input.on('drag', (pointer, gameObject, dragX, dragY) => {
  gameObject.x = dragX;
  gameObject.y = dragY;
});

this.input.on('dragstart', (pointer, gameObject) => {
  gameObject.setTint(0xff0000);
});

this.input.on('dragend', (pointer, gameObject) => {
  gameObject.clearTint();
});

下一步 #

现在你已经掌握了游戏对象,接下来学习 精灵系统,深入了解精灵的创建与管理!

最后更新:2026-03-29