Tiled碰撞编辑器,Phaser中正在使用的对象图层。

huangapple go评论101阅读模式
英文:

Tiled collision editor, object layer in use in Phaser

问题

Tiled碰撞编辑器,Phaser中正在使用的对象图层。

Tiled碰撞编辑器,Phaser中正在使用的对象图层。

我已经在Tiled中以这种方式添加了树碰撞。如何在Phaser中使用这个碰撞与玩家发生碰撞?

英文:

Tiled碰撞编辑器,Phaser中正在使用的对象图层。

Tiled碰撞编辑器,Phaser中正在使用的对象图层。

I have added tree collision this way in Tiled.
How can I use this collision to collide with the player in Phaser?

答案1

得分: 1

这是一个示例代码,用于处理Tiled地图中的碰撞物体。以下是其中的一些部分的翻译:

  1. 获取Tiled地图中指定名称的对象层 链接到文档

    1. let objectLayer = map.getObjectLayer('Trees');
  2. 遍历该层中的所有对象 链接到文档

    1. for (let obj of objectLayer.objects) {
    2. // ...
    3. }
  3. 针对每个来自该层的对象:
    根据对象类型(点、矩形、椭圆等)创建碰撞用的物理体(在此示例中使用椭圆):

    1. let ellipse = this.add.ellipse(obj.x, obj.y, obj.width, obj.height);
    2. // 你可能需要设置“origin”
    3. this.physics.add.existing(ellipse, true);
    4. ellipse.body.setCircle(obj.width / 2);
  4. 设置与玩家、AI等的碰撞:

    1. this.physics.add.collider(player, ellipse);

请注意,这段代码中的关键部分用于处理Tiled地图中的对象和碰撞,以及如何为它们创建适当的物理体。希望这有所帮助。

英文:

Well there are many way's to do this, this is one way:

