I'm working on a new game and I faced a problem (making the edges of the screen act like walls !)
after some search I found this piece of code
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
but the problem is that only the bottom and the top of the screen are working as edges while the right and the left edges aren't working (when I throw a ball to the left it goes for a while -of the screen- then hit the edge and return !)
Try this code:
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
and make sure you read over the SpriteKit Programming Guide (Listing 6-1 answers your question).
You have to subclass your GameScene with the SKPhysicsContactDelegate in order to have collisions exists in your Scene
class GameScene: SKScene, SKPhysicsContactDelegate {
physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)
physicsWorld.contactDelegate = self
}
This question has already been asked and answered here: How to set contactDelegate for physicsWorld in SpriteKit?
Check "scaleMode" of your scene.
Seems it is "AspectFill" and part of your scene simply is out of view.
If so - please try "AspectFit" value.
Docs with explanation: https://developer.apple.com/reference/spritekit/skscenescalemode
Related
tl;dr I'm trying to animate an SKScene on a plane in ARKit (i.e. a table). I can get the SKScene to appear by texturing an SCNPlane with it, but it does not animate. How can I get the animations to work?
Hi,
I'm trying to make an ARKit game which is essentially just a 2D game rendered on a plane anchored in the 3D world. I have the game as an SKScene object. Usually when rendering an SKScene in ARKit I'll create an SCNPlane and set the material to be an SCNMaterial with the SKScene diffused. This is what my current code looks like (in my renderer(_:didAdd:for:):
guard let scene = SKScene(fileNamed: "GameScene") else { return }
let scnMaterial = SCNMaterial()
scnMaterial.diffuse.contents = scene
let plane = SCNPlane(width: 0.8, height: 0.6)
plane.firstMaterial = scnMaterial
let planeNode = SCNNode(geometry: plane)
This renders the SKScene fine, but the update(_:) function is never called. After some research, I found out that when diffusing an SKScene onto an SCNMaterial, it pauses the scene. So, I added self.isPaused = false to the sceneDidLoad() of the SKScene. This gets the update(_:) function to run, but the texture on the SCNPlane is never updated, so the SKScene maintains its starting look. When the SKScene is run on its own in a UIViewController it works fine.
Does anyone know how I can get an animated SKScene to animate on an SCNPlane? At the end of the day, I just want an SKScene to animate on a plane (i.e. a table) in ARKit, so any alternative methods would work.
A Scenekit view runs its own rendering loop
and it does not update/render those node who are not moving by actions or physics movement.
Scenekit automatically decides when to update/render the nodes and when to not.
Try to apply continuous SCNAction or CAAnimation to your SCNPlane node with some movement, and it the diffuse property animation should work.
I've created a subclass:
class EnemySprite: SKSpriteNode
and added an enemy in my game scene using this code:
let enemy = EnemySprite(imageNamed:"enemy.png")
self.addChild(enemy)
Now when I shoot on the enemy I have the code:
enemy.removeFromParent()
The enemy is not seen on the screen, but the _enemiesSpritesArray.count remains the same. Also, when I shoot to the area where the enemy was, bullets stop there as if the sprite is still in the same spot.
I've tried to add:
override func removeFromParent() {
super.removeFromParent()
}
but still the same.
How can I remove the sprite completely?
You should remove the instance from the array as well.
if let index = enemiesSpritesArray.index(of: enemy) {
enemiesSpritesArray.remove(at: index)
}
This is a pretty basic question (Im new with swift and spritekit).
So anyway Im adding a particle emitter to a spritenode(call it ball) and adding the ball to my scene. This ball is on top of another spritenode that represents the background. When I run the app, the ball appears fine but the particle emitter doesn't show. The emitter shows fine when I remove the background, but not when I add the background. I will post a code example...
//Background
let background = SKSpriteNode(imageNamed:"Background")
background.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
background.zPosition = 0
self.addChild(background)
//Ball
let ball = SKSpriteNode(imageNamed: "ball")
ball.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
ball.zPosition = 1
ball.physicsBody = SKPhysicsBody(rectangleOfSize: ball.frame.size)
ball.physicsBody?.usesPreciseCollisionDetection = true
//Emitter
let emitter = SKEmitterNode(fileNamed: "emitter")
emitter.targetNode = self
ball.addChild(emitter)
self.addChild(ball)
Like I said, this seems to be a pretty basic question. I just don't know what Im doing wrong. Just to reiterate, when I run this, the emitter doesn't show. But if I take away the background, the emitter shows.
Thanks For the help :)
Simple answer - you just need to set your emitter's zPosition to be higher than the background's (but less than the ball). zPosition determines the order in which things are rendered, and the higher the number the later it is rendered (thus putting it on top).
It's also possible that your emitter nodes and your background are the same color so it appears as though it isn't there.
So I tried changing the zPosition of emitter and it didn't change anything. But when I changed the zPosition of the background to -1 the emitter showed. I wish I knew why this works haha. But thanks for the suggestions :)
I had the same thing happen but when you said it doesn't happen when you comment out the background, I remembered that there is a command in GameViewController that you have to set false.
skView.ignoresSiblingOrder = false
I am trying to add two SKSpriteNodes with their respective textures in swift, however the "Blade" does not show up on screen during the simulation. I am having no trouble getting the "Handle" to appear though. So my question is, what is the proper way to add a child of a child of self in swift so that everything works as intended?
var Handle = SKSpriteNode(imageNamed: "Handle.png")
var Blade = SKSpriteNode(imageNamed: "Blade.png")
override func didMoveToView(view: SKView) {
Handle.position = CGPointMake(self.size.width / 2, self.size.height / 14)
Blade.position = CGPointMake(Handle.position.x, Handle.position.y + 124)
self.addChild(Handle)
Handle.addChild(Blade)
}
This should get you close to where you expected it.
Blade.position = CGPointMake(0, 124)
Keep in mind when you add a sprite to another sprite the position is the position "within" that sprite. If you don't change the anchor that starts at the center of its parent. So you were starting in the center of Handle and adding half the width of the scene. Because Handle was already centered in the scene blade was off the scene.
Hopefully that makes sense and is helpful.
Also as lchamp mentioned you should lowerCamelCase
var Blade = SKSpriteNode(imageNamed: "Blade.png")
This will help you in the future identifying Classes vs Variables.
I'm working on a project in swift and I am able to make a sprite. I am trying to make a sprite at a number of different locations. As a test I replaced the code in the game scene to be:
class GameScene: SKScene {
override func didMoveToView(view: SKView){
let wall = SKSpriteNode(imageNamed: "Wall")
wall.position = CGPoint(x: 289, y: 0)
}
}
What I do not understand is this code makes a sprite in the lower left corner. As expected in the y direction only half of the sprite shows, but the x direction seems completely off. If I try to set the x value to any number below 289 it will not appear. Is the 0,0 point really 289,0 or am I missing something? I am programming for iphone 6 if that makes a difference.
Thank you!
Your scene it is not necessarily the same size of your view. You can check the size of your scene as follow:
view.scene!.frame.size
view.scene!.frame.width
view.scene!.frame.height
view.scene!.frame.midX
view.scene!.frame.midY