Accessing functions of another class - iphone

So I have a class called GameScene which has a function called makeBackground. In another class called I created an instance of it (GameScene) and called makeBackground as follows in the didMoveToView of the new class:
var gameSceneInstance:GameScene = GameScene()
gameSceneInstance.makeBackground()
However when I run it, nothing happens!
This is the function makeBackground:
func makeBackground ()
{
let bgTxt = SKTexture(imageNamed: "bg.png")
let moveBg = SKAction.moveByX(0, y: -bgTxt.size().height, duration: 5)
let replaceBg = SKAction.moveByX(0, y: bgTxt.size().height, duration: 0)
let moveBgAnimation = SKAction.repeatActionForever(SKAction.sequence([moveBg, replaceBg]))
//-----background-----
for var i:CGFloat = 0 ; i<3; i++
{
bg = SKSpriteNode(texture: bgTxt)
bg.position = CGPoint(x: CGRectGetMidX(self.frame), y: bgTxt.size().height/2 + bgTxt.size().height * i)
bg.size.width = self.frame.width
bg.runAction(moveBgAnimation)
movingObjects.addChild(bg)
}
}
Do I have to copy and paste the makeBackground function into the new class to make it work?
Similarly, in the didMoveToView of the GameScene class, I have some sprites. Can I use them in this new class?
Thanks!

if you created an instance of the GameScene object and called the makeBackground function and nothing happened then there is something wrong with your code in the makeBackground function.
Also in another topic, instance objects which are created in a class are equeals of each other and cannot be used within each others methods unless they are specifically passed in. Perhaps you can make a method in your GameScen object with which you could pass these sprites in either as a list of sprites or as individual sprites

Related

Call a function from a different swift file

XCode Version 12.4 (12D4e)
The first SKScene class in Functions.swift included the buildBackground function which I want to call in different SKScene class.
class Functions: SKScene {
func buildBackground(backgroundPath: String){
let texture = SKTexture(imageNamed: backgroundPath)
let background = SKSpriteNode(texture: texture)
background.size = CGSize(width: 512, height: 512)
background.position = CGPoint(x: 0, y: 0)
background.name = "BACKGROUND"
addChild(background)
print("Background loaded")
}
}
I'm trying to call this function in the second SKScene class in the Room.swift file
I created an instance of Functions in Room and called my function just like that:
public class Room: SKScene {
let functions = Functions()
override public func didMove(to view: SKView) {
functions.buildBackground(backgroundPath: "roomBackground")
}
}
I got "Cannot find 'Functions' in scope" on the "let functions = Functions()" line. After running a build, I got my message "Background loaded", so I guess, the function was called, however, my wallpaper SKSpriteNode has not appeared in my scene. After I tried to move buildBackground method inside Room.swift class, it all works, but there are a lot of different scenes in my project (Room1, Room2, etc.) so I don't want to copy-paste this method each file.
since you are overriding a public function, you probably need to use self :
self.functions.buildBackground(...)

Creating and Using Classes

If I create an instance of the class below and call the spawn function from my controller, the sprite will appear but I won't be able to change any of its properties.
class Hero: SKSpriteNode
{
var hero = SKSpriteNode(imageNamed: "hero3")
func spawn(parentNode: SKNode, position: CGPoint, size: CGSize = CGSize(width: 50, height: 50))
{
hero.size = size
hero.position = position
hero.physicsBody = SKPhysicsBody(circleOfRadius: 25)
hero.physicsBody?.allowsRotation = false
hero.zPosition = 10
parentNode.addChild(hero)
}
}
If I get rid of the hero property and change everything to self, it works fine.
class Hero: SKSpriteNode
{
func spawn(parentNode: SKNode, position: CGPoint, size:CGSize = CGSize(width: 50, height: 50))
{
self.size = size
self.position = position
self.texture = SKTexture(imageNamed: "hero3")
self.physicsBody = SKPhysicsBody(circleOfRadius: 25)
self.physicsBody?.allowsRotation = false
self.zPosition = 10
parentNode.addChild(self)
}
}
I'm sure this is swift 101, but can someone please explain why the first version doesn't work as expected?
In your first example, you created a var (basically a SpriteNode inside the SpriteNode).
When you instantiate the class like let hero = Hero(....) you now have a SpriteNode called hero, with a property called hero. You can change either. Calling hero.size would change the base hero, and hero.hero.size would change the inside SpriteNode....this is probably not the behavior you were looking for.
The second class looks correct, if you are just trying to create a SpriteNode and modify it. The class is a subclass of SpritNode, so it's already a SpriteNode - no need to create one inside it like the first one.
Hope this helps!
Your Hero class inherits from SKSpriteNode, so it is essentially an SKSpriteNode already, which means you don't need to create a hero SKSpriteNode variable.
In your first class, when you use hero.size = size, you're accessing the properties of the variable within your class instead of on the class itself. Then you add the hero SKSpriteNode as a child along with all its properties, but your class SKSpriteNode, which holds the variable doesn't have set properties size or a physics body. You can think of the class as a container that's holding the variable SKSpriteNode.
In your second function, when you use self.size = size, you're accessing the class's properties and giving the class SKSpriteNode all the properties you need to use it in other classes.

