Update: Even Apple's template code won't display nodes in the simulator.
The simplest of code, such as creating a red square node will not work (this project worked until today, and I haven't changed it). For example:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
let myNode = SKSpriteNode(color: UIColor.red, size: CGSize(width: 300, height: 300))
myNode.position = CGPoint(x: 0, y: 0)
self.addChild(myNode)
}
}
Or more complicated code such as:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
let myNode = SKSpriteNode(imageNamed: "Spaceship.png")
override func didMove(to view: SKView) {
myNode.position = CGPoint(x: 0, y: 0)
myNode.xScale = 0.5
myNode.yScale = 0.5
let action = SKAction.rotate(byAngle: 2, duration: TimeInterval(2))
myNode.run(SKAction.repeatForever(action))
self.addChild(myNode)
}
}
For some reason either changing the project name in general, or changing it to not include a dash fixed it. I thought I would post this in case anyone else has this problem.
Related
I can't get SKCropNode to cooperate. I've played with this for HOURS I've copied verbatim hackingwithswifts guide and the only difference being my image and it will not work. So then I dumbed it down for myself with the code below and it still doesn't work.
I've tried the guide directly from hacking with swift and it didn't work. I copied code directly from apple documentation that also didn't work. I've wasted wayyyy too much time on the simple task of cropping an image.
import SpriteKit
import GameplayKit
import UIKit
class ProcGenPlanet: SKScene{
//Background
//let background = SKSpriteNode()
var square = SKSpriteNode()
override func didMove(to view: SKView) {
square = SKSpriteNode(imageNamed: "redSquare")
square.size = CGSize(width: 1000, height: 1000)
square.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
let mask = SKSpriteNode(color: SKColor.black, size: CGSize(width: 100, height: 100))
let cropNode = SKCropNode()
cropNode.maskNode = mask
cropNode.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
cropNode.addChild(square)
}
}
I am creating 1000x1000 red square. The whole image is red. Then I am trying to crop it to 100x100 with the following code but instead NOTHING shows up.
can anyone explain how to add a node to the gameScene please.
I subclassed my Boss class but i dont know how i can display my Boss1 on the GameScene
class Boss: GameScene {
var gameScene : GameScene!
var Boss1 = SKSpriteNode(imageNamed: "boss1")
override func didMove(to view: SKView) {
Boss1.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
Boss1.zPosition = 2
self.gameScene.addChild(Boss1)
}
}
im using swift 4 and xcode 9
You don't generally subclass the scene for instances such as this. More likely you are meaning to make boss a subclass of SKSpriteNode and adding it to your scene. While there is probably dozens of ways that you could subclass this, this is just 1 way.
Also worth noting that it is not generally acceptable practice to make your variable names capitalized, classes yes, variables no.
class Boss: SKSpriteNode {
init() {
let texture = SKTetxure(imageNamed: "boss1")
super.init(texture: texture , color: .clear, size: texture.size())
zPosition = 2
//any other setup such as zRotation coloring, additional layers, health etc.
}
}
...meanwhile back in GameScene
class GameScene: SKScene {
let boss1: Boss!
override func didMove(to view: SKView) {
boss1 = Boss()
boss1.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
self.gameScene.addChild(boss1)
}
}
in GameScene you create an instance of the new class and position it and add it in the GameScene.
edit
the init function has a short cut in swift.
Boss()
is the same as
Boss.init()
you can also add custom parameters to your init in order to further clarify or add more features to your class. for example...
class Boss: SKSpriteNode {
private var health: Int = 0
init(type: Int, health: Int, scale: CGFloat) {
let texture: SKTetxure!
if type == 1 {
texture = SKTetxure(imageNamed: "boss1")
}
else {
texture = SKTetxure(imageNamed: "boss2")
}
super.init(texture: texture , color: .clear, size: texture.size())
self.health = health
self.setScale(scale)
zPosition = 2
//any other setup such as zRotation coloring, additional layers, health etc.
}
}
I'm trying to make a class from this node so I can make various objects from it, but Xcode keeps saying "Expected Declaration". How can I make a class from my node? Here is the code that's giving me an error:
P.S. I am relatively new to StackOverflow, so if my question needs more details please let me know instead of putting it on hold. Thanks!
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMove(to view: SKView) {
class nodeClass{
let platform = SKSpriteNode(color: UIColor.yellow, size: CGSize(width: 400, height: 60))
platform.xScale = 0.8
platform.yScale = 0.8
platform.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: platform.size.width, height: platform.size.width / 6))
platform.position = CGPoint(x: 150, y: -100)
platform.physicsBody?.categoryBitMask = 1
platform.physicsBody?.collisionBitMask = 0
platform.physicsBody?.isDynamic = false
platform.physicsBody?.affectedByGravity = false
self.addChild(platform)
}
}
}
You should (ideally) declare and define your class outside of a function.
For lack of a better term, at the 'root' level of your file containing code.
For personal clarity, most folks, most of the time, create a new file and use that to hold their declaration and definition of all their classes can do. This isn't strictly necessary in Swift, but it's a helpful clarity technique for when you're starting out. As I am.
Next problem: nodeClass isn't, the way you've written it, subclassing anything. It's a 'standalone' type. By virtue of it not having anything after a colon stating what it's subclassing, it's an entirely new type.
Right above, you can see GameScene is a subclass of SKScene, because it's doing this. Any type names after the one being subclassed are Protocols GameScene is agreeing to conform to.
Ad #Confused just said, you should avoid declaring a class inside a method.
Here's a possible solution
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMove(to view: SKView) {
let platform = Platform(size: CGSize(width: 400, height: 60))
platform.xScale = 0.8
platform.yScale = 0.8
platform.position = CGPoint(x: 150, y: -100)
self.addChild(platform)
}
}
class Platform: SKSpriteNode {
init(size: CGSize) {
super.init(texture: nil, color: .yellow, size: size)
let physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: size.width, height: size.width / 6)) // Are you sure about this??
physicsBody.categoryBitMask = 1
physicsBody.collisionBitMask = 0
physicsBody.isDynamic = false
physicsBody.affectedByGravity = false
self.physicsBody = physicsBody
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
When the view is presented, I would like the image named "Player" (set) which is in my images.xcassets to show on the scene.
Currently the scene just loads up blue. Not sure why, as even when adding a color to change the image color did nothing.
import SpriteKit
class CharacterScene: SKScene {
var Circle = SKSpriteNode(imageNamed: "Player")
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.blackColor()
Circle.size = CGSize(width: 40, height: 40)
Circle.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
Circle.color = SKColor.brownColor()
self.addChild(Circle)
}
}
You need to initialize the size of CharacterScene before presenting it on the screen. Here you go:
self.scene!.view!.presentScene(CharacterScene(size: self.scene!.size), transition: SKTransition.pushWithDirection(SKTransitionDirection.Up, duration: 0.3))
How do you make a sprite rock back and forth constantly like a boat?
Heres the code i wrote:
import UIKit
import SpriteKit
let boat = SKSpriteNode(imageNamed: "boat_floor")
var rotationVal = CGFloat(-1)
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
backgroundColor = UIColor.whiteColor()
boat.size = CGSize(width: self.frame.size.width, height: self.frame.size.width)
boat.position = CGPoint(x: self.frame.size.width/2, y: 0)
boat.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "boat_floor"), size: boat.size)
boat.physicsBody?.dynamic = false
boat.alpha = 1
self.addChild(boat)
ChangeAngle()
NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: Selector("ChangeAngle"), userInfo: nil, repeats: true)
}
func ChangeAngle(){
let action = SKAction.rotateByAngle(rotationVal, duration:30)
if rotationVal < 0 {
rotationVal = CGFloat(M_PI)
boat.runAction(action)
}
else if rotationVal > 0 {
rotationVal = -CGFloat(M_PI)
boat.runAction(action)
}
print(rotationVal)
}
}
If I understand you correctly, you can do it like this (just copy&paste the code to see how it works):
import UIKit
import SpriteKit
let boat = SKSpriteNode(color: SKColor.greenColor(), size:CGSize(width: 200, height: 80))
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
backgroundColor = UIColor.whiteColor()
boat.position = CGPoint(x: self.frame.size.width/2, y: 100)
boat.alpha = 1
self.addChild(boat)
let rotate = SKAction.rotateByAngle(-0.6, duration:4)
let sequence = SKAction.repeatActionForever(SKAction.sequence([rotate, rotate.reversedAction()]))
let complete = SKAction.sequence([SKAction.rotateByAngle(0.3, duration:2), sequence])
boat.runAction(complete, withKey:"someKey")
}
}
Using NSTimer is generally bad idea in SpriteKit because it don't respect node's, scene's or view's paused state.