Page 3 of 3 FirstFirst 123
Results 21 to 30 of 30

Thread: Yet another segfault (a.k.a. Darkhog is a total noob)

  1. #21
    Quote Originally Posted by phibermon View Post
    Assigned() was created to allow coders to make clear distinctions between checking to see if a func pointer is nil and checking if the result of an assigned function is nil. so without Assigned : MyFunc=nil and MyFunc()=Nil and with assigned : Assigned(MyFunc) and MyFunc()=nil.
    The distinction is important when you do not explicitly use the Nil constant value. Assigned may have been originally intended for that, it became used generally for opaque pointer references, to maintain that opacity.

    Probably best to use Assigned for readability, It's most likely an inline function however It's also an overloaded function so I believe there's run-time type checking going on, don't really know but probably is. If so it'd be technically faster to stick with nil comparisons. Maybe, I'm only assuming that type checking for overloaded functions is run-time for all types, I think it is for class types. Or maybe not, class instance reference being a pointer, maybe you can't have overloaded functions for different class types with the same calling conventions, meaning that overloading might be a compile time thing. Perhaps the compiler will optimize when the program only ever uses one version of the overloaded function. Maybe.
    Assigned() is a built-in function handled by the compiler. I don't think it is overloaded, as there are no definitions to overload. It only works on types which ultimate derive from, or are identical to, the Pointer type. It shouldn't be any slower than a comparison to Nil, since that is what it is replaced with at compile-time, at least on the Windows platform.

    I'm probably giving this too much thought. I'm a bit bored today. In fact it'd probably just be quicker to fire up Lazarus and try overloading a function with different class types.

    EDIT : yes you can overload with identical calling convention for different class types so it's Run Time type checking and nil comparisions are faster (At least in ObjFPC mode with FPC) for class references and pointers. Assuming of course that a nil comparison isn't also subject to run-time checks, which it probably isn't as it wouldn't get past the compile time checks.

    I should imagine overloaded functions with different conventions are sorted out at compile time though.

    I have no idea what you are referring to with respect to Assigned. It is simply a built-in function which the compiler hard-codes to a Nil check. If you're not explicitly using Nil as a data value, or are dealing with opaque (pointer) types, it is more "proper" to use Assigned.

  2. #22
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    Oh fair enough I was going off some page I googled in terms of Assigned which showed three definitions, just checked in FPC and yes it's built in.

    http://stackoverflow.com/questions/4...ssigned-vs-nil

    May as well use assigned. doesn't make a blind bit of difference really. If you're dealing with method pointers to methods that return pointers/objects then using assigned will help you avoid making mistakes I suppose but if you were doing that and used pointers / nil comparisons a lot then you wouldn't make that mistake anyway. Well you'd hope
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

  3. #23
    Well, here's the point. For some implementations, Assigned() may not be just a simple Nil check. For example, let's say that the Foo implementation of FPC does a Nil check AND a check for "0xbaadf00d" (uninitialized data value) to determine if a pointer is valid. If you port your code to Foo, which just checks Nil with a conditional, it may cause an unintended side effect.

    Practically, they are identical, but methodologically, they aren't. It goes back to the same reasons why it is bad to do pointer arithmetic, as in C-like languages... pointers need to be treated as opaque types, and depending on them being specific constant values is just generally a bad practice overall (and why Object Pascal is a much superior language than, say C++).

  4. #24
    Quote Originally Posted by User137 View Post
    Yeah found the download link Either you commented the bugs away, or fixed it, but i don't see problems in menu.
    PS. phibermon edited his post with fixes.
    No, you need to access debug screen. It's right ctrl+left shift+d in main menu. Then, after you touch "other" mario with submarine, game'll crash.

  5. #25
    Quote Originally Posted by phibermon View Post
    Happy birthday

    It's your update() method in the main unit that's running in a separate thread via an Allegro timer, if you call that in your main thread loop instead then that'll fix your problem.

    You are correct about the create defintion, so my apologies However if me and 137 made exactly the same mistake then it might suggest your code could benefit from some formatting.

    I'm only teasing I'm glad we found the issue, it's a great project and please keep the updates on progress coming!
    Well, I'd put it into main loop, if only I wouldn't need to call update EXACTLY 60 times per second, so game won't run too fast on more powerful machines than my own.

  6. #26
    Not sure if I've understood everything you wrote. May be I've lost the thread, but there are a lot to read...

    Allegro.pas isn't thread-safe (4.x isn't, not sure about 5.x), and interruptions works with threads. So interruption procedures should be short and they shouldn't use a lot of variables. In most cases, just increasing/decreasing an integer variable or set a boolean flag is enough and will work. If you want something more complex you should use semaphores or something (as somebody suggested). About the speed, may be you should read this tutorial I wrote some time ago.

    About Allegro's objects (sound samples, bitmaps, etc.) Allegro.pas doesn't assign NIL to variables when destroying so you should do it by yourself. In some cases the best way is to create a wrapper CLASS and use constructor and destructor to manage them.
    No signature provided yet.

  7. #27
    OK, I've caved in and now call update in main loop, with Delay(17) at end (basic Delay, from Crt unit with which you are most familiar with).

    @Nuno, your solution is IMO too complex (with ticks), though I know Delay(17) isn't what I really need, as (1/60)*1000 isn't 17ms, more like 16.66666666666667, though 17 is closest integer approximation. So, at best, I'd need more precise Delay function.

    //edit: I think I know how to customize tick approach to my needs.

    //edit#2: YAY! IT WORKS!

    Thank you guys so much! You're great help even if I sometimes don't appreciate your wisdom!
    Last edited by Darkhog; 07-08-2013 at 08:30 PM.

  8. #28
    Delay(17) is NOT the way to go, since the game will wait the same amount after every frame. On one machine, calculations will take 3ms + 17ms delay = 20ms per frame = 50FPS, but a slower machine will take 8ms + 17ms delay = 25ms per frame = 40FPS, and the game will slow down. To have a steady FPS, what you need to do is:
    Code:
    Function GetMSecs():Comp;
       begin Exit(TimeStampToMSecs(DateTimeToTimeStamp(Now()))) end;
    This function uses standard functions from SysUtils and returns current time as 64bit int containing the amount of miliseconds since 30.12.1899.

    In the game loop:
    Code:
    Time := getMSecs();
    (* Do all the calculations, drawing, et cetera *)
    While (getMSecs() - Time < DELAY_BETWEEN_FRAMES) do Delay(1)
    This way, unless the machine REALLY slows down, to the point that calculating/rendering a frame takes longer than DELAY_BETWEEN_FRAMES, you're going to have a steady FPS.

    Edit:
    Oh, and also, SysUtils contains Sleep(), which does the same crt.Delay() does.
    Last edited by Super Vegeta; 08-08-2013 at 09:37 AM.

  9. #29
    What Super Vegeta said.

    But since you're using Allegro, you should use al_rest (instead of Sleep or Delay), and al_retrace_count (instead of getMSecs, and note that it doesn't count in milliseconds). Don't forget to initialize the timer (call to al_install_timer on initialization).
    Last edited by Ñuño Martínez; 08-08-2013 at 11:04 AM.
    No signature provided yet.

  10. #30
    It's fixed now...

    I've adapted tick approach in Nuno's article and my main loop looks like that:
    Code:
          repeat        while TicksInQueue>0 do
            begin
              if ((CurrentState<>nil) and (not quit)) then CurrentState.Update;
              Dec(TicksInQueue);
            end;
            if not quit then CurrentState.BeforeDraw;
            if not quit then CurrentState.Draw;
            if not quit then CurrentState.Main;
          until quit;
    The only thing update function (timer) does now is to increase TicksInQueue.

Page 3 of 3 FirstFirst 123

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
  •