Sky Alpha Posted April 13, 2020 Share Posted April 13, 2020 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 comment Share on other sites More sharing options...
Sky Alpha Posted April 16, 2020 Author Share Posted April 16, 2020 How should I make a Selection box for a group of Sprites? Any help? Link to comment Share on other sites More sharing options...
Sky Alpha Posted April 30, 2020 Author Share Posted April 30, 2020 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 comment Share on other sites More sharing options...
Recommended Posts