Jump to content

Arcade Physics Overlap Between Rectangle and Sprites


Recommended Posts

Hello people!

I am building an RTS game and I am using phaser 3.22.0. Right now I am implementing the square selection, or multiple sprites selection under a rectangular zone. I was trying to use the following example:

http://labs.phaser.io/edit.html?src=src\physics\arcade\get bodies within rectangle.js

But It never selected My Sprites, just my Map. I don't know Why.

The second one I tryed was to create a rectangle, and watch for an overlap of the sprites and the rectangle. Turns out that it works only if the rectangle has a Positive width and Height. In other words, it Just works when I start my selection from TOP-LEFT to RIGHT-BOTTOM, any other orientation it doesn't work.

 

		squareSelection = this.add
			.rectangle(0, 0, 0, 0)
			.setStrokeStyle(1, 0xffffff)
			.setFillStyle(0xffffff, 0.3);
		this.physics.add.existing(squareSelection);
		squareSelection.body.setSize(0, 0);
		let squareX = 0;
		let squareY = 0;

 

		this.input.on("pointerup", (pointer) => {
			leftPointerDown = false;
			squareSelection.width = setTimeout((timeToSelect) => {
				squareSelection.setSize(0, 0);
				squareSelection.body.setSize(0, 0);
			}, 100);
		});

 

		this.input.on("pointermove", (pointer) => {
			if (leftPointerDown) {
				squareSelection.setSize(
					pointer.worldX - squareX,
					pointer.worldY - squareY
				);
				squareSelection.body.setSize(
					pointer.worldX - squareX,
					pointer.worldY - squareY
				);
			}
		});

 

		this.input.on(
			"pointerdown",
			function (pointer, object) {
				squareX = pointer.worldX;
				squareY = pointer.worldY;
				squareSelection.x = pointer.worldX;
				squareSelection.y = pointer.worldY;
			},
			this
		);

 

		this.physics.add.overlap(gameObjects, squareSelection, (go, square) => {

			if (
				go.type == "Sprite" &&
				!leftPointerDown &&
				squareSelection.width != 0
			) {
				go.setSelection(true);
				this.selectUnitsFromZone();
			}
		});

Is this a bug? Is there anyother solution to implement this feature in my game?

 

My Sprites are all under the Arcade Physics and all of them have a body property.

Thx in Advance

Link to post
Share on other sites
  • 2 weeks later...

All Right, just in case somebody ends up here. And is Having the Same issue.
I found an RTS Game made with Phaser 2.6.x that implemented something similar to what I Wanted to do. As I'm currently using Phaser 3.22.0 I had to make some changes in order to it to Work.

Here goes the solution I ended up implementing.

I Created an Object that had a Rectangle that would check for Overllap of objects later on.

			this.select = {
				//stores data about mouse events for the rectangle selection
				origin: new Phaser.Geom.Point(), //origin of mouse click
				current: new Phaser.Geom.Point(), //current mouse position
				topLeft: new Phaser.Geom.Point(), //top left mouse position
				width: 0, //rectangle width
				height: 0, //rectangle height
				isActive: false, //determines if a previous point was stored
				rect: new Phaser.Geom.Rectangle(this.scene, 0, 0, 0, 0, 0xffffff, 0.4),
				selectionSquare: new Phaser.GameObjects.Graphics(this.scene),
			};

I also had Listeners to Handle if the Pointer was moving and if it was the left button that was clicked. (Inside of the constructor of my class)

			this.scene.input.on("pointermove", (pointer) => {
				if (leftPointerDown) {
					this.isDraging = true;
				} else {
					this.isDraging = false;
				}
			});
			this.scene.input.on("pointerup", (pointer) => {
				if (pointer.leftButtonReleased()) {
					leftPointerDown = false;
					this.onLeftButtonUp();
				}
			});

After that I had to make the square selection change it's size when the user left clicked and moved the mouse. I put the method inside my update game loop, so It would detect any changes. You should notice that I pass in my pointer.

	update() {
		movementPattern.updateSelectionRect(pointer);
	}

