Override headache
BlitzMax Forums/BlitzMax Programming/Override headache
| ||
I'm using the game state code found in the code archive and I've modified to use methods instead of functions as I want to encapsulate it. I also need to pass a value from the original instance but here is where I have my problems. Local state:GameState = New GameState state.value = New MyType state.value.name = "A name" state.switch( New MyState ) Type MyType Field name:String End Type ' make a new type that extends this one. Overload the methods. Type MyState Extends GenericState ' Overload this one and put startup code here (loading images, sounds, etc) Method startup() ' ------------------------------------------------------------- DebugLog Self.value.name ' ------------------------------------------------------------- EndMethod ' No drawing here! Only user input and other behind-the-scene stuff Method update() EndMethod ' Draw things in this one. But no user input or logic code! Method draw() EndMethod ' Save highscore/nullify variables/scream like a banshee Method shutdown() EndMethod ' Called when the engine switches to a new state. Method on_hold() EndMethod ' Called when the engine is done with the other state and switches back t this one Method resume() EndMethod EndType ' make a new type that extends this one. Overload the methods. Type GenericState ' ------------------------------------------------------------- Field value:MyType ' ------------------------------------------------------------- ' Overload this one and put startup code here (loading images, sounds, etc) Method startup() EndMethod ' No drawing here! Only user input and other behind-the-scene stuff Method update() EndMethod ' Draw things in this one. But no user input or logic code! Method draw() EndMethod ' Save highscore/nullify variables/scream like a banshee Method shutdown() EndMethod ' Called when the engine switches to a new state. Method on_hold() EndMethod ' Called when the engine is done with the other state and switches back t this one Method resume() EndMethod EndType Type GameState Field state_list:TList Field current_state:GenericState ' ------------------------------------------------------------- Field value:MyType ' ------------------------------------------------------------- Method Switch( new_state:GenericState ) If Not Self.state_list Then Self.state_list = CreateList() Self.state_list.addlast( new_state ) If current_state Then current_state.on_hold() new_state.startup() ' ------------------------------------------------------------- new_state.value = Self.value ' ------------------------------------------------------------- Self.current_state = new_state EndMethod ' Called by the running state when it doesn't want to play anymore Method ExitState() If Not state_list Then RuntimeError("ExitState should only be called by running states!") Self.current_state.shutdown() Self.state_list.remove( Self.current_state ) If Self.state_list.Count() > 0 Then Self.current_state = GenericState( Self.state_list.last() ) Self.current_state.resume() EndIf EndMethod Method Run() If Not Self.state_list Then RuntimeError("Switch to a new game state before calling GameState.Run()") While Self.state_list.Count() > 0 Self.current_state.update() Self.current_state.draw() Wend EndMethod EndType see where i've marked the code with ------------------------ (multiple places). This is where I try to pass a object so I can reference it from my newly created gamestate. Try to run the code and you'll see how it fails and it's beyond me how to solve it.... |
| ||
Just quickly looked over the code. Two things pop out for me: 1. Superstrict missing 2. Type GenericState looks like it should be Abstract Ill have a look at the code more in-depth later... |
| ||
Try this code... it doesnt crash at least (you needed to create a new MyType): |
| ||
Thanks for looking at this, much appreciated. Yes, I definitely use SuperStrict but I missed it in the example. Your code works now as you said but it defeats what I'm trying to achieve. The MyType object is already created with the "New MyType" command before the switch is made. See MyType as the game object that should own everything else. It's important that I can pass in the already existing object so I can reference values in the MyType object such as game settings and lists etc. Or maybe this is a bad design idea? I want to avoid any globals so I can truly encapsulate my game - it will help when creating the network code so I can create two instances in one compile. Any additional thoughts are most welcome =) |
| ||
Try using create and init methods. The base type has an init method that ensures the arguments you pass it are worked on, and the derived type has a create function to wrap all the creation code. I renamed your GameState to a GameStateManager and if you don't need more than one manager there's nothing wrong with .. Then you don't have to remember to create one each time. You can even provide a nice simple API to keep the typing down.. Function SwitchGameState( new_state:GenericState ) GameStateManager.Switch( new_state ) End Function And so on. Finally, I think ExitState should take a GenericState parameter to ensure it is only ever trying to remove itself. HTH |
| ||
Finally got around to test it, my wife just delivered a son earlier than expected :) Thanks matibee - the revised code works just they way I need it to! |
| ||
Finally got around to test it, my wife just delivered a son earlier than expected :) A big congratulations! Hope they're all doing fine. Happy times :) |