Can't set image as background (SKScene) - sprite-kit

I have tried various different ways to do this and nothing works. Here's my code. If I change to a UIColor instead of using patternImage it works fine. I just want a static image as the background. I appreciate any advice I can get! Thanks!
override func viewDidLoad() {
super.viewDidLoad()
let scene = GameScene(size: view.bounds.size)
let skView = view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.ignoresSiblingOrder = true
scene.scaleMode = .resizeFill
scene.backgroundColor = UIColor(patternImage: UIImage(named: "IMG_6999")!)
skView.presentScene(scene)
}

You are setting background color, not an image.
In didMove(to view:) of GameScene.swift you need to create SpriteNode that will be contain your image. Then add this node to the scene.
For example:
import SpriteKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
let background = SKSpriteNode(imageNamed: "background")
background.zPosition = -1 //other nodes will be higher then background node
background.position = CGPoint(x: size.width/2, y: size.height/2)
addChild(background)
}
}

Related

Re-position scene to top of view

Apple's documentation states I can't change the position using the position getter/setter. I've tried the anchor point suggestion but still unable to move my scene's position in Scene Editor to the top. Does anyone have any ideas?
Implementation has been done via Scene Editor, currently the only code submitted to help scene present is below:
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Load 'GameScene.sks' as a GKScene. This provides gameplay related content
// including entities and graphs.
if let scene = GKScene(fileNamed: "GameScene") {
// Get the SKScene from the loaded GKScene
if let sceneNode = scene.rootNode as! GameScene? {
// Copy gameplay related content over to the scene
sceneNode.entities = scene.entities
sceneNode.graphs = scene.graphs
// Set the scale mode to scale to fit the window
sceneNode.scaleMode = .aspectFit
print(sceneNode.anchorPoint)
print(sceneNode.position)
// Present the scene
if let view = self.view as! SKView? {
view.presentScene(sceneNode)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
}
In AppDelegate bypass storyboard.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let viewController = GameViewController()
window?.rootViewController = viewController
window?.makeKeyAndVisible()
return true
}
In GameViewController
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(skView)
setupSKView()
}
let skView: SKView = {
let view = SKView()
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = .fill
view.presentScene(scene)
}
return view
}()
func setupSKView(){
skView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height / 2)
}
}

How to make part of a view controller SKScene and use both on the same screen?

I try to make a view controller, where i.e top half of the screen is SKScene, and bottom half of the screen is normal scene, I mean with buttons etc. Is this possible? I created a Single View application, and I am adding some code snippets below, which is the code from viewcontroller.swift file. But it doesn't create boxes to the tapped locations and also it doesn't move as expected a free fall motion when tapped. Maybe is there an issue about that I created a Single view application rather than choosing Game application when first creating the project? Maybe Metal enable/disable needed? I am not professional, therefore just guesses.
import UIKit
import SwiftUI
import SpriteKit
class GameScene: SKScene {
override func didMove(to view: SKView) {
physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let box = SKSpriteNode(color: .red, size: CGSize(width: 0.04, height: 0.04))
box.physicsBody = SKPhysicsBody(rectangleOf: box.frame.size)
box.position = location
addChild(box)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = .aspectFill
scene.backgroundColor = .clear
let transition = SKTransition.fade(withDuration: 1)
view.presentScene(scene, transition: transition)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
view.allowsTransparency = true
view.backgroundColor = UIColor.clear
}
}
}

Add SKScene overlay in RealityKit

In ARKit, we can easily add an SKScene overlay as a HUD (head up display).
let hud = SKScene(size: sceneView.frame.size)
sceneView.overlaySKScene = hud
How do you do this in RealityKit? As there are no overlaySKScene in ARView?
You can create this overlay programmatically:
import SpriteKit
import RealityKit
class ViewController: UIViewController {
#IBOutlet var arView: ARView!
let skView = SKView(frame: CGRect(x: 0, y: 0, width: 200, height: 150))
let scene = SKScene()
override func viewDidLoad() {
super.viewDidLoad()
arView.backgroundColor = .black
skView.showsFPS = true
scene.backgroundColor = .systemTeal
let boxAnchor = try! Experience.loadBox()
boxAnchor.steelBox?.scale = [9,9,9]
arView.scene.anchors.append(boxAnchor)
arView.addSubview(skView)
skView.presentScene(scene)
}
}

SKScene Won't Present When SubView Is Added To View Controller

I tried to add a subview to my GameViewController (because I want to add a banner ad at the bottom). I created it as follows:
if let view = self.view as! SKView? {
let subView = SKView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 415, height: 685)))
view.addSubview(subView)
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = SKSceneScaleMode.aspectFit
subView.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsDrawCount = false
addBannerViewToView(bannerView)
}
}
This works initially - it presents my GameScene. But later, I ask my GameScene to present another subclass of SKScene that I created, which I call Shop, using the following code:
func initializeShop() {
let shop = Shop(size: self.size)
let transition = SKTransition.fade(withDuration: 0.1)
self.view?.presentScene(shop!, transition: transition)
}
And it simply does not present. It remains on the current view.
This works completely fine if I do NOT add a subview to the initial view in the GameViewController, i.e.
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = SKSceneScaleMode.aspectFit
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsDrawCount = false
}
}
So it seems like there is some property of the GameViewController's default SKView that allows presentation, but not a subview. But I can't find any documentation that says that - from what I can tell, all SKViews should be able to present SKScenes.
Any help would be much appreciated.

How to proper set up a UIButton in SKScene

I set up a UIButton in my Scene/View and the Button shows when the Scene is called by the ViewController. The problem is when I click the Button and my GameScene will be called, the Button will is still there. I think I set up the button in a wrong way.
I guess the problem is that I can't call the removeFromSuperview() function on the button1 in my startGame function.
How can I fix this? Any help is appreciated!
import Foundation
import SpriteKit
import UIKit
class MenuScene: SKScene {
override init(size: CGSize) {
super.init(size: size)
backgroundColor = SKColor.grayColor()
let label = SKLabelNode(fontNamed: "CourierNewPS-BoldMT")
label.text = "Start Game"
label.fontSize = 40
label.fontColor = SKColor.blackColor()
label.position = CGPoint(x: size.width/2, y: size.height/2)
addChild(label)
}
override func didMoveToView(view: SKView) {
let button1=UIButton(frame: CGRectMake(size.width/2, size.height/2, 300, 100))
button1.backgroundColor = UIColor.greenColor()
button1.setTitleColor(UIColor.blackColor(), forState: .Normal)
button1.setTitle("Unfocused", forState: .Normal)
button1.setTitle("Start", forState: .Focused)
button1.addTarget(self, action: "startGame:", forControlEvents: UIControlEvents.PrimaryActionTriggered)
self.view?.addSubview(button1)
}
func startGame(sender:UIButton) {
let gameView = view! as SKView
gameView.ignoresSiblingOrder = true
let reveal = SKTransition.flipHorizontalWithDuration(0.2)
let scene = GameScene(size: self.size)
gameView.presentScene(scene, transition:reveal)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You have access to your button1 object with sender from startGame(sender:UIButton) method. It is the reference to button1 in this case. And you can call removeFromSuperview method from it:
func startGame(sender:UIButton) {
let gameView = view! as SKView
gameView.ignoresSiblingOrder = true
let reveal = SKTransition.flipHorizontalWithDuration(0.2)
let scene = GameScene(size: self.size)
gameView.presentScene(scene, transition:reveal)
sender.removeFromSuperview()
}