source: trunk/src/ticker.cpp @ 124

Last change on this file since 124 was 124, checked in by sam, 11 years ago

Make the editor more responsive by handling GTK events before waiting for
the loop to complete.

  • Property svn:keywords set to Id
File size: 3.1 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 "profiler.h"
15#include "ticker.h"
16#include "asset.h"
17#include "timer.h"
18
19/*
20 * Ticker implementation class
21 */
22
23static class TickerData
24{
25    friend class Ticker;
26
27public:
28    TickerData() :
29        todo(0),
30        nassets(0)
31    {
32        for (int i = 0; i < Asset::GROUP_COUNT; i++)
33            list[i] = NULL;
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    }
44
45private:
46    /* Asset management */
47    Asset *todo;
48    Asset *list[Asset::GROUP_COUNT];
49    int nassets;
50
51    /* Fixed framerate management */
52    Timer timer;
53    float delta_time, bias;
54}
55tickerdata;
56
57static TickerData * const data = &tickerdata;
58
59/*
60 * Ticker public class
61 */
62
63void Ticker::Register(Asset *asset)
64{
65    /* If we are called from its constructor, the object's vtable is not
66     * ready yet, so we do not know which group this asset belongs to. Wait
67     * until the first tick. */
68    asset->next = data->todo;
69    data->todo = asset;
70}
71
72void Ticker::TickGame()
73{
74    Profiler::Stop(Profiler::STAT_TICK_FRAME);
75    Profiler::Start(Profiler::STAT_TICK_FRAME);
76
77    Profiler::Start(Profiler::STAT_TICK_GAME);
78
79    data->delta_time = data->timer.GetSeconds();
80    data->bias += data->delta_time;
81
82    /* Insert waiting objects in the appropriate lists */
83    while (data->todo)
84    {
85        Asset *a = data->todo;
86        data->todo = a->next;
87
88        int i = a->GetGroup();
89        a->next = data->list[i];
90        data->list[i] = a;
91        data->nassets++;
92    }
93
94    /* Garbage collect objects that can be destroyed */
95    for (int i = 0; i < Asset::GROUP_COUNT; i++)
96        for (Asset *a = data->list[i], *prev = NULL; a; prev = a, a = a->next)
97            if (a->destroy)
98            {
99                if (prev)
100                    prev->next = a->next;
101                else
102                    data->list[i] = a->next;
103
104                data->nassets--;
105                delete a;
106            }
107
108    /* Tick objects for the game loop */
109    for (int i = 0; i < Asset::GROUP_COUNT; i++)
110        for (Asset *a = data->list[i]; a; a = a->next)
111            if (!a->destroy)
112                a->TickGame(data->delta_time);
113
114    Profiler::Stop(Profiler::STAT_TICK_GAME);
115}
116
117void Ticker::TickRender()
118{
119    Profiler::Start(Profiler::STAT_TICK_RENDER);
120
121    /* Tick objects for the render loop */
122    for (int i = 0; i < Asset::GROUP_COUNT; i++)
123        for (Asset *a = data->list[i]; a; a = a->next)
124            if (!a->destroy)
125                a->TickRender(data->delta_time);
126
127    Profiler::Stop(Profiler::STAT_TICK_RENDER);
128    Profiler::Start(Profiler::STAT_TICK_BLIT);
129}
130
131void Ticker::ClampFps(float fps)
132{
133    Profiler::Stop(Profiler::STAT_TICK_BLIT);
134
135    float ideal_time = 1.0f / fps;
136    if (ideal_time > data->bias)
137        data->timer.WaitSeconds(ideal_time - data->bias);
138    data->bias -= ideal_time;
139}
140
Note: See TracBrowser for help on using the repository browser.