In my game I want to call a function every few seconds that creates random objects from an array. Currently I'm moving this objects by SKAction like this:
func createRandmoObject() {
let random = arc4random_uniform(4)
randomObject = randomObjects[random]
randomObject.runAction(SKAction.moveTo(CGPoint(x: randomObject.position.x, y: 0 - randomObject.size.height), duration: 3))
addChild(randomObject)
}
and when the object hits the player it gets removed, then the function gets called again. The problem with this method is I found that the motion of the object isn't always smooth, when the framerate drops for some reason, stutterness occurs. Now I know how to calculate delta time in the update method, but I'm not sure how to apply it to an object when that object keeps changing and not always on the screen, and there are some other objects like it(let's think of them as enemies, and there are another function that creates another enemy) So how can I make those random objects move according to deltatime instead of SKAction?
While you can use SKAction in spritekit projects, if your game is based on physics, you should utilize the update method for all of your sprites movements. SKactions are ok for simple games but if your game involves collisions and random movements, update method is the choice to go for.
Related
I use cannon.js to simulate firing bullets. The bullet passed through the object without collision. I know this is because the speed is too fast. The bullet passes through the object at the interval of two frames. Is there any way to avoid this situation
I am very new to Swift and currently coding a minigolf game.
However, the player can hit the ball n times.
How do I make a simple view which should show how many hits the player has left?
I think that you want something like this:
First of all, i recommend you to create a function to call when the game is restarted, there you can reset the scene, reset the player moves, etc...
You may do this like:
func restart(){
//Everything you need to restart the game
}
To call it later you just have to:
restart()
Ok, let's go to what you asked now:
declare a Int variable that contains the number of moves that the player has:
var playerMoves = 10 //Whatever number you want
Ok, you have a variable that contains the number of moves, now you have to show this on your scene, to do this, create an SKLabelNode:
let moveLabel = SKLabelNode()
Now, set the label text to be equal your playerMoves, set the position, the zPosition, the font, whatever you want:
moveLabel.text = "\(playerMoves)" //add this line to restart function that i mentioned and also set the variable playerMoves to "n" again.
moveLabel.position = ....
moveLabel.fontSize = ....
moveLabel.zPosition = ... //A number higher than any other zPosition
addChild(moveLabel) //Don't forget to add the label to scene!
Thats it! And now you have to update the playerMoves every time the player moves, to do this i'm assuming you are controlling somehow when the player moves (using update function, touches began, created a function, etc....)
so...when the player take one move:
playerMoves -= 1
moveLabel.text = "\(playerMoves)"
THATS IT!!! :) HOPE IT HELPS!
there are several ways to go about it. the most common way would be to overlay a spritekit scene over the scenekit scene. in the spritekit scene you can have a label element that you update
the code might look something like
let overlay = SKScene(fileNamed: "yourspritekitscene.sks")
yourScnView.overlaySKScene = menuOverlay
you can also assign a spritekit scene as a texture on a 3D object in your scene. or you can can make the numbers a texture you swap as you count down.
I am quite new to SpriteKit, coming from about 4 months playing around with HTML5. Using Mark Wihlberg's HTML5 youtube game tutorials, my programs always constantly updated a player or object's position.
Example if it helps:
function run() {
var loop = function() {
window.requestAnimationFrame(loop, canvas);
update(); //here I would add maybe 3 to a player's x pos and redraw in draw()
draw();
}
window.requestAnimationFrame(loop, canvas);
}
But looking at various SpriteKit tutorials online, many use SKAction to move nodes across the screen.
My question is whether constantly updating a node's position in SpriteKit is unorthodox, or frowned upon, and I should get used to using actions, and why?
No it isn't frowned upon, and it's good to know how to do these things manually. If it's fairly straightforward, regular movement, then SKAction is fine. For more complicated stuff (and SKActions can actually get complicated, with sprites following paths and bezier curves etc), use the Update() function, iterate over your sprites (using enumerateChildNodesWithName or similar) and move them as necessary.
You can combine the 2 - move the sprites in Update() and animate them with an SKAction, or vice-versa.
Bear in mind that you don't call Update(); it is called automatically by the game engine 60 times a second. It gets passed a time, so you can work out exactly how long it has been since Update() was last called (not always 1/60s)
Im creating a game that where you tap to start the player to make him jump, and then as he goes up, more and more objects generate for you to collect to gain points (think of doodle jump). I have it set up so this will happen, but instead of being given a boost by the object, he just floats up out of the scene. Id also like to know how to remove the object from the scene when the player touches it. Thanks in advance(:
Here is my code for making him gain velocity when he touches the object:
func bounceOff() {
player.physicsBody?.affectedByGravity = false
player.physicsBody?.applyImpulse(CGVectorMake(0, 10))
let advance = SKAction.moveByX(0, y: 10, duration: 5)
runAction(advance)
}
Your object goes off the screen because you cancel gravity. The impulse you apply pushes up, but there is no force pulling down. As to removing node from the scene. You can use node's removeFromParent method.
Okay I have some physics objects, and they are all nicely categorized, and my didBeginContact is properly fired, and does what it is supposed to do. The problem is this:
I have two categories of objects, say ball and paddle.... When the ball touches a paddle the ball should explode... simple enough.. The problem lies in that the ball could touch 2 paddles at the same time... So, more than one didBeginContact gets called, and as such more than 1 explosion happens (1 per paddle the ball contacted with).. So the problem I am trying to figure out is, how do I remove/ignore all subsequent contacts with paddles from being handled if the code has already handled a collision involving the original ball? Removing the SKSpriteNode from parent before starting the explosion does not nullify the other contacts, they still get handled... so how do I tell it.. HEY PHYSICS CONTACTS STUFF... that body is no longer in the picture... so just throw those contacts away and don't worry about them?
I suppose I could explicitly check that the parent still has the SKSpriteNode available in the contact code before doing the explosion etc, but that seems kludgy at best, though I suppose it would work... Is there another/better way to handle this? I have to believe there is.
The moment you get the contact, set the contactBitMask of the ball node's physicsBody as 0. I am assuming the node needs to be destroyed and does not need to be reused.
This should prevent multiple contacts from appearing for the same node.
If the above doesn't work, you can try the following methods:
Removing the node from parent within the contact delegate, and triggering the explosion animation subsequently.
Subclass SKSpriteNode or SKPhysicsBody for the ball nodes and add a property for eg. alreadyTouched. Then you can check and set the property from within the contact delegate.
If you have three physicsBodies (ball, paddle1 and paddle2) and ball is set to collide with paddles (but paddles do not collide with each other) and the ball collides with 2 paddles during the same update cycle, then the game engine will generate 2 separate SKPhysicsContact objects - ball & paddle1 and ball & paddle2.
didBegincontact (Swift2) or didBegin(contact:) (Swift 3) (dBC for brevity) will then be called twice during the same update() cycle i.e. there will be 2 calls to dBC between calls to update()- firstly for the SKPhysicsContact between ball & paddle1 and then for the contact between ball & paddle2. You can do ball.removeFromParent() during the first contact, and the ball will be removed from the node tree but this will not prevent the second call to dBC for the ball & paddle2 collision and you will likely perform the same actions against ball (exploding, removing the score etc).
The simplest thing to do is to create a subclass of SKSPriteNode for your ball (ballNode?) and add a single property isActive, initialised to true. This is very easy.
In dBC, when the ball hits the paddle, check its isActive property and if false, simply return. If it's true, perform the normal collision actions and then set ball.isActive to false. When dBC is called the second time, the check against isActive will prevent any duplicate actions.
You could also use the ball's userData (part of SKSpriteNode) to store the isActive values to prevent subclassing, if you'd prefer that.
There are other ways to handle this issue, but so far I've found this one to work and to be the simplest.