2

How do I compose a touchesBegun command in a StartButton class that calls start() in the scene any instance of itself has been placed in?

I know... probably OOP 101. But well beyond me, today.

UPDATE:

Here is how I currently (partially) solve the problem. It doesn't feel right, but it works, somewhat. Not as much as I'd like:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    SoundManager.playSceneStartSound()
    run(ready)
     if CEO.startButtonIsActive{
        print("We're STARTING NOW...")
        if let menuScene = self.scene as? Menu_Memory {
            menuScene.startTheGame()
            }
        else
        if let menuScene = self.scene as? Menu_Chaser {
            menuScene.startTheGame()
            }
        else
        if let menuScene = self.scene as? Menu_Picker {
            menuScene.startTheGame()
            }
        else
        if let menuScene = self.scene as? Menu_Q_AndA {
            menuScene.startTheGame()
            }
        else
        {print("Houston, we have a problem... no gameScene")}
        }
    else
    {
    print("You still have some preparation to do, amigo!")
    }
}

Alternatively, the ability to pass a Class Type would be helpful too. This is almost a separate question, but for the fact I think they're very closely related, perhaps.

At any rate: in a button, trying to create a reference to a class type, I've tried a bunch of variations, with no luck.

Some of my ridiculous attempts, all fail:

Menu_Memory is a SKScene

    var menuClass01: Menu_Memory.self
    var menuClass02: AnyClass = Menu_Memory.self
    var menuClass03: AnyClass = Menu_Memory(self)
    var menuClass04: AnyClass as! Menu_Memory.self
    var menuClass05: AnyClass as! Menu_Memory(self)
Confused
  • 6,048
  • 6
  • 34
  • 75
  • You mean how do you call a method defined in a scene from within another class likely subclass of SKSpriteNode? If so, use delegation. I have answered something like that few times. What you need is a protocol which scene will conform to, a delegate property on a button. So when you press a button it will do self.delegate.start() . start() is a method you should declare in protocol and implement it in a scene. Delegate propery of a button should be set after the button is created. – Whirlwind Dec 12 '16 at 00:49
  • That looks a lot like Greek, to me. Without protocols, can this be done? – Confused Dec 12 '16 at 00:51
  • So that is what you are trying to achieve? It is not Greek, you'll see. I will post you an example of one of my answers where this is explained in detail. Another way...Hm...There are probably few more ways. Try to expand your question to explain exact situation and me or somebody else will tell you what would be a good way to go. – Whirlwind Dec 12 '16 at 00:58
  • I have a very limited understanding of how to use protocols, and even less understanding of how to use delegates and delegation. Despite using it a few times, and it being in the project I'm working on... I'm looking at my own code with zero understanding of it. – Confused Dec 12 '16 at 00:59
  • For example, is there a real need that your button has its own toucesBegan? If not, then you can do touches handling directly in a scene. So you can call your start() method from a scene directly (i assume that start() is an instance method of a scene). – Whirlwind Dec 12 '16 at 01:01
  • 1
    I will explain you delegation pattern and protocols in our SKA Slack channel tomorrow. One of my answers about something similar : http://stackoverflow.com/a/36524132 – Whirlwind Dec 12 '16 at 01:06
  • Yes, there is a need for the start button to have its own touch handling. I'm trying to build a modular environment with many game modes. – Confused Dec 12 '16 at 01:06
  • Cheers! I'll bring my A-game, which is about D level. D for dunce. – Confused Dec 12 '16 at 01:10
  • Also from that answer, is discutable who is the boss. I said there, that button is a boss, and it tells scene what to do. But you can look it from the other angle. A button is a worker, and it notifies his boss (a scene) that it should take some actions because some work is done. So the boss should decide what next. Anyhow, I think it is a good example of what we were talking about. You have all there. Just try to read it all. – Whirlwind Dec 12 '16 at 01:19
  • Overview of delegates - http://stackoverflow.com/a/12833975/1430420. It mentions Objective-C, but it explains delegates & delegation regardless of language, platform or framework. – Steve Ives Dec 12 '16 at 09:37
  • @Confused, how does your `Menu_Memory` class look? – holex Dec 12 '16 at 09:45
  • I've read more about delegates, on more sites, over a longer period of time, than I care to admit to. I simply just don't ever get it. – Confused Dec 12 '16 at 09:45
  • @holex it's just a normal SKScene, full of nonsense and guff. Has a supporting .sks file, too. – Confused Dec 12 '16 at 09:45
  • @Confused You'll suddenly 'get it' when you read the right explanation, and then wonder how you ever 'didn't get it' :-) – Steve Ives Dec 12 '16 at 09:46
  • @Confused, if that is yours, why did not you create a singleton of that class or delegates maybe (as it was recommended above)? – holex Dec 12 '16 at 09:47
  • It's the blend of extensions, associated types and generics, which seem to all need to be within protocol design to make it work, that's doing my head in. @SteveIves I can't get the full picture. – Confused Dec 12 '16 at 09:48
  • @Confused - just to clarify: you want to be able to add your start button (which is a sub-class of SKSpriteNode) to any scene, and then when the button is clicked on -screen, the start() method of that scene to be called? Is the scene to be already on screen or can it be another scene? – Steve Ives Dec 12 '16 at 09:52
  • @SteveIves both. But the important thing is the touchesBegan() of the button be able to call to wherever it needs to call. I've followed a combination of an Alessandro answer and a Whirlwind answer and gotten some of what I want working with Protocols and Delegates, but it's a strewn out mess... – Confused Dec 12 '16 at 09:53
  • I'm baffled I can't pass around Class Types. I thought that would be the easiest way to do it. – Confused Dec 12 '16 at 09:54
  • It could either have a back button, or swerve off to other scenes, via new choices and a new start button @SteveIves – Confused Dec 12 '16 at 09:57
  • @Confused what happens in a scene that has a start() function but which doesn't contain a start button? Does the scene call it's own 'start()' function if there is no 'start' button? – Steve Ives Dec 12 '16 at 09:59
  • argh, sorry. I see the confusion. I shouldn't be calling all these start() buttons. Some are more like config buttons that eventually start a scene somewhere else. Imagine a game with an enormous number of modes, and many different options and game modes for each mode... and that's the sort of molasses I'm in. @SteveIves – Confused Dec 12 '16 at 10:06
  • I've minimised the problem to the least I think I need to get what I want working, @SteveIves, rather than try to explain the minestrone soup and spaghetti pasta mess I'm working in. – Confused Dec 12 '16 at 10:07
  • @SteveIves I've come to realise Protocols and Delegates are somewhat like Physics Masks... in that getting them to work requires going through a preflight clipboard check. "have you done this... done that... been over here to do this... made a few of these... considered what this does..." ok... "Launch!" – Confused Dec 13 '16 at 08:17
  • @Confused. here's a check-list I wrote for delegates in Objective-C : http://stackoverflow.com/a/12827033/1430420 It should translate to Swift easily enough. – Steve Ives Dec 13 '16 at 09:36