<!-- language-all: lang-js -->

  1. get object layer, with the name from Tiled (link to the documentation):

    1. // let map = this.make.tilemap( {...} );
    2. let objectLayer = map.getObjectLayer( &#39;Trees&#39; );
  2. iterate over all objects from that layer (link to the documentation):

    1. for( let obj in objectLayer.objects ){
    2. // ...
    3. }
  3. For each object from the layer:
    Depending on your object type (point, rectangle, ellipse, ...) you create the physics-body for the collision (for this example I will use a ellipse):

    1. let ellipse = this.add.ellipse( obj.x, obj.y, obj.width, obj.height );
    2. // you might need to set the &quot;origin&quot;
    3. this.physics.add.existing( ellipse, true );
    4. ellipse.body.setCircle(obj.width / 2);

    > Info/Tipp: if you are using arcade physics the "hitbox" will be a rectangle, doesn't matter which gameObject you use. If you want round physics body with arcade you could use the setCircle method on the body (link to documentation). For complex shapes I would recommend using the matter.js engine.

  4. Setup collision with: player, ai, ...

    1. this.physics.add.collider( player, ellipse );

Updated running demo:

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

  1. document.body.style = &#39;margin:0;&#39;;
  2. let json_map = {&quot;compressionlevel&quot;:-1,&quot;height&quot;:5,&quot;infinite&quot;:false,&quot;layers&quot;:[{&quot;compression&quot;:&quot;&quot;,&quot;data&quot;:&quot;AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==&quot;,&quot;encoding&quot;:&quot;base64&quot;,&quot;height&quot;:5,&quot;id&quot;:1,&quot;name&quot;:&quot;TileLayer1&quot;,&quot;opacity&quot;:1,&quot;type&quot;:&quot;tilelayer&quot;,&quot;visible&quot;:true,&quot;width&quot;:8,&quot;x&quot;:0,&quot;y&quot;:0},{&quot;draworder&quot;:&quot;topdown&quot;,&quot;id&quot;:2,&quot;name&quot;:&quot;ObjectLayer1&quot;,&quot;objects&quot;:[{&quot;class&quot;:&quot;&quot;,&quot;ellipse&quot;:true,&quot;height&quot;:10,&quot;id&quot;:1,&quot;name&quot;:&quot;&quot;,&quot;rotation&quot;:0,&quot;visible&quot;:true,&quot;width&quot;:10,&quot;x&quot;:8,&quot;y&quot;:8},{&quot;class&quot;:&quot;&quot;,&quot;height&quot;:5,&quot;id&quot;:2,&quot;name&quot;:&quot;&quot;,&quot;rotation&quot;:0,&quot;visible&quot;:true,&quot;width&quot;:15,&quot;x&quot;:19.2,&quot;y&quot;:25.6},{&quot;class&quot;:&quot;&quot;,&quot;height&quot;:0,&quot;id&quot;:3,&quot;name&quot;:&quot;&quot;,&quot;point&quot;:true,&quot;rotation&quot;:0,&quot;visible&quot;:true,&quot;width&quot;:0,&quot;x&quot;:48,&quot;y&quot;:4.8}],&quot;opacity&quot;:1,&quot;type&quot;:&quot;objectgroup&quot;,&quot;visible&quot;:true,&quot;x&quot;:0,&quot;y&quot;:0}],&quot;nextlayerid&quot;:3,&quot;nextobjectid&quot;:4,&quot;orientation&quot;:&quot;orthogonal&quot;,&quot;renderorder&quot;:&quot;right-down&quot;,&quot;tiledversion&quot;:&quot;1.9.2&quot;,&quot;tileheight&quot;:8,&quot;tilesets&quot;:[{&quot;columns&quot;:1,&quot;firstgid&quot;:1,&quot;image&quot;:&quot;tiles.png&quot;,&quot;imageheight&quot;:8,&quot;imagewidth&quot;:8,&quot;margin&quot;:0,&quot;name&quot;:&quot;tiles&quot;,&quot;spacing&quot;:0,&quot;tilecount&quot;:1,&quot;tileheight&quot;:8,&quot;tilewidth&quot;:8}],&quot;tilewidth&quot;:8,&quot;type&quot;:&quot;map&quot;,&quot;version&quot;:&quot;1.9&quot;,&quot;width&quot;:8};
  3. let config = {
  4. type: Phaser.AUTO,
  5. width: 8 * 8,
  6. height: 5 * 8,
  7. zoom: 4,
  8. physics: {
  9. default: &#39;arcade&#39;,
  10. arcade: { debug: true }
  11. },
  12. scene: { preload, create },
  13. };
  14. function preload () {
  15. this.load.tilemapTiledJSON(&#39;map&#39;, json_map);
  16. }
  17. function create () {
  18. let graphics = this.make.graphics();
  19. graphics.fillStyle(0x933AFF);
  20. graphics.fillRect(0, 0, 10, 10);
  21. graphics.generateTexture(&#39;tiles&#39;, 10, 10);
  22. let player = this.add.rectangle(50, 10, 5, 5, 0xffffff);
  23. this.physics.add.existing(player);
  24. player.setDepth(100);
  25. player.body.setVelocityX(-10);
  26. let map = this.make.tilemap({ key: &#39;map&#39;, tileWidth: 8, tileHeight: 8 });
  27. let tiles = map.addTilesetImage(&#39;tiles&#39;, &#39;tiles&#39;);
  28. let layer = map.createLayer(0, tiles, 0, 0);
  29. let objectLayer = map.getObjectLayer( &#39;ObjectLayer1&#39; );
  30. for( let obj of objectLayer.objects ){
  31. // since you are not displaying the object the shape doesn&#39;t matter, only the collision body
  32. let gameObject = this.add.rectangle( obj.x, obj.y, obj.width, obj.height )
  33. .setOrigin(0);
  34. this.physics.add.existing( gameObject, true );
  35. if(obj.ellipse){
  36. // For the ellipse version you would need to change the body
  37. gameObject.body.setCircle( obj.width / 2 );
  38. } else if(obj.point){
  39. // For the point we need no set an width and height
  40. gameObject.body.setSize( 4, 4 );
  41. }
  42. this.physics.add.collider( player, gameObject );
  43. }
  44. }
  45. new Phaser.Game(config);

<!-- language: lang-html -->

  1. &lt;script src=&quot;//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

> Btw.: In my Tiled version even, when I create the circle-object the width and height, I had to set does properties manualy. So check them if they are set.
>
> Tiled碰撞编辑器,Phaser中正在使用的对象图层。

答案2

得分: 0

  1. 最终,我找到了解决方案,这对我有效。
  2. addCollisionFromTiled(layerName: string, group: number) {
  3. const graphics = this.scene.add.graphics().lineStyle(2, 0x00ff00, 1)
  4. const objectLayer = this.map.getObjectLayer(layerName)
  5. objectLayer.objects.forEach((object: Phaser.Types.Tilemaps.TiledObject) => {
  6. if (object.rectangle) {
  7. const rect2 = this.scene.add.rectangle(0, 0, object.width, object.height)
  8. const polygon = new Phaser.Geom.Polygon(rect2.pathData)
  9. const body2 = this.scene.matter.add.fromVertices(
  10. object.x! + object.width! / 2,
  11. object.y! + object.height! / 2,
  12. polygon.points.slice(0, -1)
  13. )
  14. const collision = this.scene.matter.add.gameObject(
  15. rect2,
  16. body2
  17. ) as Phaser.Physics.Matter.Sprite
  18. collision.setStatic(true)
  19. collision.setCollisionGroup(group)
  20. graphics.strokeRect(object.x!, object.y!, object.width!, object.height!)
  21. } else if (object.ellipse) {
  22. const elps2 = this.scene add ellipse(0, 0, object.width, object.height)
  23. const polygon = new Phaser.Geom.Polygon(elps2.pathData)
  24. const body2 = this.scene.matter add fromVertices(
  25. object.x! + object.width! / 2,
  26. object.y! + object.height! / 2,
  27. polygon.points.slice(0, -1)
  28. )
  29. const collision = this.scene.matter add gameObject(
  30. elps2,
  31. body2
  32. ) as Phaser.Physics.Matter.Sprite
  33. collision.setStatic(true)
  34. collision.setCollisionGroup(group)
  35. graphics.strokeEllipse(
  36. object.x! + object.width! / 2,
  37. object.y! + object.height! / 2,
  38. object.width!,
  39. object.height!
  40. )
  41. } else if (object.polygon || object.polyline) {
  42. const objPol = object.polygon ? object.polygon : object.polyline
  43. const polygon = new Phaser.Geom.Polygon(objPol)
  44. const points: { x: number; y: number }[] = []
  45. for (let point of polygon.points) {
  46. points.push({
  47. x: object.x! + point.x,
  48. y: object.y! + point.y,
  49. })
  50. }
  51. const sliceCentre = this.scene.matter.vertices.centre(points)
  52. const body2 = this.scene.matter.add.fromVertices(sliceCentre.x, sliceCentre.y, points)
  53. const poly2 = this.scene.add.polygon(sliceCentre.x, sliceCentre.y, points)
  54. const collision = this.scene.matter.add.gameObject(
  55. poly2,
  56. body2
  57. ) as Phaser.Physics.Matter.Sprite
  58. collision.setStatic(true)
  59. collision.setCollisionGroup(group)
  60. graphics.strokePoints(points)
  61. }
  62. })
  63. }
英文:

Finally, I got a solution, and this is working for me.

  1. addCollisionFromTiled(layerName: string, group: number) {
  2. const graphics = this.scene.add.graphics().lineStyle(2, 0x00ff00, 1)
  3. const objectLayer = this.map.getObjectLayer(layerName)
  4. objectLayer.objects.forEach((object: Phaser.Types.Tilemaps.TiledObject) =&gt; {
  5. if (object.rectangle) {
  6. const rect2 = this.scene.add.rectangle(0, 0, object.width, object.height)
  7. const polygon = new Phaser.Geom.Polygon(rect2.pathData)
  8. const body2 = this.scene.matter.add.fromVertices(
  9. object.x! + object.width! / 2,
  10. object.y! + object.height! / 2,
  11. polygon.points.slice(0, -1)
  12. )
  13. const collision = this.scene.matter.add.gameObject(
  14. rect2,
  15. body2
  16. ) as Phaser.Physics.Matter.Sprite
  17. collision.setStatic(true)
  18. collision.setCollisionGroup(group)
  19. graphics.strokeRect(object.x!, object.y!, object.width!, object.height!)
  20. } else if (object.ellipse) {
  21. const elps2 = this.scene.add.ellipse(0, 0, object.width, object.height)
  22. const polygon = new Phaser.Geom.Polygon(elps2.pathData)
  23. const body2 = this.scene.matter.add.fromVertices(
  24. object.x! + object.width! / 2,
  25. object.y! + object.height! / 2,
  26. polygon.points.slice(0, -1)
  27. )
  28. const collision = this.scene.matter.add.gameObject(
  29. elps2,
  30. body2
  31. ) as Phaser.Physics.Matter.Sprite
  32. collision.setStatic(true)
  33. collision.setCollisionGroup(group)
  34. graphics.strokeEllipse(
  35. object.x! + object.width! / 2,
  36. object.y! + object.height! / 2,
  37. object.width!,
  38. object.height!
  39. )
  40. } else if (object.polygon || object.polyline) {
  41. const objPol = object.polygon ? object.polygon : object.polyline
  42. const polygon = new Phaser.Geom.Polygon(objPol)
  43. const points: { x: number; y: number }[] = []
  44. for (let point of polygon.points) {
  45. points.push({
  46. x: object.x! + point.x,
  47. y: object.y! + point.y,
  48. })
  49. }
  50. const sliceCentre = this.scene.matter.vertices.centre(points)
  51. const body2 = this.scene.matter.add.fromVertices(sliceCentre.x, sliceCentre.y, points)
  52. const poly2 = this.scene.add.polygon(sliceCentre.x, sliceCentre.y, points)
  53. const collision = this.scene.matter.add.gameObject(
  54. poly2,
  55. body2
  56. ) as Phaser.Physics.Matter.Sprite
  57. collision.setStatic(true)
  58. collision.setCollisionGroup(group)
  59. graphics.strokePoints(points)
  60. }
  61. })
  62. }

huangapple
  • 本文由 发表于 2023年2月24日 07:57:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551462.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定