In GameViewController
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
let skView = self.view as SKView
var boo = Bool();
boo = true;
skView.showsFPS = boo;
skView.showsNodeCount = boo;
skView.showsPhysics = boo;
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
And in didMoveToView
var hero = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 40, height: 40));
let hero_body = SKPhysicsBody(rectangleOfSize: hero.size);
hero.position = CGPoint(x:self.frame.size.width/2, y:50);
self.addChild(hero)
I dont understand how the position work.. when the Y is 50, the rectangle is not showing. Before in xcode 5 with objective-c in order the node to be in bottom of the screen I would do
-self.frame.size.height/2 + hero.size.height/2
But in here this doesn't work
The comment is right. -self.frame.size.height/2 + hero.size.height/2 worked when your anchor point was CGPointMake(0.5f,0.5f); It seems that in your case the anchor point was never changed from (0,0). To change it, use the self.anchorPoint = CGPointMake(0.5f, 0.5f); method in your scene.
Related
I have this code in my GameScene swift file:
var background = SKSpriteNode(imageNamed: "background")
let blockImage = SKTexture(imageNamed: "block")
let blockSize = CGSize(width: 64, height: 64)
override func didMove(to view: SKView) {
setUpGame()
}
func setUpGame(){
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
addChild(background)
let block = SKSpriteNode(texture: blockImage, size: blockSize)
block.position.x = block.frame.width/2
block.position.y = frame.height - block.frame.height/2
addChild(block)
}
This is my code in my GameController file:
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
let scene = GameScene(size: self.view.bounds.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
// added to see physics body
view.showsPhysics = true
}
}
why does it take multiple runs for my block node to appear on the simulator except for my background? After the block finally show, it will continue to show after every run until I edit my code. Ive tried removing my background node just in case that might be the issue, but it didn't change anything
I have a 200 x 100 box-like menu button SKSpriteNode declared below.
menuBtn.size = CGSize(width: scrWidth * 1.5, height: 100)
menuBtn.texture = SKTexture(image: UIImage(named: "menuBtn")!)
The problem is, the hitbox for the button is still right, and the width of the SKTexture is fine, but the height of the SKTexture is around 1/2 the size of the actual menuBtn. It is a png, and I've checked and there's no clear textures around the sprite (just the transparent png ones), what am I doing wrong?
Pic of button: https://imgur.com/a/8BtXGLC
Pic of button in App: https://imgur.com/a/ZfW3xDL
Pic of how I want it to look: https://imgur.com/a/2zlSv8y
The texture's png image size is 1044x1044 if that has any impact.
First of all, make sure you are sending the correct size to your scene from GameViewController to your scene, in this example GameScene.
// without .sks
class GameViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
// ...
if let view = self.view as! SKView?
{
let scene = GameScene()
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFit
// Set anchorPoint and pass scene.size
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
scene.size = view.bounds.size
// Present the scene
view.presentScene(scene)
}
// ...
}
// with .sks
class GameViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
// ...
if let view = self.view as! SKView?
{
if let scene = SKScene(fileNamed: "GameScene.sks")
{
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFit
// Pass scene.size
scene.size = view.bounds.size
// Present the scene
view.presentScene(scene)
}
}
// ...
}
In your GameScene create the object. I recommend working in screenWidth and screenHeight when you create objects so they scale to all iOS devices.
class GameScene: SKScene
{
override func didMove(to view: SKView)
{
// ...
// scene width / height
let sceneWidth = size.width
let sceneHeight = size.height
// object
let menu : SKSpriteNode = SKSpriteNode()
menu.texture = SKTexture(imageNamed: "menu")
menu.size = CGSize(width: sceneWidth * 0.75, height: 100)
let y_pos : CGFloat = -sceneHeight * 0.5 + menu.size.height * 0.5
menu.position = CGPoint(x: 0, y: y_pos)
menu.zPosition = 1
addChild(menu)
// ...
}
}
The problem I had was that there were extra transparent pixels in my base image, all I had to do was remove them with GIMP.
Somebody told me in one of my other questions that SpriteKit was easier than UI. I searched online on how to get started with SpriteKit, and I got this: https://www.raywenderlich.com/145318/spritekit-swift-3-tutorial-beginners. I put the images in and everything, I put this code in:
import SpriteKit
class GameScene: SKScene {
// 1
let player = SKSpriteNode(imageNamed: "player")
override func didMove(to view: SKView) {
// 2
backgroundColor = SKColor.white
// 3
player.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
// 4
addChild(player)
}
}
(the code they told me to put in), and when I run it, I just see a blank screen. On the tutorial, it had a ninja, but mine is just a blank screen.
Can anyone help with this?
if the screen is white try this :
import SpriteKit
class GameScene: SKScene {
// 1
var player = SKSpriteNode()
override func didMove(to view: SKView) {
// 2
backgroundColor = SKColor.white
// 3
let image = UIImage(named: "player")
let texture = SKTexture(image: image!)
player = SKSpriteNode(texture: texture)
player.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
// 4
addChild(player)
}
}
If the screen not white : make sure the scene presented correctly .
If you have the GameScene.sks :
In GameViewController :
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
let scene = SKScene(fileNamed: "GameScene")
scene.scaleMode = .aspectFill
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
If you don't have GameScene.sks File
In GameViewController :
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
let scene = GameScene(size : view.frame.size)
scene.scaleMode = .aspectFill
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
I want to know how can I scale the window to fit with the same size in all diveces. The problem is that in some diveces the objects doesnt cover the same space of how I want.
I have my scaleMode = .ResizeFill but the problem is that if I make it .AspectFill it doesnt appear in the correct place. I think that the problem is that I added a new container on the scene, but I dont know how to solve it.
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene(fileNamed:"GameScene") {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .ResizeFill
scene.position = view.center
skView.presentScene(scene)
}
}
override func didMoveToView(view: SKView) {
/* Setup your scene here */
scaleMode = .ResizeFill
node.position = view.center
// 3) Add the container to the scene
//addChild(node)
// 4) Set the sprite's x position
sprite.position = CGPointMake(radius, 0)
// 5) Add the sprite to the container
node.addChild(sprite)
// 6) Rotate the container
rotate()
sprite.color = UIColor.whiteColor()
sprite.colorBlendFactor = 1.0
sprite.zPosition = 4.0
circulo = SKSpriteNode(imageNamed: "circuloFondo2")
circulo.size = CGSize(width: 294, height: 294)
circulo.color = UIColor(red: 0.15, green: 0.15, blue: 0.15, alpha: 1)
circulo.colorBlendFactor = 1
circulo.alpha = 0.35
circulo.position = view.center
self.addChild(circulo)
circulo.zPosition = 1
}
The issue might be in code where you draw circle,You might be drawing
the circle with same radius for all screen sizes.
Instead of drawing the circle with the same radius, you need to
provide dynamic radius of the circle according to the device width.
Replace this
circulo.size = CGSize(width: 294, height: 294)
Use following snippet
let padding:CGFloat = 40.0
circulo.size = CGSize(width:view.frame.size.width - padding , height: view.frame.size.width - padding)
Hello I have a SCNScene with a sprite kit overlay. I also have a subview that contains just a UISlider. The Slider controls the value of one of the SKLabel nodes in the sprite kit overlay. However when I am moving the slider the label does not update. It only updates once I touch outside of the slider. So I am guessing that the SCNScene and the overlay don't update while my touches are in the subview and only update once I touch back to the main view. How can I fix this?
Thanks!
My project is in swift, but if you only know objective-c ill still gratefully take your answer and translate on my own.
SceneKit Code:
class MyMarbleScene: UIViewController {
var scene: SCNScene!
var sceneView: SCNView!
var hud : MyMarbleSpriteKit!
var cameraNode: SCNNode!
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
scene = SCNScene()
sceneView = SCNView()
sceneView.frame = self.view.frame
sceneView.autoresizingMask = UIViewAutoresizing.allZeros
sceneView.scene = scene
sceneView.autoenablesDefaultLighting = false
sceneView.allowsCameraControl = false
sceneView.backgroundColor = UIColor.blackColor()
self.view = sceneView
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 20, z: 60)
hud = MyMarbleSpriteKit(size: self.view.frame.size, game: self)
sceneView.overlaySKScene = hud
let frame = CGRectMake(10.0, self.view.frame.height*0.5, 180.0, 10.0)
let slider = UISlider(frame: frame)
slider.addTarget(self, action: "sliderValueChanged:", forControlEvents: UIControlEvents.ValueChanged)
slider.backgroundColor = UIColor.clearColor()
slider.minimumValue = 1.0
slider.maximumValue = 10.0
slider.continuous = true
slider.value = 5
self.view?.addSubview(slider)
}
func sliderValueChanged(sender: UISlider) {
var currentValue = Int(sender.value)
println("\(currentValue)")
self.hud.updateLabel(currentValue)
}
}
SpriteKit code
class MyMarbleSpriteKit: SKScene {
var myScene: MyMarbleScene!
var SensLabelTwo = SKLabelNode()
override func didMoveToView(view: SKView) {
}
init(size: CGSize, game:MyMarbleScene) {
super.init(size: size)
myScene = game
let SensLabel = SKLabelNode()
SensLabel.text = "Marble Sensitivity:"
SensLabel.fontName = "AvenirNext-HeavyIta"
SensLabel.fontSize = 40
SensLabel.fontColor = UIColor.whiteColor()
SensLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.Top
SensLabel.position = CGPoint(x: 170, y: size.height-20)
self.addChild(SensLabel)
SensLabelTwo.text = "5"
SensLabelTwo.fontName = "AvenirNext-HeavyIta"
SensLabelTwo.fontSize = 60
SensLabelTwo.fontColor = UIColor.whiteColor()
SensLabelTwo.verticalAlignmentMode = SKLabelVerticalAlignmentMode.Top
SensLabelTwo.position = CGPoint(x: 100, y: size.height-80)
self.addChild(SensLabelTwo)
}
func updateLabel(text: Int){
println("helllo")
SensLabelTwo.text = String(format:"%i", text)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
the 2D scene is not automatically refreshed when it's modified.
You will have to wait for the 3D scene to be redisplayed first. This happens when 3D animations or actions are running or when playing is set to YES. Alternatively, you can manually request a refresh with -[SCNView setNeedsDisplay].