Custom Class in Swift using SKSpritenodes/Collision Detection

I am currently working on a game where enemies get spawned from the left of the screen and move right. I want to give these enemies their own attributes (health, strength, etc). So I am working on creating a Basic_fighter class. I also have a user sniper scope that the user uses to hit the enemies. The problem I have is how to access the enemies attributes in the DidBeginContact Function since the function only returns two nodes, and not the class information. I will put my code below
Basic_Fighter_Class
import Foundation
import SpriteKit
class Basic_Fighter {
var health = Int()
var type = SKSpriteNode()
init(sk:SKSpriteNode){
self.type = sk
self.health = 3
}
}
func spawn_enemies(){
let enemynode = SKSpriteNode(imageNamed: "Shooter")
enemynode.size = CGSize(width: 100, height: 40)
enemynode.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
enemynode.physicsBody = SKPhysicsBody(rectangleOfSize: enemynode.size)
enemynode.physicsBody?.affectedByGravity = false
enemynode.physicsBody?.categoryBitMask = BodyType.enemy
enemynode.physicsBody?.contactTestBitMask = BodyType.bullet
let enemy = Basic_Fighter(sk: enemynode)
addChild(enemynode)
}
I am able to detect the contact made between the user scope and the enemy in the DidBeginContact function, but I do not know how to access the information of the enemy, such as its health.
I think you can access it with enemynode.health, I'm not sure though.

Swift: Multiple scenes in Sprite Kit, touchesBegan from different SpriteNodes types on 2nd and 1st scene are called

