LandonSchropp Posted April 20, 2017 Share Posted April 20, 2017 I'm building a simple tic-tac-toe game in Phaser. I've added a sprite for the board, and I'd like to detect where inside the board the user has clicked so I can add a. Here's what I have so far: let game = new Phaser.Game(380, 720, Phaser.AUTO, '', { preload, create }); function preload() { game.load.image('board', `/images/board.png`); } function create() { // Add the board let board = game.add.sprite(0, 0, 'board'); board.anchor.setTo(0.5, 0.5); board.position = game.world.bounds.size().multiply(0.5, 0.5); // Scale the board so it properly fits in the canvas let scale = game.world.bounds.width / board.width * 0.9; board.scale.setTo(scale, scale); // Listen to clicks on the sprite board.inputEnabled = true; board.events.onInputDown.add(onBoardClick, this); } I'd really love to be able to do something like this: function onBoardClick(sprite, pointer) { // Get the coordinates of the click relative to the bounds inside the board let point = sprite.relativeClickCoordinates; let { x, y } = point.divide(sprite.width, sprite.height).multiply(3, 3); let row = Math.floor(x); let column = Math.floor(y); } Ideally, this would spit out values for row and column between 0 and 2. Obviously relativeClickCoordinates doesn't exist, but I haven't been able to find an equivalent property or function while digging through the Phaser docs. Ideally, the relative coordinates of the click would take into account: The anchor point of the sprite The scale of the sprite The position of the sprite relative to the mouse Is there a simple way to accomplish this? Is there a better way? Thanks in advance! Link to comment Share on other sites More sharing options...
samid737 Posted April 20, 2017 Share Posted April 20, 2017 One way might be to dissect the area of the game manually via switch statements, and check if the mouse pointer lies within a certain range (x,y) and assign the appropriate column/row directly but thats inconvenient if you want a bigger board size. Another possiblity might be to create two groups that contain sprites (X and O).You correctly position each sprite(two nested for loops), enable input to listen to mouseclicks, but set their alpha to zero to hide them. You can add a custom property to each sprite within the most inner for loop: ROWNUMBER and COLUMNNUMBER . Then, if the corresponding player clicks, set either X or O sprite alpha to 1, get corresponding COLUMNNUMBER and ROWNUMBER and continue with your algorithm. Another, maybe more convenient way (maybe not) : Here is an example of a tic-tac-toe game concept purely based upon collision checking (without physics). You can quickly alter the size of the board using this method. Here is the codepen: Basically, you make a group of sprites and a group of hidden (green debug rendered) lines that you use for intersection calculation. Then after each player clicks on his board, it will "notify" any line that intersects with the sprite in that board and mark it. So you are keeping track of the intersect counts that each player has with each line, and if its a winning combination(for example: LINE_ROW2.intersection_list.filter_To("player2").count==3), then you have a winner. Also, since the number of possible "win lines" are 2*boardsize+2*diagonal lines., you can adjust the board size to any dimension. It does not directly answer your problem, but it might give you more ideas on how to approach it within Phaser. Its probably not the standard, quickest/most efficient algorithm, but its an interesting way of demonstrating the usefulness of collision detection. Also using this approach will allow you to retrieve any property you mentioned, such as mouse position (in the collisionCheck function). You can use the pointer object to retrieve the x and y position of your mouse when you click a certain area: http://phaser.io/docs/2.6.2/Phaser.Pointer.html Link to comment Share on other sites More sharing options...
LandonSchropp Posted April 21, 2017 Author Share Posted April 21, 2017 Thanks for the reply! I like all of the ideas, and the collision detection was really interesting! In this case, I think I'd like to keep it simple and do the math, but I'll definitely be keeping a couple of those techniques in my toolbox. I was able to get things working by taking advantage of getBounds. Here's what I did: function onBoardClick(sprite, pointer) { let { x, y, width, height } = sprite.getBounds(); let row = Math.floor((pointer.y - y) * 3 / height); let column = Math.floor((pointer.x - x) * 3 / width); } Thanks again for the help! samid737 1 Link to comment Share on other sites More sharing options...
Recommended Posts