How do I set up a grid-based area check

  • Heya

    Been trying to think of the best ways to do the following. I wanted a top down project where an npc can be clicked and ordered to move to a position if that gridspace is free. movement and everything is easy enough to set up with the pathfinding tool, but the area check is what's giving me pause.

    Was wondering if, rather than having the npc move to mouse.x, mouse.y, instead I should spawn an invisible sprite that spawns in that grid space and acts as a beacon, remaining in that area until the npc either dies or moves to another area. that way, when you click to move an npc to an area, the beacon won't spawn in that area if there's already one in the space, and so the next npc can't move.

    It seems a bit convoluted though, and I don't like that I'm effectively doubling the number of instances in the level by doing this.

    It might also be better than the second npc can move in the general area of the first, and instead fill an empty space adjacent to the targeted area.

    Is there a better way to handle this?

    Cheers

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Instead of spawning a beacon object you could add instance variables to the npc: "targetX" "targetY" .

    On mouse click, if there is no NPC in the space set targetX, targetY to mouse.X,mouse.Y. and trigger the pathfinding.

  • .... that way, when you click to move an npc to an area, the beacon won't spawn in that area if there's already one in the space, and so the next npc can't move. ...

    Sounds like a valid solution to me. But. You gonna have all sort of little problems due the spawning. Mainly because you can not use a newly created object to evaluate things before the next top level event. You also need a system that pairs NPC to its target. That is easily done with instance variables, yet will force you in a lot of picking. And in the end you win nothing to little compared to the already proposed solution.

    Still, it is handy to just have a target sitting on that place to just simple (Line of Sight) know if there is already a NPC heading to that place. I suggest bringing the target in a container with the NPC. Target will be picked when you pick the NPC. NPC will be picked when you pick the target. So, they are strictly paired up. When one dies, the other dies.

  • Thanks for the replies

    Instead of spawning a beacon object you could add instance variables to the npc: "targetX" "targetY" .

    On mouse click, if there is no NPC in the space set targetX, targetY to mouse.X,mouse.Y. and trigger the pathfinding.

    I thought of that originally, but the issue with that, as 99instances2Go points out, is that it's not checking if there's another unit moving towards that space.

    Sounds like a valid solution to me. But. You gonna have all sort of little problems due the spawning. Mainly because you can not use a newly created object to evaluate things before the next top level event. You also need a system that pairs NPC to its target. That is easily done with instance variables, yet will force you in a lot of picking. And in the end you win nothing to little compared to the already proposed solution.

    I considered setting an alarm when clicking a unit to move it, so that it waits like .1 of a second before checking the area and moving off, as I thought timing might be an issue. I'm going purely theoretical though so I haven't tested anything but thought there might be some timing issues involved. It seems like a really clunky idea though and I'm convinced it's a silly way of doing it.

    I may have missed something though, but what's 'the already proposed solution' that you mention? Or are you referring to mekonbekon's post?

    Cheers

  • You could also use an array t do this and just store the uid of the object in a grid space (beware one object will have a uid of 0).

    So assuming you set up the level so at most one object is in a grid you could do:

    Start of layout

    --- array: set size to (layoutwidth/32, layoutheight/32, 1)

    --- for each sprite

    ------ array: set at (sprite.x/32, sprite.y/32) to sprite.uid

    so basically if a grid location is 0 it's empty otherwise it's the uid of the object in it. To do movement you'd set the grid of the destination grid to the uid first and then when the sprite arrives there you can set the old position to 0 again. Some instance variables can be used for that.

  • dropbox.com/s/ek8cv68m874mq5j/DoNOTargetANonFlyZone.capx

    Yep, something like this was pretty much exactly what I was thinking, thanks for taking the time to put it into practice. My issue with it is that there seems to be a lot of checking going on and creating unnecessary instances.

    You could also use an array t do this and just store the uid of the object in a grid space (beware one object will have a uid of 0).

    I totally forgot about arrays. This actually sounds like it could be really efficient and might solve all my issues. Cheers for that.

    Thanks, I'm going to go away and have a bit of a play with this.

  • Right, so this is working well, except I have an issue.

    The array is checking for the Sprites UID and changing the array as necessary but, if there's more than one instance of the sprite it is not making multiple array changes.

    So I can have 5 of the same sprites on the screen, move them around and watch the array changing accordingly, but it's only changing for the first instance of the sprite. The rest are ignored.

    Any suggestions?

    Cheers

  • Right, so this is working well, except I have an issue.

    The array is checking for the Sprites UID and changing the array as necessary but, if there's more than one instance of the sprite it is not making multiple array changes.

    So I can have 5 of the same sprites on the screen, move them around and watch the array changing accordingly, but it's only changing for the first instance of the sprite. The rest are ignored.

    Any suggestions?

    Cheers

    Instead of using UID, why don't you use instance variable?

  • I don't think it's UID that's causing the issue.

    I can set value to 1 in the event for example, and it's still only going to change the array for the first instance in the layout.

  • How about using Sprite on created condition then?

  • yeah, tried it. Set it up so that every second a new sprite spawned randomly in the layout, it still didn't update the array except for the first instance.

  • If anyone's having this issue in the future, all it needed was:

    system > for each SPRITE: ARRAY set value ((SPRITE.x / 32) , (SPRITE.Y / 32)) to SPRITE.UID

    Seems to work,

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)