I want k to follow multiple paths. I want it to finish p1 and then run p2. After it finishes p2, i want it to follow p3. How can I do this? Is there a handler that detects if the sprite finishes the path?
//k is my SKSpritenode
func followPath(path:CGPath,sprite:SKSpriteNode,speed:CGFloat){
sprite.runAction(SKAction.followPath(path, speed: speed))
}
followPath(p1, sprite: k, speed: 90)
followPath(p2, sprite: k, speed: 90)
followPath(p3, sprite: k, speed: 90)
You can add a list of actions into a sequence and then this sequence as one long actions itself.
Apologies, as I use Xamarin and C#, so my calls will look slightly different, but in essence, here's a simple example:
var rect = new CGRect(0, 0, 100, 100);
var path = new CGPath();
path.AddRect(rect);
var moveOneDirection = SKAction.FollowPath(path, false, true, 5.0f);
var sequence = SKAction.Sequence(moveOneDirection, moveOneDirection.ReversedAction);
sprite.RunAction(SKAction.RepeatAction(sequence, 3));
This will make your sprite move along a rectangle, then back, and do this 3 times. Obviously, you can add many more paths!
Related
I've been trying to code this for days now, without success.
My game is a 2D endless runner. My hero is locked onto a specific point on the X-axis. The obstacles are randomly spawned (height and distance) buildings.
I'd like to add a chasing enemy to the game. Currently for visuals only.
chasingCopNode = CopSprite.newInstance(position: CGPoint(x: -90, y: 0))
let follow = SKAction.moveTo(x: thiefNode.position.x - 50, duration: 5)
let wait = SKAction.wait(forDuration: 2)
let fallBehind = SKAction.moveTo(x: -90, duration: 4)
let chasingSequence = SKAction.sequence([follow, wait, fallBehind])
chasingCopNode.run(chasingSequence)
chasing = true
self.addChild(chasingCopNode)
I created this to move tha chasing sprite along the X-axis.
In my update function, I simply update the Y position of the enemy with the hero's Y position.
That is working, but not quite the thing I need. Since the Y positions are the same, the enemy sprite is flying sometimes (because there is no building under it).
I couldn't come up with any working ideas for the movement on the Y-axis.
I was thinking maybe add a function that calculates the needed Y impulse for the enemy to land on the next building, but I was not able to do that correctly.
thank you for your help!
I am fairly new to swift and Sprite Kit. I am trying create a simple game using SKSpriteNodes. My game needs to keep track the sequence of the "clicked" nodes as it needs to be processed based on its sequence. I am thinking of creating a list, as the nodes are clicked it will be added to the list. Is this the easiest way? I am thinking that it may consume more memory. My nodes are of the same names. Below is the method I used in adding the nodes in my scene. I need to know the sequence of colored balls clicked.
for x in listNodes{
var ballNode = SKSpriteNode(imageNamed: String(color))
ballNode.name = "ball"
var point: CGPoint = CGPointMake(0,0)
var done: Bool = false
let randomX = randomRange(CGRectGetMinX(self.frame), max: CGRectGetMaxX(self.frame)-(ballNode.size.width))
let randomY = randomRange(CGRectGetMinY(self.frame) + self.border.size.height, max: CGRectGetMaxY(self.frame)-ballNode.size.height)
point = CGPointMake(randomX, randomY)
ballNode.anchorPoint = CGPointMake(0,0)
ballNode.position = point
self.addChild(ballNode)
}
Hey I'm trying to get the point of collision and then create a joint at that point for two nodes. I'm not sure what my results mean or how to get what I want.
I don't have access to the contact points which I see in other posts. The CCContactSet from the collision only gives me number of points and normal.
I output the normal during collision begin and its (1.0, -0.0) for left wall, (-0.0, 1.0) for bottom wall, (-1.0, 0.0) for right wall, (-0.0, -1.0) for top wall. I don't understand them basically. I know they are only referring to the second hullPiece though because no matter how I rotate or position the booster during the collision, the results stay the same. They only change if I rotate the hullPiece.
So how do I get the contact points to create the joint? Am I supposed to use the normal for that, and if so how?
newSprite = CCSprite(imageNamed: "Booster.png")
newSprite.position = CGPoint(x: 200, y: 200)
newSprite.scale = 4.0
let spritePhysics = CCPhysicsBody(rect: newSprite.textureRect, cornerRadius: 0)
spritePhysics.collisionType = "booster"
spritePhysics.sensor = true
newSprite.physicsBody = spritePhysics
editorPhysics.addChild(newSprite)
newSprite2 = CCSprite(imageNamed: "HullPiece.png")
newSprite2.position = CGPoint(x: 200, y: 200)
newSprite2.scale = 4.0
let spritePhysics2 = CCPhysicsBody(rect: newSprite2.textureRect, cornerRadius: 0)
spritePhysics2.collisionType = "hull"
spritePhysics2.sensor = true
newSprite2.physicsBody = spritePhysics2
editorPhysics.addChild(newSprite2)
func ccPhysicsCollisionBegin(pair: CCPhysicsCollisionPair!, booster: CCNode!, hull: CCNode!) -> ObjCBool
{
NSLog("contact point\(pair.contacts.count) \(pair.contacts.normal)")
return true
}
You get access to the contact points through the contacts property of the CCPhysicsCollisionPair.
Here's what the contacts struct looks like:
typedef struct CCContactSet {
/// The number of contact points in the set.
/// The count will always be 1 or 2.
int count;
/// The normal of the contact points.
CGPoint normal;
/// The array of contact points.
struct {
/// The absolute position of the contact on the surface of each shape.
CGPoint pointA, pointB;
/// Penetration distance of the two shapes.
/// The value will always be negative.
CGFloat distance;
} points[2];
} CCContactSet;
Through the points array you can access the exact collision position for each involved shape.
I've created a tiled map composed of multiple sprite nodes that are 367x367. I create this map like so:
for var i = 0; i < Int(multiplier); i++ {
for var j = 0; j < Int(multiplier); j++ {
// Positive
var map = SKSpriteNode(imageNamed: "tiledBackground.png")
var x = CGFloat(i) * map.size.height
var y = CGFloat(j) * map.size.height
map.position = CGPointMake(x, y)
self.addChild(map)
}
}
In the above example, the multiplier is 27 and the map size is 10,000x10,000.
This creates the map as expected, however I want this map to have boundaries that the player can't leave. I know how to create the boundaries, but I'm not sure what values to initialize the physics body with.
I've tried this: SKPhysicsBody(rectangleOfSize: map.mapSize) however that produced very erroneous results.
I also tried this: SKPhysicsBody(edgeLoopFromRect: CGRectMake(0, 0, map.mapSize.width, map.mapSize.height)) which built a physics body like it should (I have showPhysics = TRUE), however the physics body seemed to move with the player (I have the player moving and am centering the map on the player). You can see what I mean here: http://gyazo.com/675477d5dd86984b393b10024341188a (It's a bit hard to see, but that green line is the boundary for the physics body. When the tiled map ends (And where it turns grey), the physics body should stop as that's where the player shouldn't be allowed to move any more).
Just leave a comment if you need any more code (I believe I included anything that is relevant).
After messing around with a bit of my code I found a fix was to just add the physicsBody to my map instead of the scene. A rather easy fix, so I'm surprised I didn't think of it sooner.
With this in mind, I've answered my own question and no longer need help.
I am building my first iPhone game using Xcode, SpriteKit and Swift. I am new to these technologies but I am familiar with general programming concepts.
Here is what I am trying to do in English. I want circles to randomly appear on the screen and then begin to expand in size. However, I do not want a circle to appear in a location where a circle currently exists. I am having trouble determining each circle's position.
Inside GameScene.swift I have the following code inside the didMoveToView:
runAction(SKAction.repeatActionForever(
SKAction.sequence([
SKAction.runBlock(addCircle), SKAction.waitForDuration(3, withRange: 2)]
)))
The piece of code above calls my "addCircle" method:
func addCircle() {
// Create sprite.
let circle = SKSpriteNode(imageNamed: "grad640x640_circle")
circle.name = "circle"
circle.xScale = 0.1
circle.yScale = 0.1
// Determine where to position the circle.
let posX = random(min: 50, max: 270)
let posY = random(min: 50, max: 518)
// ***Check to see if position is currently occupied by another circle here.
circle.position = CGPoint(x: posX, y: posY)
// Add circle to the scene.
addChild(circle)
// Expand the circle.
let expand = SKAction.scaleBy(2, duration: 0.5)
circle.runAction(expand)
}
The random function above just chooses a random number within the given range. How can I check to see if my random functions are generating a location that is currently occupied by another circle?
I was thinking of using a do..while loop to randomly generate a set of x and y coordinates and then check to see if a circle is at that location but I cannot find how to check for that condition. Any help would be greatly appreciated.
There are a few methods which can help you in this regard:
(BOOL) intersectsNode: (SKNode*)node, available with SKNode, and
CGRectContainsPoint() as well as the CGRectContainsRect() methods.
For instance the loop to check for intersection can look as follows:
var point: CGPoint
var exit:Bool = false
while (!exit) {
let posX = random(min: 50, max: 270)
let posY = random(min: 50, max: 518)
point = CGPoint(x: posX, y: posY)
var pointFound: Bool = true
self.enumerateChildNodesWithName("circle", usingBlock: {
node, stop in
let sprite:SKSpriteNode = node as SKSpriteNode
if (CGRectContainsPoint(sprite.frame, point))
{
pointFound = false
stop.memory = true
}
})
if (pointFound)
{
exit = true
}
}
//point contains CGPoint where no other circle exists
//Declare new circle at point