source: trunk/src/ticker.cpp @ 116

Last change on this file since 116 was 116, checked in by sam, 10 years ago

Implement a better timing mechanism for fixed framerate. Accuracy is
sub-millisecond but can be improved if we get rid of SDL timers.

  • Property svn:keywords set to Id
File size: 2.7 KB
Line 
1//
2// Deus Hax (working title)
3// Copyright (c) 2010 Sam Hocevar <sam@hocevar.net>
4//
5
6#if defined HAVE_CONFIG_H
7#   include "config.h"
8#endif
9
10#include <cstdlib>
11#include <cstdio>
12#include <stdint.h>
13
14#include "ticker.h"
15#include "asset.h"
16#include "timer.h"
17
18/*
19 * Ticker implementation class
20 */
21
22static class TickerData
23{
24    friend class Ticker;
25
26public:
27    TickerData() :
28        todo(0),
29        nassets(0)
30    {
31        for (int i = 0; i < Asset::GROUP_COUNT; i++)
32            list[i] = NULL;
33        timer = new Timer();
34        bias = 0.0f;
35    }
36
37    ~TickerData()
38    {
39#if !FINAL_RELEASE
40        if (nassets)
41            fprintf(stderr, "ERROR: still %i assets in ticker\n", nassets);
42#endif
43        delete timer;
44    }
45
46private:
47    /* Asset management */
48    Asset *todo;
49    Asset *list[Asset::GROUP_COUNT];
50    int nassets;
51
52    /* FPS management */
53    float delta_time;
54    Timer *timer;
55    float bias;
56}
57tickerdata;
58
59static TickerData * const data = &tickerdata;
60
61/*
62 * Ticker public class
63 */
64
65void Ticker::Register(Asset *asset)
66{
67    /* If we are called from its constructor, the object's vtable is not
68     * ready yet, so we do not know which group this asset belongs to. Wait
69     * until the first tick. */
70    asset->next = data->todo;
71    data->todo = asset;
72}
73
74void Ticker::TickGame()
75{
76    data->delta_time = data->timer->GetSeconds();
77    data->bias += data->delta_time;
78
79    /* Insert waiting objects in the appropriate lists */
80    while (data->todo)
81    {
82        Asset *a = data->todo;
83        data->todo = a->next;
84
85        int i = a->GetGroup();
86        a->next = data->list[i];
87        data->list[i] = a;
88        data->nassets++;
89    }
90
91    /* Garbage collect objects that can be destroyed */
92    for (int i = 0; i < Asset::GROUP_COUNT; i++)
93        for (Asset *a = data->list[i], *prev = NULL; a; prev = a, a = a->next)
94            if (a->destroy)
95            {
96                if (prev)
97                    prev->next = a->next;
98                else
99                    data->list[i] = a->next;
100
101                data->nassets--;
102                delete a;
103            }
104
105    /* Tick objects for the game loop */
106    for (int i = 0; i < Asset::GROUP_COUNT; i++)
107        for (Asset *a = data->list[i]; a; a = a->next)
108            if (!a->destroy)
109                a->TickGame(data->delta_time);
110}
111
112void Ticker::TickRender()
113{
114    /* Tick objects for the render loop */
115    for (int i = 0; i < Asset::GROUP_COUNT; i++)
116        for (Asset *a = data->list[i]; a; a = a->next)
117            if (!a->destroy)
118                a->TickRender(data->delta_time);
119}
120
121void Ticker::ClampFps(float fps)
122{
123    float ideal_time = 1.0f / fps;
124
125    data->timer->WaitSeconds(ideal_time - data->bias);
126    data->bias -= ideal_time;
127}
128
Note: See TracBrowser for help on using the repository browser.