You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让2D游戏角色随移动平台同步移动?

实现角色随Tween移动平台同步移动的方案

我在2D游戏中做了一个角色和通过Tween实现左右移动的平台,平台是用TiledMapEditor创建的对象并赋予纹理生成的。现在想实现角色站在平台上时能跟着一起移动,试过多种方法都没成功,求解决办法。

现有代码

MovementPlatform.ts

import {
  ActorProps,
  ICollectable,
  IDieable,
  IMoveable,
} from "@games/common/interfaces";
import { Actor } from "@games/common/objects";

export default class MovementPlatform
  extends Actor
  implements IMoveable, IDieable, ICollectable {
  declare body: Phaser.Physics.Arcade.Body;
  declare startX;
  constructor(props: ActorProps) {
    super(props);
    this.scene.physics.add.existing(this);
    this.body.setAllowGravity(false);
    this.body.immovable = true;
    this.startX = this.x;

    this.move();
  }

  update(...args: any[]): void { }

  die(): void { }

  move(): void {
    this.scene.tweens.add({
      targets: this,
      x: this.startX + 200,
      duration: 1000,
      yoyo: true,
      repeat: -1,
    });
  }

  collect(...props: any[]): void { }
}

生成移动平台的代码(已正常工作)

private spawnMovementPlatform() {
  const movementPlatformTiles = getObjectsByType(
    "movementPlatform",
    this.map
  );

  movementPlatformTiles.forEach((el: Phaser.Tilemaps.Tile, i: number) => {
    const movementplatform = new MovementPlatform({
      key: `movementPlatform-${this.movements.length}`,
      scene: this,
      texture: "movementPlatform",
      x: el.x,
      y: el.y + 200,
    }).setDepth(3);

    this.movements.push(movementplatform);
  });
}

当前碰撞器代码

this.physics.add.collider(this.player, this.movements, () => {});

解决方案

核心问题是:Tween直接修改平台的x属性,但Phaser物理系统不会自动把平台的位移同步给站在上面的角色,需要手动处理位移同步。

1. 修改MovementPlatform类,记录位移增量

给平台添加属性记录上一帧的位置,在update方法中计算每一帧的位移差,同时同步物理碰撞体的位置:

import {
  ActorProps,
  ICollectable,
  IDieable,
  IMoveable,
} from "@games/common/interfaces";
import { Actor } from "@games/common/objects";

export default class MovementPlatform
  extends Actor
  implements IMoveable, IDieable, ICollectable {
  declare body: Phaser.Physics.Arcade.Body;
  declare startX;
  private prevX: number; // 新增:记录上一帧的x坐标

  constructor(props: ActorProps) {
    super(props);
    this.scene.physics.add.existing(this);
    this.body.setAllowGravity(false);
    this.body.immovable = true;
    this.startX = this.x;
    this.prevX = this.x; // 初始化上一帧坐标

    this.move();
  }

  update(...args: any[]): void {
    // 计算当前帧的位移差,同步物理碰撞体位置
    const deltaX = this.x - this.prevX;
    this.body.x += deltaX;
    this.prevX = this.x; // 更新上一帧坐标
  }

  die(): void { }

  move(): void {
    this.scene.tweens.add({
      targets: this,
      x: this.startX + 200,
      duration: 1000,
      yoyo: true,
      repeat: -1,
    });
  }

  collect(...props: any[]): void { }
}

2. 修改碰撞器回调,同步角色位移

在碰撞回调中判断角色是否站在平台上方,只有满足条件时才把平台的位移增量同步给角色:

this.physics.add.collider(this.player, this.movements, (player, platform) => {
  const movementPlatform = platform as MovementPlatform;
  // 确保角色是站在平台顶部(避免侧面碰撞触发同步)
  if (player.body.touching.down && movementPlatform.body.touching.up) {
    const deltaX = movementPlatform.x - movementPlatform.prevX;
    player.x += deltaX;
    // 如果角色使用物理系统控制,也可以同步body的位置
    player.body.x += deltaX;
  }
});

3. 关键说明

  • 保持平台的immovable: true,避免角色推动平台;
  • 同步body.x是为了让物理碰撞体和视觉对象位置一致,防止碰撞判断出现偏移;
  • 碰撞条件判断确保只有角色站在平台上时才同步位移,避免误触发。

内容的提问来源于stack exchange,提问作者yunusemre agdin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 15:16:04