Phaser object not Draggable

题意:“Phaser 对象不可拖动”

问题背景:

This code does not allow the rectangle w/topbar to be draggable. What do I need to change? I created a scrollabel Phaser scene and can get the 'box' to draw but it is not draggable. When the user selects the topbar I want to be able to move the box in any direction within the phaser container.

“这段代码不允许带有顶部栏的矩形可拖动。我需要更改什么?我创建了一个可滚动的 Phaser 场景,并且能够绘制出 'box',但它不可拖动。当用户选择顶部栏时,我希望能够在 Phaser 容器内的任何方向移动该框。”

This code creates the phaser scene and the scene is scrollabel x and y but the box crateed can not be selected or dragged.

“这段代码创建了 Phaser 场景,场景可以在 x 和 y 方向滚动,但创建的框无法被选中或拖动。”

let currentScene; // Global variable to store the current scene
let mainRect, topBar; // Global variables to store the main rectangle and top bar
let isDragging = false; // Variable to track if dragging is in progress

function preload() {
  console.log("Preload function called"); // Log when preload is called
  // Load assets here if needed
}

function create() {
  console.log("Create function called"); // Log when create is called
  // Assign the created scene to currentScene
  currentScene = this;

  // Log the current scene
  console.log("Current Scene:", currentScene);

  // Enable camera controls for scrolling
  this.cameras.main.setBounds(0, 0, 5000, 300); // Set the bounds of the camera
  this.cameras.main.setScroll(0, 0); // Initialize the camera position

  // Add event listener to handle two-finger scrolling within the Phaser canvas
  this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => {
    if (!isDragging) {
      this.cameras.main.scrollX += deltaX;
      this.cameras.main.scrollY += deltaY;
    }
  });

  // Add touch event listeners to handle touch-based scrolling within the Phaser canvas
  this.input.on('pointerdown', (pointer) => {
    if (pointer.isDown && !isDragging) {
      this.input.dragStartX = pointer.x;
      this.input.dragStartY = pointer.y;
      this.input.cameraStartX = this.cameras.main.scrollX;
      this.input.cameraStartY = this.cameras.main.scrollY;
    }
  });

  this.input.on('pointermove', (pointer) => {
    if (pointer.isDown && !isDragging) {
      const deltaX = pointer.x - this.input.dragStartX;
      const deltaY = pointer.y - this.input.dragStartY;
      this.cameras.main.scrollX = this.input.cameraStartX - deltaX;
      this.cameras.main.scrollY = this.input.cameraStartY - deltaY;
    }
  });

  // Expose createActivityObject to the global scope for button click
  window.createActivityObject = () => createActivityObjectInternal(currentScene);
}

function update() {
  // Log the positions of the main rectangle and top bar during the update
  if (mainRect && topBar) {
    console.log(`Update - mainRect: (${mainRect.x}, ${mainRect.y}), topBar: (${topBar.x}, ${topBar.y})`);
  }
}

const config = {
  type: Phaser.AUTO,
  width: 5000, // Set the width of the visible area
  height: 300, // Set the height of the visible area
  parent: "phaser-container",
  backgroundColor: 'rgb(200, 249, 251)', // Set the background color of the Phaser scene
  scene: {
    preload: preload,
    create: create,
    update: update,
  },
  render: {
    pixelArt: true, // Enable pixel art rendering for sharper edges
    antialias: false, // Disable antialiasing for sharper edges
  },
};

document.addEventListener("DOMContentLoaded", () => {
  console.log("DOMContentLoaded event fired"); // Log when DOMContentLoaded event fires
  let game = new Phaser.Game(config);
  console.log("Game:", game); // Log the game object

  // Add event listener to the button to create the draggable object
  document.getElementById("create-activity-button").addEventListener("click", () => {
    if (currentScene) {
      createActivityObjectInternal(currentScene);
    }
  });
});

