cocos2d swift how to present a scene? - ios

Just started with coco2d/swift and am having trouble presenting a scene. I created a new one in spritebuilder, published it, and am loading it with CCReader as a scene. When I try to present it, it won't present.
class MainScene: CCNode {
override init(){
super.init()
let mainMenu = CCBReader.loadAsScene("ccbResources/MainMenu");
CCDirector.presentScene(mainMenu)
}
}
I get a build error saying:
"cannot invoke presentScene with an argument list of type CCScene".
So I can't really find any examples of this working for me or how to do it.

Only once you can use presentScene, then try replaceScene
class GameScene: CCScene {
class func scene() -> GameScene
{
return GameScene()
}
override init()
{
super.init()
}
}
class MainScene: CCScene {
class func scene() -> MainScene
{
return MainScene()
}
override init()
{
super.init()
//to replace scene
CCDirector.sharedDirector().replaceScene(GameScene.scene())
}
}

Related

How to notify a change from a class to multiple ViewControllers?

I'm writing because I'd like to know what's the best method to notify a change from a class to multiple ViewControllers. At the moment I'm using delegate method but I'm sure It's not the best one for this purpose. I created a class where I receive data and after a bit of processing I need to send the processed message to some ViewControllers (any one shows a piece of that message.). At the moment I have a singleton for the class and I assign its delegate to a different ViewController when I load it through a menu. What's your suggestion to do this job?
Here is an example of my actual code:
import Foundation
protocol MyClassDelegate {
func receivedData(_ sender: MyClass)
}
class MyClass: NSObject {
// create the var for delegate
var delegate: MyClassDelegate?
// save the single instance
static private var instance: MyClass {
return sharedInstance
}
private let sharedInstance = MyClass()
static func getInstance() -> MyClass {
return instance
}
func processData() {
// at the end of the process
delegate?.receivedData(self)
}
}
class Menu: UIViewController {
private var containerView: UIView!
private let myClass = Myclass.getInstance()
private var vcOne = VcOne()
private var vcTwo = VcTwo()
override func viewDidLoad() {
super.viewDidLoad()
containerView = UIVIew()
// set containerView position and dimensions
}
func selectViewController(previous: UIViewController, next: UIViewController) {
// remove actual loaded ViewController
previous.willMove(toParent: nil)
previous.view.removeFromSuperView()
previous.removeFromParent()
// assign the delegate
myClass.delegate = next
// add the new ViewController
self.addChild(next)
slef.addSubView(next.view)
next.didMove(toParent: self)
}
}
class VcOne: UIViewController, MyClassDelegate {
func receivedData(_ sender: MyClass) {
// data received
}
}
class VcTwo: UIViewController, MyClassDelegate {
func receivedData(_ sender: MyClass) {
// data received
}
}
You can use NotificationCenter https://developer.apple.com/documentation/foundation/notificationcenter to broadcast a message. or use KVO. Generally I consider notification center much easier.
simple example:
https://www.hackingwithswift.com/example-code/system/how-to-post-messages-using-notificationcenter

Subscribing to a property

