I am trying to make an auto scroller game. I have my Character and my ground as two separate nodes. My problem is that I don't if I should make the character or my ground move indefinitely, and how.
I did try moving my player indefinitely but I don't think I am doing it right.
let move = SKAction.repeatForever(SKAction.moveTo(x: player.position.x + 10, duration: 1))
player.run(move)
For the moment the player kinda trips on the ground. I am completely lost, I hope someone has done this before and can give me the answer. Thank You Very Much
ok found the answer myself
I should have tried this before
anyway what I did Is make my ground run the move action
let move = SKAction.repeatForever(SKAction.moveBy(x: -200, y: 0, duration: 1))
GroundNode.run(move)
Related
I wanted to do a simple asteroids games where the asteroids go from far to bypass you (z>0) in SceneKit.
let moveAction = SCNAction.move(to: SCNVector3(0, -10, 10), duration: 2)
rockNode.runAction(moveAction)
Says I have a spaceship in Z axis 0, even though I can visually see the asteroids pass through the spaceship, the collision detection does not occurred. The collision only happened if the end point of the moveAction ends in Z axis 0 and in the same location as the spaceship.
Does detection only occurred after the moveAction ended (thus will not detect collision)? If yes, what solution do I have in detecting the collision during the asteroids movement?
did you set the isDynamic to true on both of your objects? and they both need to have different categoryBitmasks otherwise SceneKit will treat them as the same objects (can't comment don't have 50 rep yet) if not then do so collision should happen even when moving an object programmatically
Make the physics body as: kinematic. So it can detect collision even during SCNAction.
eg:
rockNode?.type = .kinematic
Or you can set it from Physics Inspector
Keep coding....... :)
I'm developing a small game in Swift 3 with SpriteKit and I want to move the enemies to the direction of the character, but at all times the enemies stop when they arrive at the character's initial position.
I'm doing this:
enemigo.name = "enemigo"
enemigo.position = CGPoint(x: 280, y: 100)
enemigo.xScale = 1/1
enemigo.yScale = 1/15
addChild(enemigo)
let movement1 = CGVector(
dx: (enemigo.position.x - personaje.position.x)*10,
dy: (enemigo.position.y - personaje.position.y)*10
)
let actionTransaction = SKAction.move(by: movement1, duration: 20)
enemigo.run(actionTransaction)
How should I move the enemies to a specific direction without stopping at the initial position of the character?
You've done all the hard work figuring out the vector of direction.
Now you can repeat this moveBy action as often as you like, and the enemy will keep moving in the same direction, further and further, because move(by: CGVector) is relative, not absolute:
let actionTransaction = SKAction.move(by: movement1, duration: 20)
So all you need do is run this forever with a key, so you can then seek it out from anywhere, and stop it whenever you like.
run(SKAction.repeatForever(actionTransaction), withKey: "movingEnemy")
Alternatively, you could consider using GameplayKit together with SpriteKit. GameplayKit provides standard implementations of common algorithms for games and can be used together with SpriteKit.
Unfortunately I'm not too familiar with it, so I can't give you code. I would suggest having a look at Apple's GameplayKit programming guide. There are functions available for setting a goal of an agent (e.g. an enemy) to move toward a specific location, avoid obstacles, intercept another agent, or flee from an agent, etc.
So while your player moves, some enemies could be programmed to try and catch the player, while other enemies could try to run away from the player. Other enemies could be made to wander around randomly, etc.
So in a nutshell, GameplayKit can add quite powerful functionality to a SpriteKit game. This could mean spending a bit more time upfront thinking about the architecture of your game, but in the end it could be worth it if you will also use the other functionalities of GameplayKit.
What I'm trying to do is moving a sprite in a random direction or a random point and have it continue moving - with the affects of physics. I tried moving a sprite to a random point and although it worked, it just stopped if the random point was in the middle of the screen. I'm just hoping for the basics so any code/help from someone would be helpful. Also if you think theres a post already on this, can you list the hyperlink? I spent some time researching and I couldn't figure it out. Thanks in advance!
See SKPhysicsBody and methods like applyImpulse.
In short, you create and configure an SKPhysicsBody; assign it to the sprite; and then apply force vectors to the body. Procedural example:
let sprite = SKShapeNode(circleOfRadius: 10)
sprite.physicsBody = SKPhysicsBody(circleOfRadius: 10)
sprite.physicsBody.friction = 0.2
sprite.physicsBody.restitution = 0.75
sprite.physicsBody.mass = 0.5
sprite.physicsBody.applyImpulse(CGVector(1, 1))
Much of this you can configure declaratively, rather than procedurally, with the SpriteKit scene editor in Xcode.
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.
If I'm making a game in SpriteKit that has a large "world", and I need the user to have the option of zooming in and out of the SKScene, how would I go about this? Or, to make things simpler, in the didMoveToView function, how can I present more of the world to the user's device's screen (without using world.runAction(SKAction.scaleTo(0.5)) or something)?
There's a SKCameraNode that's built specifically for this. The SKCameraNode defines the viewport into your scene. You create a camera node and assign it to the camera property of your scene.
let cameraNode = SKCameraNode()
cameraNode.position = CGPoint(x: scene.size.width / 2, scene.size.height / 2)
scene.addChild(cameraNode)
scene.camera = cameraNode
You can then create actions and run those actions on the camera. So to zoom in on the scene, you'd do this.
let zoomInAction = SKAction.scale(to: 0.5, duration: 1)
cameraNode.run(zoomInAction)
The cameraNode basically is a square node in the scene, that I think takes the proportions of the view by default? Cuz there's no size initializer. So when you make it smaller, the scene looks like it gets zoomed. To zoom out you'd make an action that increases the scale. Basically imagine a rectangle on your entire scene, and whatever is in the cameraNode's rectangle directly shows on your iPhone screen. You can also add moveTo actions and sequence actions and set timingModes on the actions same as if it were your normal spriteNode.
Here's the WWDC where the apple guy shows what I've just said. CameraNode bit is around 3 mins before the end.
https://developer.apple.com/videos/play/wwdc2015-604/
So, the best solution I could could find goes something like this. In the didMoveToView function, create an SKSpriteNode called World and make it whatever size you want your world to be. Then, write world.setScale(0.5) if you want a 50% zoom-out. However, if you have a player node that needs to always be centered in the screen, you'll need to add the following to your update function.
override func update(currentTime: CFTimeInterval) {
world.position.x = -player.position.x * (0.5)
world.position.y = -player.position.y * (0.5)
}