Results 1 to 10 of 26

Thread: State machine - requesting advice

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Code:
          //if CurrentState<>nil then CurrentState.Destroy; // This you can't call.
          //CurrentState = MainMenuState sometimes, and calling Destroy on already Destroyed object brings trouble...
          if MainMenuState<>nil then MainMenuState.Destroy;
    Not entirely sure, but i think you need to override them all. CurrentState is type TState, so calling CurrentState.Update etc must refer to object it was created as. Hence override.
    Code:
    TMainMenuState = class(TState)
        public
          constructor Create; override;
          destructor Destroy; override;
          procedure Update; override;
          procedure BeforeDraw; override;
          procedure Draw; override;
          procedure Main; override;

  2. #2
    The reason why you are getting segfault on MainMenuState.Destroy is becouse you are calling inherited on the start of the destructor method.
    In constructor (SomeObject.Create) you always call inherited on start of the method to make sure that constructor code from parent class is executed first.
    But in destructor (SomeObject.Destroy) you should always call inherited last othervise destructor code from parent class is executed too fast and can lead to memory leaks due to only freeing part of your objects memory (only memory of parent class is being freed up).

    As for nothing except initialization showing shouldn't you be calling the stuff from your Main Loop within the OnTimer events of your timers that you prepared in initialization part of your game?

  3. #3
    Well, yes, but some things are needed to be called in main loop, like drawing. As for your suggestion regarding segfault (calling inherited in destroy last), it didn't fix the issue.

    @User137: Segfault is even there if only I'm destroying only MainMenuState, without touching CurrentState.

    As for overriding, let the compiler speak for itself:
    Quote Originally Posted by FPC
    states.pas(32,17) Error: There is no method in an ancestor class to be overridden: "TMainMenuState.Update;"
    states.pas(33,17) Error: There is no method in an ancestor class to be overridden: "TMainMenuState.BeforeDraw;"
    states.pas(34,17) Error: There is no method in an ancestor class to be overridden: "TMainMenuState.Draw;"
    states.pas(35,17) Error: There is no method in an ancestor class to be overridden: "TMainMenuState.Main;"
    states.pas(48,1) Fatal: There were 4 errors compiling module, stopping
    And those methods are in ancestor (TState)!

  4. #4
    Yes, but you need to mark a method as "virtual" in your ancestor to be able to override it.

  5. #5
    It works, thanks! Now if only I could figure out that pesky segfault...

  6. #6
    Figured it out, you need to have virtual; at the end of the TState methods. If you also add them abstract; , then you don't need to make them implementation code at all. But that is only useful tip if you never plan to add them any code, and also if they're abstract, then they must be defined in all inheriting classes.

    Can't see the source for segfault if you did also what SilverWarior said.

    1 other tip that i could give, is making new unit for TState alone. Then you can use the same state-machine in all your projects. You could move the CurrentState variable there, and also make a universal procedure like
    Code:
    procedure RunStatesApp;
    begin
          repeat
            CurrentState.BeforeDraw;
            CurrentState.Draw;
            CurrentState.Main;
          until quit;
    end;
    that you would call from main program unit.
    (Make sure there are no uses-list's in the universal state-unit)
    Last edited by User137; 29-06-2013 at 11:28 AM.

  7. #7
    Hm, thanks. May I send you project files so you can help me debugging this segfault (will try to check callstack before that)?

    //edit: Callstack isn't helpful. It shows only that function I mentioned before (ntdll!LdrWx86FormatVirtualImage (1584)) and since it seems to be Windows function, I can't really do anything about it...

    Question: Do modern operating systems (Windows/Linux/Mac) free up memory that was used of program even if it was leaked? If they are I could probably get away with not freeing states up at end of program without any damage for players. Of course best would be to fix underlying issue, but if you won't be able to help I'll need some sort of last resort.
    Last edited by Darkhog; 29-06-2013 at 11:37 AM.

  8. #8
    Quote Originally Posted by Darkhog View Post
    Hm, thanks. May I send you project files so you can help me debugging this segfault
    Sure. You could also consider using some webservice to temporarily upload files. Speaking of which, i guess i'll have to try Dropbox myself. Are there better ones? Google drive sharing is not very anonymous i think, doesn't everyone see your email?
    edit2: Seems i was wrong about the email thing. You only see yourself logged in google account, and possibly other accounts viewing them, but just their names.

    edit:
    Quote Originally Posted by Darkhog View Post
    Question: Do modern operating systems (Windows/Linux/Mac) free up memory that was used of program even if it was leaked?
    Yes, they free it. But i'm not sure if attached debugger like used for Delphi or Lazarus handles that well.
    Last edited by User137; 29-06-2013 at 11:49 AM.

  9. #9
    Well, I'm only worried about players when they will want to play SHL several times in a row and they'll fill memory by accident. I'm not worried about me as developer, as I know what I'm getting into and in worst case, I can restart PC. Though I don't want players to need to restart their PCs.

    Anyway, as I've said, this is last resort. I want to figure out how to actually fix that.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •