Results 1 to 10 of 30

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

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    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.

  2. #2
    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.

  3. #3
    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.

  4. #4
    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.

  5. #5
    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.

  6. #6
    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.

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
  •