source: trunk/src/ticker.cpp @ 150

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

Replace mouse scrolling with a joystick simulated by the e/s/d/f keys.

  • Property svn:keywords set to Id
File size: 4.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 "core.h"
15
16/*
17 * Ticker implementation class
18 */
19
20static class TickerData
21{
22    friend class Ticker;
23
24public:
25    TickerData() :
26        todo(0),
27        nentities(0)
28    {
29        for (int i = 0; i < Entity::GROUP_COUNT; i++)
30            list[i] = NULL;
31        bias = 0.0f;
32    }
33
34    ~TickerData()
35    {
36#if !FINAL_RELEASE
37        if (nentities)
38            fprintf(stderr, "ERROR: still %i entities in ticker\n", nentities);
39#endif
40    }
41
42private:
43    /* Entity management */
44    Entity *todo;
45    Entity *list[Entity::GROUP_COUNT];
46    int nentities;
47
48    /* Fixed framerate management */
49    Timer timer;
50    float deltams, bias;
51}
52tickerdata;
53
54static TickerData * const data = &tickerdata;
55
56/*
57 * Ticker public class
58 */
59
60void Ticker::Register(Entity *entity)
61{
62    /* If we are called from its constructor, the object's vtable is not
63     * ready yet, so we do not know which group this entity belongs to. Wait
64     * until the first tick. */
65    entity->next = data->todo;
66    data->todo = entity;
67}
68
69void Ticker::TickGame()
70{
71    Profiler::Stop(Profiler::STAT_TICK_FRAME);
72    Profiler::Start(Profiler::STAT_TICK_FRAME);
73
74    Profiler::Start(Profiler::STAT_TICK_GAME);
75
76    data->deltams = data->timer.GetMs();
77    data->bias += data->deltams;
78
79    /* Garbage collect objects that can be destroyed. We can do this
80     * before inserting awaiting objects, because there is no way these
81     * are already marked for destruction. */
82    for (int i = 0; i < Entity::GROUP_COUNT; i++)
83        for (Entity *a = data->list[i], *prev = NULL; a; prev = a, a = a->next)
84            if (a->destroy)
85            {
86                if (prev)
87                    prev->next = a->next;
88                else
89                    data->list[i] = a->next;
90
91                data->nentities--;
92                delete a;
93            }
94
95    /* Insert waiting objects into the appropriate lists */
96    while (data->todo)
97    {
98        Entity *a = data->todo;
99        data->todo = a->next;
100
101        int i = a->GetGroup();
102        a->next = data->list[i];
103        data->list[i] = a;
104        data->nentities++;
105    }
106
107    /* Tick objects for the game loop */
108    for (int i = 0; i < Entity::GROUP_COUNT; i++)
109        for (Entity *a = data->list[i]; a; a = a->next)
110            if (!a->destroy)
111            {
112#if !FINAL_RELEASE
113                if (a->state != Entity::STATE_IDLE)
114                    fprintf(stderr, "ERROR: entity not idle for game tick\n");
115                a->state = Entity::STATE_PRETICK_GAME;
116#endif
117                a->TickGame(data->deltams);
118#if !FINAL_RELEASE
119                if (a->state != Entity::STATE_POSTTICK_GAME)
120                    fprintf(stderr, "ERROR: entity missed super game tick\n");
121                a->state = Entity::STATE_IDLE;
122#endif
123            }
124
125    Profiler::Stop(Profiler::STAT_TICK_GAME);
126}
127
128void Ticker::TickRender()
129{
130    Profiler::Start(Profiler::STAT_TICK_RENDER);
131
132    /* Tick objects for the render loop */
133    for (int i = 0; i < Entity::GROUP_COUNT; i++)
134        for (Entity *a = data->list[i]; a; a = a->next)
135            if (!a->destroy)
136            {
137#if !FINAL_RELEASE
138                if (a->state != Entity::STATE_IDLE)
139                    fprintf(stderr, "ERROR: entity not idle for render tick\n");
140                a->state = Entity::STATE_PRETICK_RENDER;
141#endif
142                a->TickRender(data->deltams);
143#if !FINAL_RELEASE
144                if (a->state != Entity::STATE_POSTTICK_RENDER)
145                    fprintf(stderr, "ERROR: entity missed super render tick\n");
146                a->state = Entity::STATE_IDLE;
147#endif
148            }
149
150    Profiler::Stop(Profiler::STAT_TICK_RENDER);
151    Profiler::Start(Profiler::STAT_TICK_BLIT);
152}
153
154void Ticker::ClampFps(float deltams)
155{
156    Profiler::Stop(Profiler::STAT_TICK_BLIT);
157
158    if (deltams > data->bias + 200.0f)
159        deltams = data->bias + 200.0f; // Don't go below 5 fps
160    if (deltams > data->bias)
161        data->timer.WaitMs(deltams - data->bias);
162    data->bias -= deltams;
163}
164
Note: See TracBrowser for help on using the repository browser.