I am facing a problem using multiple scenes in Sprite Kit (Swift). I’ve setup 3 scene (the game scene, preferences and a help scene). I’ve defined two different SpriteNode classes, called CardItem and MenuItem. While I am using CardItem just at the game scene, I uses MenuItem at all three scenes. So when I touch at the game scene (standard scene) the CardItem SpriteNode, just the touchesBegan function from that class (in game scene) is called. But when I jump into the preferences or help scene (from the game scene), and touch on a SpriteNode MenuItem not just their touchesBegan functions is called but also the touchesBegan from the CardItem type at the game scene!!! (which still is available in the back) is called.
My question is now, is this a feature or a bug in my app?
Here my GameScene Class with the scene initialization
class GameScene: SKScene, PreferencesSceneDelegate, HelpSceneDelegate {
var prefView: SKView?
var helpView: SKView?
var activeGame: Game?
var gamePrefs = gamePreferences()
var prefManager: PreferencesManager!
func prefSceneDidFinish(myScene: PreferencesScene, command: String) {
// Remove PreferencesScene from Screen
if (command == "Abbruch") {
myScene.view!.removeFromSuperview()
setButtonTexture(command)
} else if command == "Done" {
myScene.view!.removeFromSuperview()
activeGame!.setupNewGame(self, gamePrefs: self.gamePrefs, prefManager: self.prefManager, command: 1)
} else {
println("prefSceneDidFinish: command \(command) not specified")
}
}
func helpSceneDidFinish(myScene: HelpScene) {
// Remove HelpScene from Screen
myScene.view!.removeFromSuperview()
}
override func didMoveToView(view: SKView) {
let background = Card(cardType: .background)
background.cardID = CardName.background.rawValue
background.anchorPoint = CGPoint(x: 0.5, y: 1.0)
background.position = CGPoint(x: size.width/2, y: size.height)
background.zPosition = -2
background.userInteractionEnabled = false
self.addChild(background)
//
// Preferences Initialization
//
self.prefView = SKView(frame: CGRectMake(0, 0, self.frame.width, self.frame.height))
// Create and configure PreferencesScene
prefscene = PreferencesScene(size: view.bounds.size)
prefscene.scaleMode = .AspectFill
prefManager = PreferencesManager(prefs: gamePrefs)
tmpSeriesSelection = gamePrefs.inScope // Initialize after data load fromn file
self.prefView!.presentScene(prefscene)
prefscene!.thisDelegate = self
//
// Help Initialization
//
self.helpView = SKView(frame: CGRectMake(0, 0, self.frame.width, self.frame.height))
// Create and configure HelpScene
helpscene = HelpScene(size: view.bounds.size)
helpscene.scaleMode = .AspectFill
self.helpView!.presentScene(helpscene)
helpscene!.thisDelegate = self
var helpSceneBackground = SKSpriteNode(imageNamed: "HelpSceneBackground.png")
helpSceneBackground.anchorPoint = CGPoint(x: 0.5, y: 1.0)
helpSceneBackground.position = CGPoint(x: size.width/2, y: size.height)
helpSceneBackground.zPosition = 0
helpSceneBackground.userInteractionEnabled = false
helpscene.addChild(helpSceneBackground)
activeGame = Game(scene: self, gamePrefs: gamePrefs, prefManager: prefManager)
}
Here is the code snippet (MenuItem touchesBegan) where I call the scenes
case .help :
println("Pressed Help")
var transition = SKTransition.fadeWithDuration(Double(0.0))
self.scene!.view?.addSubview(gamescene.helpView!)
case .preferences :
…
var transition = SKTransition.fadeWithDuration(Double(0.0))
self.scene!.view?.addSubview(gamescene.prefView!)
case .ok :
println("OK Selektion")
…
gamescene.prefManager.save(gamescene.gamePrefs)
prefscene.thisDelegate!.prefSceneDidFinish(prefscene, command: "Done")
Thanks in advance for your help
You are bound to run into problems when your scenes create their own SKView-instances which presents scenes, which creates views, which creates scenes etc. So, skip your prefView and helpView properties and use the scene's view property to present your scenes one after another.
view?.presentScene(scoreScene)
If (for some reason) you need to retain(1) the different scene-instances handle this in your GameViewController instead.
(1) In most cases you probably shouldn't...

accessing an SKSpriteNode declared inside a specific method

In my GameScene class, I have a method called shootLaser that creates an SKSpriteNode called Laser, and adds it as a child of self. This method is called on a timer every several seconds
func shootLaser(){
var Laser = SKSpriteNode(imageNamed: "LaserDot.png")
Laser.position = CGPointMake(100, 100)
Laser.physicsBody = SKPhysicsBody(circleOfRadius: 20)
Laser.physicsBody?.categoryBitMask = PhysicsCatagory.Laser
Laser.physicsBody?.contactTestBitMask = PhysicsCatagory.Blade
Laser.physicsBody?.affectedByGravity = false
Laser.physicsBody?.dynamic = false
Laser.physicsBody?.density = 0.5
self.addChild(Laser)
}
In the update() method, which is automatically called every time a frame is rendered, I try to access the position of the Laser object, but I get an error "Use of unresolved identifier 'Laser'" when I try to set laserLoc to Laser.position
override func update(currentTime: CFTimeInterval)
{
/* Called before each frame is rendered */
// moves every value up an index each frame
let laserLoc = Laser.position
if (laserPoints[0] != nil){
for var index = 9; index >= 1; index--
{
laserPoints[index] = laserPoints[index - 1]
}
laserPoints[0] = CGPointZero
}
I don't seem to have any issues accessing properties of SKSpriteNodes that are declared in the outside any method. Is there a way around this? Thanks in advance!
EDIT:
I am aware that "Laser" is purely local within the shootLaser() method, but just the same, is there a way I can access its properties in the update method?
Try instead putting Laser after the class declaration instead of instead of in the function. Like this:
class YourClassName: SKScene {
var Laser = SKSpriteNode(imageNamed: "LaserDot.png")
Also, make sure you remove the declaration of Laser inside the function and edit the function to look like this.
func shootLaser(){
var Laser = SKSpriteNode(imageNamed: "LaserDot.png")
Laser.position = CGPointMake(100, 100)
Laser.physicsBody = SKPhysicsBody(circleOfRadius: 20)
Laser.physicsBody?.categoryBitMask = PhysicsCatagory.Laser
Laser.physicsBody?.contactTestBitMask = PhysicsCatagory.Blade
Laser.physicsBody?.affectedByGravity = false
Laser.physicsBody?.dynamic = false
Laser.physicsBody?.density = 0.5
self.Laser.removeFromParent()
self.addChild(Laser)
}