Back to my custom class, I implemented the selection handler.

	updateSelectionRect(pointer) {
		var mousePointer = pointer;

		if (leftPointerDown) {
			this.select.current.setTo(
				mousePointer.worldX + this.scene.cameras.main.x,
				mousePointer.worldY + this.scene.cameras.main.y
			);

			if (this.select.isActive) {
				if (
					this.select.origin.x < this.select.current.x &&
					this.select.current.y < this.select.origin.y
				) {
					//its to the right and above

					this.select.topLeft.setTo(
						this.select.origin.x,
						this.select.current.y
					);
				} else if (
					this.select.origin.x < this.select.current.x &&
					this.select.current.y > this.select.origin.y
				) {
					//its to the right and below
					this.select.topLeft.setTo(this.select.origin.x, this.select.origin.y);
				} else if (
					this.select.origin.x > this.select.current.x &&
					this.select.current.y > this.select.origin.y
				) {
					//its to the left and below
					this.select.topLeft.setTo(
						this.select.current.x,
						this.select.origin.y
					);
				} else {
					//its to the left and above

					this.select.topLeft.setTo(
						this.select.current.x,
						this.select.current.y
					);
				}

				var width = (this.select.width = Math.abs(
					this.select.origin.x - this.select.current.x
				));
				var height = (this.select.height = Math.abs(
					this.select.origin.y - this.select.current.y
				));
				var rectangle = this.select.rect;
				rectangle.x = this.select.topLeft.x;
				rectangle.y = this.select.topLeft.y;
				rectangle.width = width;
				rectangle.height = height;
				this.scene.add.existing(rectangle);
				var graphics = this.select.selectionSquare;
				graphics.clear();
				graphics.fillStyle(0xffffff, 0.4);
				graphics.fillRect(
					this.select.topLeft.x,
					this.select.topLeft.y,
					width,
					height
				);
				this.scene.add.existing(graphics);
			} else {
				//capture the current coordinate and store as origin
				var rectangle = this.select.rect;
				this.select.origin.setTo(this.select.current.x, this.select.current.y);
				rectangle.x = this.select.topLeft.x;
				rectangle.y = this.select.topLeft.y;
				rectangle.width = this.select.width;
				rectangle.height = this.select.height;
				this.scene.add.existing(rectangle);
				var graphics = this.select.selectionSquare;
				graphics.clear();
				graphics.fillStyle(0xffffff, 0.4);
				graphics.fillRect(
					this.select.topLeft.x,
					this.select.topLeft.y,
					this.select.width,
					this.select.height
				);
				this.scene.add.existing(graphics);
				this.select.isActive = true;
			}
		}
	}

And Finally, when the mouse is released I Select the Units and Reset my selection Object.

	/**
        Handles left button release.
    */
	onLeftButtonUp() {
		this.updateSelectedGroup();

		this.select.isActive = false;
		this.select.origin.setTo(0, 0);
		this.select.current.setTo(0, 0);
		this.select.topLeft.setTo(0, 0); //top left of selection rect
		this.select.width = 0; //width of rect
		this.select.height = 0; //height of rect

		this.select.rect.x = 0;
		this.select.rect.y = 0;
		this.select.rect.width = 0;
		this.select.rect.height = 0;

		this.select.selectionSquare.clear();
	}

Here is the Group Selection.

	/**
        Updates the group members selected property.
    */
	updateSelectedGroup() {
		this.bodies = this.scene.physics.overlapRect(
			this.select.topLeft.x,
			this.select.topLeft.y,
			this.select.rect.width,
			this.select.rect.height
		);

		selectedUnits = [];
		for (let i = 0; i < this.bodies.length; i++) {
			let unit = this.bodies[i].gameObject;
			if (
				unit.type == "Sprite" &&
				this.select.selectionSquare.width != 0 &&
				unit.team == this.team
			) {
				unit.setSelection(true);
				selectedUnits.push(unit);
			}
		}
	}

I hope It helps somebody that Needs to make something like this. With little changes it should work in your game as well.

Special Thanks to nhays89 that posted his code on GitHub as a, https://github.com/nhays89/BELPhaser

I had a code pretty similar to his code, but couldn't manage the propper orientation selection as I described in the beggining of this topic.

70 to 80% of this code is his, thx man!

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...