// Internal function to create a draggable rectangle with a top bar
function createActivityObjectInternal(scene) {
  console.log("Creating activity object"); // Log the function call
  console.log("The scene is: ", scene); // Log the scene object

  if (!scene) {
    console.error("Scene is not defined");
    return;
  }

  const scale = 0.15; // Scale factor to reduce size to 15%
  const rectWidth = 400 * scale * 1.5; // Increase width by 50%
  const rectHeight = 100 * scale; // Keep height the same
  const topBarHeight = 12 * scale;
  const rectX = 100;
  const rectY = 100;

  // Create the main rectangle
  mainRect = scene.add.rectangle(rectX, rectY + topBarHeight, rectWidth, rectHeight - topBarHeight, 0xffffff).setOrigin(0);
  mainRect.setStrokeStyle(2 * scale, 0x000000);
  mainRect.setDepth(1); // Ensure the main rectangle is on top
  console.log("Main rectangle created:", mainRect); // Log the main rectangle creation

  // Create the top bar
  topBar = scene.add.rectangle(rectX, rectY, rectWidth, topBarHeight, 0xffa500).setOrigin(0);
  topBar.setStrokeStyle(2 * scale, 0xffa500);
  topBar.setDepth(2); // Ensure the top bar is on top
  console.log("Top bar created:", topBar); // Log the top bar creation

  // Ensure the topBar is created before making it draggable
  if (topBar) {
    console.log("Top bar is not null or undefined"); // Log the top bar check

    // Check if input plugin is available
    if (scene.input) {
      console.log("Input plugin is available"); // Log input plugin availability

      // Add the top bar to the input system
      topBar.setInteractive();
      scene.input.setDraggable(topBar);
      console.log("Top bar added to input system and set as draggable"); // Log input system addition and draggable setting

      // Handle dragging
      scene.input.on("dragstart", (pointer, gameObject) => {
        console.log("Drag start:", gameObject); // Log drag start
        isDragging = true; // Disable scrolling
      });

      scene.input.on("drag", (pointer, gameObject, dragX, dragY) => {
        if (gameObject === topBar) {
          mainRect.x = dragX;
          mainRect.y = dragY + topBarHeight;
          topBar.x = dragX;
          topBar.y = dragY;
          console.log("Dragging:", { dragX, dragY }); // Log dragging coordinates
        }
      });

      scene.input.on("dragend", (pointer, gameObject) => {
        console.log("Drag end:", gameObject); // Log drag end
        isDragging = false; // Re-enable scrolling
      });
    } else {
      console.error("Input plugin is not available");
    }
  } else {
    console.error("Failed to create topBar");
  }
}

问题解决:

Well first of all there are two point I would like to make:

“首先,我想提出两点:”

  • Great question and good documentation   “很好的问题,并且文档写得很好。”
  • BUT you should only post relevant code to make the question easier/fast to read and solve the issue (AND while making a MRE you might even find the bug yourself).   “但你应该只发布相关的代码,以便让问题更容易/快速阅读和解决(同时在创建最小可复现示例(MRE)时,你甚至可能自己发现问题)。”

This out of the way, while shortening your code (see demo below), I go a functioning build.

“说到这里,在简化你的代码时(见下面的演示),我得到了一个可运行的版本。”

I think the Problem is scene.input.setDraggable(topBar);, I removed this line and activated the dragging functionality through the .setInteractive({ draggable: true }) method on the topBar.
With this the dragging should work.

“我认为问题出在 `scene.input.setDraggable(topBar);` 这一行。我删除了这行代码,并通过 `topBar.setInteractive({ draggable: true })` 方法激活了拖动功能。这样拖动应该就能正常工作了。”

Short Demo:
(ShowCasing this)

简短的示例:

let currentScene;
let isDragging = false;

function create() {
  console.log("Create function called"); // Log when create is called
  // Assign the created scene to currentScene
  currentScene = this;

  console.log("Current Scene:", currentScene);

  this.cameras.main.setBounds(0, 0, 5000, 300);
  this.cameras.main.setScroll(0, 0);

  window.createActivityObject = () => createActivityObjectInternal(currentScene);
}

const config = {
  width: 500,
  height: 180,
  parent: "phaser-container",
  scene: { create },
};

new Phaser.Game(config);

document.getElementById("create-activity-button").addEventListener("click", () => {
  if (currentScene) {
    createActivityObjectInternal(currentScene);
  }
});


function createActivityObjectInternal(scene) {

  if (!scene) {
    console.error("Scene is not defined");
    return;
  }

  const rectWidth = 100;
  const rectHeight = 50;
  const topBarHeight = 20;
  const pos = {x: 100, y:100};

  let mainRect = scene.add.rectangle(pos.x, pos.y + topBarHeight, rectWidth, rectHeight - topBarHeight, 0xffffff).setOrigin(0).setStrokeStyle(2, 0x000000);
  let topBar = scene.add.rectangle(pos.x, pos.y, rectWidth, topBarHeight, 0xffa500).setOrigin(0).setStrokeStyle(1 , 0xffa500).setInteractive({ draggable: true });
  

  scene.input.on("drag", (pointer, gameObject, dragX, dragY) => {
    if (gameObject === topBar) {
      topBar.x = dragX;
      topBar.y = dragY; 
      mainRect.x = dragX;
      mainRect.y = dragY + topBarHeight;
    }
  });

}

console.clear();
document.body.style = 'margin:0;';
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

<button id="create-activity-button">ADD STUFF</button>
<br />

btw.: if you are creating multipe "Items" with the Button, defining mainRect and topBar global will create an issue. For the demo I moved the definition to the function createActivityObjectInternal scope, but if you want to use them outside this function, you would have to find a better solution.

“顺便提一下:如果你使用按钮创建多个 'Items',将 `mainRect` 和 `topBar` 定义为全局变量会导致问题。在演示中,我将定义移动到了 `createActivityObjectInternal` 函数的作用域内,但如果你想在该函数外使用它们,你需要找到一个更好的解决方案。”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

营赢盈英

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值