1 Answers1

1

UPDATE Now that I have a clue as to what ur doing. Should be self-explaining. Yell at me if it isn't:

public extension SKScene {
  func startGame() { // Because startTheGame is a terriblename..
    // Override in your subclasses of SKScene if desired.
  }
}

enum Menu { // Used as namespace for chaser and menu classes

  final class Chaser: SKScene {
    override func startGame() {
      print("chaser started")
    }
  }

  final class Memory: SKScene {
      override func startGame() {
      print("memory started")
    }
  }
}

.

final class Button: SKNode {
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    scene!.startGame() // No need for guard / if-let,
                       // because how can you click the node if its scene is nil :)?
  }
}
Fluidity
  • 3,985
  • 1
  • 13
  • 34
  • on a personal note, You'll probably want to steer clear of the stuff that OOP tends to entail, such as complex delegates and inheritance etc... You are much more procedural-type programmer, and the more state (vars) you enter into your program, the more confusing / harder to debug it will become. Protocols are good though. Coupling can be good, though it's shunned universally.. if it makes sense to you, then it's better to do that than something that doesn't (delegates). This is why I tend to keep classes minimal and just use functions, because both options are bad / complex in comparison – Fluidity Dec 13 '16 at 00:07
  • when working in an OOP framework though, it's hard to fight it.... so instead of making delegates I will just pull out vars / funcs and put them in a file scope (such as for an app with multiple view controllers). The alternative is a `manager` class or coupling, or clever functions. – Fluidity Dec 13 '16 at 00:12
  • See update to the question to see what I've come up with to solve part of the problem of a start button knowing where it is... – Confused Dec 13 '16 at 00:57
  • As to your comments about OOP approaches, etc... if I knew what you were talking about I probably wouldn't need to ask the questions ;) – Confused Dec 13 '16 at 00:59
  • @Confused you can use switch and is like I did... dont need a dozen if let statements. can use let with case too – Fluidity Dec 13 '16 at 01:59
  • there is at least a dozen ways to use switch including with types and optionals – Fluidity Dec 13 '16 at 02:02
  • your code is doing esse tially same thing i came up with. i think you are on right track. see my use of the Memory types dummy init for passing around around 'type value' – Fluidity Dec 13 '16 at 02:08
  • I don't see how you do anything other than print() on a touch. – Confused Dec 13 '16 at 02:10
  • just call doSomehing in tbegan xD – Fluidity Dec 13 '16 at 02:11
  • your if let blocks are my checkIfMemory() . i jist wrapped it insode doSomething(). so call doSomething in tb and you will have your start func essentially – Fluidity Dec 13 '16 at 02:12
  • @Confused do you want to call different functions based on which scene its in? Because you could just run `start()` if `self.scene != nil`. I thought you wanted to do different functions based on which scene it was in... if you just want to run one function, it is a lot simpler – Fluidity Dec 13 '16 at 12:05
  • @Confused I updated answer with new comments. I think this is exactly what you were looking for: `extension SKScene` – Fluidity Dec 13 '16 at 12:30
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/130547/discussion-between-fluidity-and-confused). – Fluidity Dec 13 '16 at 17:28
  • 1
    @Fluidity So, following this pattern, you might end up with a scene with a lot of methods that does nothing, isn't that right ? Say you need some more methods. Like endGame(), pauseGame() ... And you have a few scenes...Like MenuScene, GameplayScene, LevelSelectScene , SettingsScene etc. The endGame() and pauseGame() methods are specific for GameplayScene()... But other three scenes will have all these methods as well, which actually does nothing, means they have no purpose at all. What do you think about that? Personally, I think your solution will work, but it is not an ideal design ... – Whirlwind Dec 16 '16 at 22:14
  • Or you had in mind to write an extension per SKScene subclass and define desired methods there ? – Whirlwind Dec 16 '16 at 22:17
  • @Whirlwind fileprivate extensions xD – Fluidity Dec 16 '16 at 22:19
  • overriding for subclass would be best but he isnt set up that way yet – Fluidity Dec 16 '16 at 22:20
  • @Confused you need to read what ww said for future development concerns. fp extension is a hotfix really to what he mentioned – Fluidity Dec 16 '16 at 22:23
  • @Whirlwind haha i have seen hos codebas... he is not looking to refactor to subclasses but it would be good, or to extend with a protocol would be good – Fluidity Dec 16 '16 at 22:25