I have a singleton service class which maintains a value of heading it gets from the compass. I have a UIView which draws some custom graphics based on this. I'm trying to do something like an Observable in javascript, where my code gets executed when there's a change in the value.
final class LocationService: NSObject {
static let shared = LocationService()
public var heading:Int
public func getHeading() -> Int {
return self.heading
}
Then in my UIView subclass:
var ls:LocationService = LocationService.shared
var heading: Int = ls.getHeading() {
didSet {
setNeedsDisplay()
}
}
I tried also just directly accessing the property via ls.heading but this doesn't get accepted either. It's telling me I cannot use the instance member within the property initialiser. What's a proper swift method of doing this?
Edit:
I've been working with Christian's answer below and some other documentation and now got to here where it all compiles nicely, but doesn't actually work. Here's my delegator and protocol:
final class LocationService: NSObject {
static let shared = LocationService()
weak var delegate: CompassView?
var heading:Int
func headingUpdate(request:HeadingRequest, updateHeading:CLHeading) {
print ("New heading found: \(updateHeading)")
self.heading = Int(updateHeading.magneticHeading)
self.delegate?.setHeading(newHeading: Int(updateHeading.magneticHeading))
}
public func getHeading() -> Int {
return self.heading
}
}
protocol LSDelegate: class {
func setHeading(newHeading:Int)
}
Then in the delegate:
class CompassView: UIView, LSDelegate {
func setHeading(newHeading:Int) {
self.heading = newHeading
print("heading updated in compass view to \(self.heading)")
setNeedsDisplay()
}
}
So I get the print message that the heading has been updated in the headingUpdate function. The print message in the setHeading function in the delegate CompassView never gets displayed.
You can use the delegation pattern and have that class that wants to consume your events implement the functions in your protocol.
protocol MyDelegate {
func setNeedsDisplay()
}
class LocationService: NSObject {
var myDelegate : MyDelegate?
var heading: Int = ls.getHeading() {
didSet {
myDelegate?.setNeedsDisplay()
}
}
...
func assignDelegate() {
self.myDelegate = MyConsumer()
}
}
class MyConsumer : MyDelegate {
func setNeedsDisplay()
{
}
}

Optional functions for override in Swift classes?

I'm trying to make a simple game using Swift. The game has different levels, and each level requires the game to behave in slightly different ways. I decided to use a different class for each level, all inherited from a base level class.
This is the base:
import SpriteKit
class LevelBase {
var scene: GameScene! // Seems very dodgy
var blocks = [SKSpriteNode]()
init(scene: GameScene) { // Should this be required init?
self.scene = scene
}
func filterBlock(_ block: SKSpriteNode) {
blocks = blocks.filter() { $0 !== block } // Looks really dodgy to me
}
func update(time: TimeInterval) {
// For override
}
func levelUp() {
// For override
}
func postGenerate() {
// For override
}
}
However, to me, this class seems to be very badly written. I can't find any examples anywhere of functions created in a class just to be overwritten, which makes me think I'm doing something wrong. Should I be using extensions or protocols for optional functions like that? I don't quite understand how they work, so I haven't used any so far.
The second issue is that this class needs to be initialized with the game scene variable, since some levels need it to add or remove sprites. This seems especially dodgy, considering the class is created in the game scene's file.
Surely there's a better way?
I have no experience with SpriteKit, but from a general perspective you should consider to "Favour composition over Inheritance".
You would have one Level class that is not intended for subclassing but can be instantiated with objects or values that have different implementation.
Additionally you should use protocols to define those and you can add default implementation as protocol extensions.
final class Level {
init(levelImplementation: LevelImplementationType) {
self.levelImplementation = levelImplementation
}
let levelImplementation: LevelImplementationType
func navigate() {
levelImplementation.navigate()
}
func update(timeInterval: TimeInterval) {
levelImplementation.update(timeInterval: timeInterval)
}
}
The Level would be instantiated with an object or struct conforming to LevelImplementationType
protocol LevelImplementationType {
func navigate()
func update(timeInterval: TimeInterval)
}
Default implementations can be done via an extension.
extension LevelImplementationType {
func navigate() {
}
func update(timeInterval: TimeInterval) {
}
}
The LevelImpelmenation needs to conform to LevelImplementationType, but don't have any further constraints. i.e. they can have very different initialisers.
struct LevelImplementation1: LevelImplementationType {
// useses default implementation of `navigate` and `update` from extension
}
struct LevelImplementation2: LevelImplementationType {
// useses default implementation of `update` from extension
func navigate() {
}
}
struct LevelFileImplementation: LevelImplementationType {
init(with path: String) {
// read variables from file at path
}
func navigate() {
// navigate as given in file
}
}
Level instances cane be created like
let level1 = Level(levelImplementation: LevelImplementation1())
let level2 = Level(levelImplementation: LevelImplementation2())
let level3 = Level(levelImplementation: LevelFileImplementation(with: "path/to/file"))

Swift Delegate from Singleton not working

I'm trying to implement SharedInstanceDelegate in App class. I have no idea why the functions under the protocol are not being called.
This is my Protocol and class.
class App {
let sharedInstance = SharedInstance.shared
init() {
self.sharedInstance.delegate = self
}
}
extension App: SharedInstanceDelegate {
func1() { } // this is not executed
func2() { }
}
protocol SharedInstanceDelegate: class {
func1()
func2()
}
class SharedInstance {
static let shared = SharedInstance()
weak var delegate: SharedInstanceDelegate?
private init() { }
func method1() {
self.delegate?.func1() // this is executed
}
}
I believe you meant to make SharedInstanceDelegate a protocol, but you've made it a class. In either case, App does not conform/inherit SharedInstanceDelegate, so it's not clear how this would even compile.
Here is how I would implement your code to work with the delegate:
class App {
let sharedInstance = SharedInstance.shared
init() {
self.sharedInstance.delegate = self
}
}
extension App: SharedInstanceDelegate {
func func1() { } // this will run now
func func2() { }
}
protocol SharedInstanceDelegate {
func func1()
func func2()
}
class SharedInstance {
static let shared = SharedInstance()
var delegate: SharedInstanceDelegate?
private init() { }
func method1() {
self.delegate?.func1() // this is executed
}
}
Still no idea why this was happening, but cleaning the project fixed this. This is very strange. I have other delegates that call successfully.
Your code could work but it depends on how you are calling func1(). Calling it like this:
let testinstance = App().sharedInstance
testinstance.delegate?.func1()
will not work because you are not holding on to the App object. In this case the App object is the delegate, but because its a weak member and no one is retaining it, it gets released right away.
If you call it like this:
let testapp = App()
testapp.sharedInstance.delegate?.func1()
it works. In this case the App object is being retained and is still around when func1() is called.
Either way the way these classes are related is confusing to me. Why have a separate SharedInstance class at all?

Empty vars when calling method from singleton class

So I have a singleton class in which I have implemented the delegate of my module. However when that delegate method gets executed in this singleton I call a method in another class of the App and it crashes because all the variables previously set in that class are empty.
class Player: Jukebox, JukeboxDelegate {
static let sharedInstance = Player()
func setDelegate(){
jukebox = Jukebox(delegate: self)
}
func play(Link: String) {
jukebox.setIT([JukeboxItem(URL: NSURL(string: Link)!)])
jukebox.setImage(currentImage)
jukebox?.play()
}
func audioPlayerDidFinishPlaying(player: Jukebox, successfully flag: Bool) {
if pltype == PlayerType.Playlist {
MyMusicVC.continuePlaying() { () -> () in
}
}
}
func jukeboxStateDidChange(state: Jukebox) {
}
func jukeboxPlaybackProgressDidChange(jukebox: Jukebox) {
}
func jukeboxDidLoadItem(jukebox: Jukebox, item: JukeboxItem) {
}
func jukeboxDidUpdateMetadata(jukebox: Jukebox, forItem: JukeboxItem) {
}
}
Any ideas on why could this be happening?
Its hard to understand what is going on. But you are subclassing a Jukebox class. Then making this subclass a delegate of the Jukebox itself. Then I also notice you're setting a Jukebox property that appears to be optional but not.
For example. Why in the play() function is jukebox. used twice but the last line is jukebox?. Is jukebox optional? Or implicitly unwrapped? And if thats the case, why are you using it unwrapped twice and then optionally the third time.
Have you tried not making this singleton a subclass of jukebox. Instead just make it conform to the JukeBoxDelegate protocol and see if that accomplishes the same goal?

Resources