1 #include <time.h>
2 #include <sys/time.h>
3 #include <unistd.h>
4 
5 
6 #include "globals.h"
7 #include "sound.h"
8 #include "netvariables.h"
9 #include "netdata.h"
10 #include "network.h"
11 #include "thread.h"
12 #include "status.h"
13 #include "object.h"
14 #include "ship.h"
15 #include "screen.h"
16 #include "key.h"
17 
18 
19 struct timeval LastTime;
20 struct timeval UpdateTime;
21 
22 
RunFrame()23 void RunFrame()
24 {
25   int i, j, RunTime;
26   struct timezone tz;
27   struct timeval now;
28   float AgeTime;
29 
30   // Play the boom sounds
31   NextBoom--;
32   if (NextBoom == 0) {
33     if (BoomPhase) {
34       playsound(Boom1);
35       BoomPhase = 0;
36     } else {
37       playsound(Boom2);
38       BoomPhase = 1;
39     }
40     NextBoom = BoomDelay;
41   }
42 
43   // Update looping sounds
44   if (Ships[myShip]) {
45     if (!Ships[myShip]->Alive || !Ships[myShip]->Shield) {
46       if (ShieldSoundNum!=-1) {
47         stopsoundinloop(ShieldSoundNum);
48         ShieldSoundNum=-1;
49       }
50     } else {
51       if (KeyValues.ShieldKey && ShieldSoundNum==-1) {
52         ShieldSoundNum=playsoundinloop(ShieldOnSound);
53       }
54     }
55     if (!Ships[myShip]->Alive) {
56       if (ThrustSoundNum!=-1) {
57         stopsoundinloop(ThrustSoundNum);
58         ThrustSoundNum=-1;
59       }
60     } else {
61       if (KeyValues.zForwardKey && ThrustSoundNum==-1) {
62         ThrustSoundNum=playsoundinloop(ThrustSound);
63       }
64     }
65   } else {
66     if (ShieldSoundNum!=-1) {
67       stopsoundinloop(ShieldSoundNum);
68       ShieldSoundNum=-1;
69     }
70     if (ThrustSoundNum!=-1) {
71       stopsoundinloop(ThrustSoundNum);
72       ThrustSoundNum=-1;
73     }
74   }
75 
76   // Display object and ship sprites
77   gettimeofday(&now, &tz);
78 
79   // Send out update every second
80   if (now.tv_sec!=UpdateTime.tv_sec) {
81     SendUpdate();
82     memcpy(&UpdateTime, &now, sizeof(struct timeval));
83   }
84 
85   if (Ships[myShip]) {
86     DrawStatus();
87     for (i=0; i<MAX_PLAYERS; i++) {
88       if (Ships[i] && i!=myShip && Ships[i]->Alive) {
89         DrawObject(Ships[i]);
90       }
91     }
92 
93     InitTransparencyQueue();
94 
95     for (i=0; i<MAX_OBJECTS; i++) {
96       if (Objects[i]) {
97         if (Objects[i]->Type==ASTEROID_TYPE || Objects[i]->Type==SHOT_TYPE || Objects[i]->Type==NUKE_TYPE) {
98           DrawObject(Objects[i]);
99         } else if (Objects[i]->Type==SHIELD_POWERUP_TYPE || Objects[i]->Type==ARMOR_POWERUP_TYPE ||
100                    Objects[i]->Type==NUKE_POWERUP_TYPE || Objects[i]->Type==HYPERWARP_POWERUP_TYPE) {
101           DrawPowerup(Objects[i]);
102           QueueTransparency(&Objects[i]->Position, i, 3);
103         } else if (Objects[i]->Type==NUKE_EXPLOSION_TYPE) {
104           QueueTransparency(&Objects[i]->Position, i, 4);
105         }
106       }
107     }
108 
109     EnableTransparency();
110 
111     for (i=0; i<MAX_OBJECTS; i++) {
112       if (Objects[i]) {
113         if ((Objects[i]->Type==EXPLOSION_TYPE || Objects[i]->Type==BIG_EXPLOSION_TYPE) && Objects[i]->Age < 1.0) {
114           QueueTransparency(&Objects[i]->Position, i, 1);
115         }
116       }
117     }
118 
119     for (i=0; i<MAX_PLAYERS; i++) {
120       if (Ships[i] && i!=myShip && Ships[i]->ShieldOn) {
121         QueueTransparency(&Ships[i]->Position, i, 2);
122       }
123     }
124 
125     DrawTransparencies();
126 
127     DrawCrosshairs();
128 
129     DrawTest();
130 
131     DisableTransparency();
132   }
133 
134 #ifdef DEBUG
135   printf("Game Thread Sleeping\n");
136 #endif
137   pthread_mutex_unlock(&ClientLock);
138   /*
139     We need to sleep to accomplish the following:
140 
141     Make sure that each frame update takes the same amount of time
142     Handle the sound correctly
143     Allow other threads to update the data
144     Not be too much of a CPU hog
145   */
146   RunTime=(now.tv_sec-LastTime.tv_sec)*1000000+(now.tv_usec-LastTime.tv_usec);
147   LastTime.tv_sec=now.tv_sec;
148   LastTime.tv_usec=now.tv_usec;
149 
150   // The Cygwin usleep and gettimeofday functions appear to be broken,
151   // so this is a workaround
152 #ifndef CYGWIN
153   if (RunTime<FRAME_DELAY*1000 && RunTime>0) {
154     usleep(FRAME_DELAY*1000-RunTime);
155     AgeTime=0.15;
156   } else {
157     AgeTime=0.15*((float)RunTime/(float)(FRAME_DELAY*1000));
158   }
159 #else
160   usleep(FRAME_DELAY*1000);
161   AgeTime=0.15;
162 #endif
163   for (i=0; i<MAX_OBJECTS; i++) {
164     if (Objects[i]) {
165       if (Objects[i]->Type==EXPLOSION_TYPE) {
166         Objects[i]->Age+=AgeTime;
167       } else if (Objects[i]->Type==BIG_EXPLOSION_TYPE) {
168         Objects[i]->Age+=AgeTime/6.0;
169       }
170     }
171   }
172 
173   gettimeofday(&LastTime, &tz);
174 
175   pthread_mutex_lock(&ClientLock);
176 #ifdef DEBUG
177   printf("Game Thread Awake\n");
178 #endif
179 }
180