I am using GameplayKit to create paths around obstacles in a given map boundary (lets say a rectangle 1000x1000).
I know that you can make certain nodes avoid "obstacles" when pathfinding, which I am using quite nicely. What I am curious about however is such:
Is there a way to use this same logic and count anything not in the map boundary as an "obstacle"?
A work around would be to create 2 SKNodes and fit them together to create an inner "hole" which becomes 1000x1000, but I am trying to avoid unnecessary addition of nodes if there is a better way. Below I am showing what I could do.
Ideally I want to make the red and black area treated as an obstacle so that all paths remain inside the main square.
UPDATE:
I am using GameplayKit as I have already said, and the pathfinding algorithm can not count regions that are NOT included in a given physics body as an obstacle. It can only count obstacles to be closed polygons that lie within a region. Creating the 2 nodes as shown above works because the pathfinding will now not be able to create any points that lie outside the green rect.
Just have your game layered like this
Scene
SKNode topshape
SKNode bottomshape
SKNode innerbox <-- This is the size of your inner square
SKNode gamenodes <-- Place all inner nodes here
...
Then attach a SKPhysicsBody using an edge loop rectangle the size of innerbox, to the innerbox SKNode and make it a wall category, this will keep all your nodes inside, providing your nodes do not move at insane speeds breaking the engine.
You would be adding 1 additional node instead of 2 (Technically you could make bottomshape and topshape 1 node, making it 0 nodes added), but all processing would get done within the inner node, so not much overhead gets added.
Related
I am trying to figure out what is the best way to draw a line between two SKNodes in SpriteKit, nodes that move each frame. [Example sketch below... the red line is what I want to draw]
I can draw a line. At the moment I override the update call and every frame I detect the position of the two nodes (P1 and P2), and then simply draw a line [using an SKShapeNode and creating the path that goes from P1 to P2 then setting the shape node's path to it...].
It works and it performs well. However, that is handling two nodes, one line that visually connects them. What I am going to need is two draw multiple lines between multiple nodes. I feel like it'll be cumbersome to do so for N nodes to loop through each case every frame and remove and redraw lines.
I am wondering if there is a way to leverage physics body and joint to "add" a line between two nodes once and then have sprit kit handle the updates as the nodes move.
So, what is the best way to show lines between nodes that moves around every frame instead of having to loop through them each frame to redraw the line nodes as I get more nodes to handle?
I am currently working on a 2D endless runner, written in Swift3 and using Spritekit.
Short question:
Is there a way to only check for collisions on the right side of my character's rectangular physics body?
More info:
The platform on which the character runs is made of puzzle pieces and the user builds upon it as the game progresses. The character progresses left to right, in respect to the background (which goes right to left).
I want the character to automatically jump when he collides with a piece on his right side. However, any pieces that the player puts to the right of him (same Y value as the character) is of the same class as the pieces underneath him.
So the same code that checks for collision between the character and pieces to his right, and make him jump, will also make him jump as long as the game detects collision between the character and the pieces under him.
I have not been able to find another problem like mine, since usually others' characters are colliding with objects of different classes from their ground class.
Thanks!
P.S. I have tried to make my character a SKSpriteNode with two physics bodies, but I could not find any helpful documentation. If it helps any, my character also performs a looping running animation--though I can't imagine that would harm anything.
You could achieve that by detecting collisions with your rectangle and then deciding whether the collision was with the side of your interest or not. Here is a discussion about how to do that. Good luck!
Have you tried adding a non visible sub node (e.g. feetNode) to your character's sprite node and giving that sub node the physics body (class) for floor contact ?
Depending on the rest of your logic, it may allow you to use a different physics class for your character have more flexibility in collision detection.
In fact, you could probably use that approach with several sub nodes in your character's sprite node and have multiple collision behaviours for the character depending on what hits it.
Once you obtain the contact point of the 2 bodies that are colliding, determine which body is the one that is colliding by checking the categorymasks and then check its CGPoints x position. This x position can be compared to the other body's x position to know exactly which side it is colliding from.
if Body A's x position > Body B's x position, Body A is on the right and if not, its on the left.
As simple as that.
Hope this helps!
I am seeming to have difficulty keeping my sprite nodes inside a map boundary that I have set up in the following way:
I have an SKNode *enemy that moves around an SKScene by goals and behaviors courtesy of GameplayKit from iOS 9. Currently the node wanders, and avoids obstacles that are defined GKPolygonObstacle objects. I have my bitmask set up so that any obstacle is deemd category wall, which the node is told to collide with (AKA disallow passing through).
In my didBeginContact:(SKPhysicsContact *)contact I am handling these collisions. All is working exactly as planned and there are no issues when manually moving this enemy.
However, the problem begins when I have the enemy wander around the scene through an SKGoal *wanderGoal set up as
// Low --> 0.5 Lowest --> 0.25
enemy.wanderGoal = [GKGoal goalToWander:low];
[enemy.agent.behavior setWeight:lowest forGoal:enemy.wanderGoal];
// Add obstacles to avoid for each of the inner map nodes
// that act as impassible areas for the enemy to pass through.
NSArray *obstacles = [SKNode obstaclesFromNodePhysicsBodies:innerMapArray];
/** This goal does not change --> enemies will ALWAYS
avoid the obstacles in the level map. This should always
be set to the highest priority of the enemy goals
*/
enemy.avoidGoal = [GKGoal goalToAvoidObstacles:obstacles maxPredictionTime:10];
// Highest --> 250
[enemy.agent.behavior setWeight:highest forGoal:enemy.avoidGoal];
The enemy moves randomly as expected, and seems to avoid the obstacles most of the time...yet on the occasion the enemy does in fact pass through the map barrier. Let me expand on this:
The map barrier is essentially a rectangle, and I have set up 2 nodes that act as a shell that represent the left half and the right half of this shape. These nodes have a thickness of 100 points so they are not simply CGPath refs but rather shapes. They act as these two brackets act: [] (my halves are flush touching at the middle).
My question is such:
How can I prevent the enemy from passing through these obstacles with using either physics with the bitmask categories, or by the goal behavior? (Or both together)
I understand that while a GKGoal is a suggested behavior it does not guarantee this goal to be reached (but it can be ~95% sure it wont happen as Apple's AgentsCatalog shows). But, what I don't understand is why the enemy does not simply "slide" along the edge of the boundary as the goal tells it to (try to) "pass" through such boundary.
This "sliding" behavior does happen when I manually move the enemy around the scene, and as I attempt to move it passed a boundary deemed an obstacle, it slides towards the direction that I am having it move (just as any video game does that has map boundaries).
SO
If someone can help me prevent this from happening / explain how to approach preventing the enemy from ever passing through these (supposedly) "impassible" areas, I would be most appreciative.
FYI: If you are unclear with what I am describing / how I have created any objects, please ask and I will provide more info to help.
I need to force/specify the drawing order of all children within node A. I have SKView.ignoresSiblingOrder = NO. If I start setting zPosition on the sprites inside node A (inside update: of the scene), the drawing order would also affect globally so that the children inside node A draws on top of/behind other nodes that are not children of node A, and this messes things up. So I specifically need to adjust the drawing order of the children within node A. How? I can't rearrange the order of the sprite in the children array in update: now can I (performance hit...)?
Update: judging from the SpriteKit reference, for complex scenes we probably have no choice but to set zPosition for everything. I'll do that for now, see if it holds.
I hope you all can help with this. I'm working on app of a board game. I have hex shaped tiles which are called randomly and laid out at the start of the game. Each of these tiles has four sides with a value of 1 and the other two sides have values of 2 and 3.
Each tile is a SKSpriteNode with transparent rectangle Nodes on the edges. There are 5 different types of tiles and they need to be separate Sprites with child nodes because in addition to being randomly laid out they area also randomly rotated. So I need to know programmatically which tile edges are touching which edges of other tiles.
Like this:
https://app.box.com/s/nnym97st3xmrsx979zchowdq1qwsmpoo
(I tried to post an image of what I'm trying to accomplish, but apparently I don't have a high enough of a rating.) ;-)
For example: If a "2" is touching a "3", etc.
I first tried Collision detection, but of course that only works with dynamic, moving objects.
I tried an IF statement to compare if the other nodes were touching and then remembered that the coordinates where specific to the Parent Node, so that didn't work.
I then tried intersectsNode, but that seems to only work with nodes under the same parent.
I am currently working with convertPoint in order to get the coordinates to match the scene and thus be comparable. But I can't seem to get it work the way I need.
There must be something simple that I am not seeing. Any ideas?
Certainly not simple.
One solution would be to start all your shapes slightly spaced out from each other. Add invisible child nodes with physics bodies to all six sides and give each physics body an appropriate category based on their rating (1, 2 or 3).
When you start the game, move all the outer nodes into their proper position (sides touching) by using whatever movement method your prefer. This will give you contact messages as each hex side touches another. The contact messages will tell you what side number is touching its neighbor.
The exact coding of this idea depends on your current code, game play, etc...