1 // Copyright 2005 by Anthony Liekens <anthony@liekens.net>
2 // Copyright 2007 by Robert Schuster <robertschuster@fsfe.org>
3
4 #include <SDL/SDL_gfxPrimitives.h>
5
6 #include "canvas.h"
7
8 #include "extensions.h"
9 #include "coordinate.h"
10 #include "settings.h"
11 #include "fonts.h"
12
13 SDL_Surface* Canvas::main = 0;
14
15 gcn::SDLGraphics *Canvas::sdlGraphics = 0;
16
17 Font* Canvas::font = 0;
18
19 void
alphaBlend(SDL_Surface * surface,Uint8 alpha)20 Canvas::alphaBlend( SDL_Surface* surface, Uint8 alpha ) {
21 if( alpha == 0 ) {
22 for( int x = 0; x < surface->w; x++ )
23 for( int y = 0; y < surface->h; y++ ) {
24 Uint32 *bufp;
25 bufp = (Uint32 *)surface->pixels + y*surface->pitch/4 + x;
26 if( *bufp != 0 )
27 *bufp &= 0x00ffffff;
28 }
29 } if( alpha != 255 ) {
30 for( int x = 0; x < surface->w; x++ )
31 for( int y = 0; y < surface->h; y++ ) {
32 Uint32 *bufp;
33 bufp = (Uint32 *)surface->pixels + y*surface->pitch/4 + x;
34 if( *bufp != 0 ) {
35 // seperate RGB from A, update A for new value, OR them together again
36 Uint32 color = ( *bufp & 0x00ffffff ) | ( ( *bufp >> 24 ) * alpha >> 8 ) << 24;
37 *bufp = color;
38 }
39 }
40 }
41 }
42
43 void
drawSelector(Coordinate & c,Sint16 offset,Sint16 width,Sint16 height,Uint8 R,Uint8 G,Uint8 B)44 Canvas::drawSelector(Coordinate &c, Sint16 offset,
45 Sint16 width, Sint16 height, Uint8 R, Uint8 G, Uint8 B)
46 {
47 int x1 = c.getXMapped() + offset;
48 int y1 = c.getYMapped() + offset;
49
50 hlineRGBA( main, x1, x1 + 2, y1, R, G, B, 255 );
51 hlineRGBA( main, x1 + width - 2, x1 + width, y1, R, G, B, 255 );
52 hlineRGBA( main, x1, x1 + 2, y1 + height, R, G, B, 255 );
53 hlineRGBA( main, x1 + width - 2, x1 + width, y1 + height, R, G, B, 255 );
54 vlineRGBA( main, x1, y1, y1 + 2, R, G, B, 255 );
55 vlineRGBA( main, x1, y1 + height, y1 + height - 2, R, G, B, 255 );
56 vlineRGBA( main, x1 + width, y1, y1 + 2, R, G, B, 255 );
57 vlineRGBA( main, x1 + width, y1 + height, y1 + height - 2, R, G, B, 255 );
58 }
59
60 void
drawNearestPlanetSelector(Coordinate & c,int size)61 Canvas::drawNearestPlanetSelector(Coordinate &c, int size)
62 {
63 size *= 3;
64 int offset = -size/2;
65
66 drawSelector(c, offset, size, size, 255, 0, 0);
67 }
68
69 void
drawPlanet(Coordinate & loc,int size,Uint32 color)70 Canvas::drawPlanet( Coordinate &loc, int size, Uint32 color ) {
71 drawPlanetMapped(loc.getXMapped(), loc.getYMapped(), size, color);
72 }
73
74 void
drawPlanetMapped(int x,int y,int size,Uint32 color)75 Canvas::drawPlanetMapped(int x, int y, int size, Uint32 color ) {
76 int R = getRed(color);
77 int G = getGreen(color);
78 int B = getBlue(color);
79
80 filledCircleRGBA( main, x, y, size + 2, 0, 0, 0, 128 );
81 filledCircleRGBA( main, x, y, size, R, G, B, 255 );
82 aacircleRGBA( main, x, y, size, R, G, B, 255 );
83 filledEllipseRGBA( main, x, y - size / 2, size, size / 2, 255 - 4 * ( 255 - R ) / 5, 255 - 4 * ( 255 - G ) / 5, 255 - 4 * ( 255 - B ) / 5, 255 );
84 aaellipseRGBA( main, x, y - size / 2, size, size / 2, 255 - 4 * ( 255 - R ) / 5, 255 - 4 * ( 255 - G ) / 5, 255 - 4 * ( 255 - B ) / 5, 255 );
85 }
86
87 void
drawResidentShip(Coordinate & shipLocation,Coordinate & planetLocation,int color)88 Canvas::drawResidentShip(Coordinate& shipLocation, Coordinate& planetLocation,
89 int color) {
90 int sx = shipLocation.getXMapped();
91 int sy = shipLocation.getYMapped();
92
93 int px = planetLocation.getXMapped();
94 int py = planetLocation.getYMapped();
95
96 int r = getRed(color);
97 int g = getGreen(color);
98 int b = getBlue(color);
99
100 aalineRGBA(main, sx, sy, px, py, r, g, b, 64);
101 filledCircleRGBA(main, sx, sy, 1, r, g, b, 255);
102 }
103
104 void
drawFlyingShip(Coordinate & shipLocation,double direction,int color)105 Canvas::drawFlyingShip(Coordinate& shipLocation, double direction, int color)
106 {
107 int sx = shipLocation.getXMapped();
108 int sy = shipLocation.getYMapped();
109
110 int r = getRed(color);
111 int g = getGreen(color);
112 int b = getBlue(color);
113
114 int headX, headY;
115 int leftTipX, leftTipY;
116 int rightTipX, rightTipY;
117
118 headX = (int) (sx + 5.0 * cos( direction));
119 headY = (int) (sy + 5.0 * sin( direction));
120 leftTipX = (int) (sx + 2.0 * cos( direction + M_PI / 3.0));
121 leftTipY = (int) (sy + 2.0 * sin( direction + M_PI / 3.0));
122 rightTipX = (int) (sx + 2.0 * cos( direction - M_PI / 3.0));
123 rightTipY = (int) (sy + 2.0 * sin( direction - M_PI / 3.0));
124
125 aalineRGBA(main, leftTipX, leftTipY, headX, headY, r, g, b, 255);
126 aalineRGBA(main, rightTipX, rightTipY, headX, headY, r, g, b, 255);
127 aalineRGBA(main, rightTipX, rightTipY, leftTipX, leftTipY, r, g, b, 255);
128 }
129
130 void
drawSelection(Coordinate & location)131 Canvas::drawSelection(Coordinate& location)
132 {
133 aacircleRGBA(main, location.getXMapped(), location.getYMapped(), 3, 255, 192, 0, 255 );
134 }
135
136 void
drawOrbit(Coordinate & center,double rotationDistance,int color)137 Canvas::drawOrbit(Coordinate ¢er, double rotationDistance, int color)
138 {
139 int r = getRed(color);
140 int g = getGreen(color);
141 int b = getBlue(color);
142
143 aaellipseRGBA(main, center.getXMapped(), center.getYMapped(),
144 (int) (rotationDistance * Settings::getGameWidth()),
145 (int) (rotationDistance * Settings::getGameHeight()),
146 r, g, b, 64);
147 }
148
149 void
drawBuildProgress(Coordinate & location,int size,double percentage)150 Canvas::drawBuildProgress(Coordinate& location, int size, double percentage)
151 {
152 aacircleRGBA( main, location.getXMapped(), location.getYMapped(),
153 (int) (size + 102.5 - percentage),
154 0xff, 0xff, 0xff,
155 (int)( 0.2 * percentage ));
156 }
157
158 void
drawText(int x,int y,const char * msg,int r,int g,int b,int a)159 Canvas::drawText(int x, int y, const char *msg, int r, int g, int b, int a)
160 {
161 font->render(main, x, y, msg, r, g, b, a);
162 }
163
164 void
drawBox(int x,int y,int w,int h,int r,int g,int b)165 Canvas::drawBox(int x, int y, int w, int h, int r, int g, int b)
166 {
167 boxRGBA( main, x, y, w, h, r, g, b, 255 );
168 }
169
170 int
getFontHeight()171 Canvas::getFontHeight()
172 {
173 return font->getHeight();
174 }
175
176 void
drawRadar()177 Canvas::drawRadar()
178 {
179 int radarSteps = 4;
180 Uint32 radarColor = 0xfee190;
181
182 double s = 1.0 / radarSteps;
183 for( int i = 1; i <= radarSteps; i++ ) {
184 aaellipseRGBA( main, Settings::getGameOffsetX() + Settings::getGameWidth() / 2,
185 Settings::getGameHeight() / 2, (int) (i * s * Settings::getGameWidth() / 2),
186 (int)( i * s * Settings::getGameHeight() / 2 ), 144, 225, 144, 64 );
187 }
188 lineRGBA( main,
189 Settings::getGameOffsetX() + Settings::getGameWidth() / 2, 0,
190 Settings::getGameOffsetX() + Settings::getGameWidth() / 2,
191 Settings::getGameHeight(), 255, 225, 144, 64 );
192 lineRGBA( main,
193 Settings::getGameOffsetX(),
194 Settings::getGameHeight() / 2,
195 Settings::getGameOffsetX() + Settings::getGameWidth(),
196 Settings::getGameHeight() / 2, 255, 225, 144, 64 );
197 }
198
199 void
drawSun()200 Canvas::drawSun()
201 {
202 // Sun in the middle
203 Sint16 x0 = Settings::getGameOffsetX() + Settings::getGameWidth() / 2;
204 Sint16 y0 = Settings::getGameHeight() / 2;
205
206 filledTrigonRGBA( main, x0+5, y0, x0-5,y0, x0, y0+15, 255, 205, 0, 255);
207 filledTrigonRGBA( main, x0+5, y0, x0-5,y0, x0, y0-15, 255, 205, 0, 255);
208 filledTrigonRGBA( main, x0+15, y0, x0,y0+5, x0, y0-5, 255, 205, 0, 255);
209 filledTrigonRGBA( main, x0-15, y0, x0,y0+5, x0, y0-5, 255, 205, 0, 255);
210
211 filledTrigonRGBA( main, x0+10, y0-10, x0+5,y0, x0, y0-5, 255, 205, 0, 255);
212 filledTrigonRGBA( main, x0-10, y0-10, x0-5,y0, x0, y0-5, 255, 205, 0, 255);
213 filledTrigonRGBA( main, x0+10, y0+10, x0+5,y0, x0, y0+5, 255, 205, 0, 255);
214 filledTrigonRGBA( main, x0-10, y0+10, x0-5,y0, x0, y0+5, 255, 205, 0, 255);
215
216 filledCircleRGBA( main, x0,y0, 7, 255, 255, 0, 255 );
217 filledCircleRGBA( main, x0,y0, 6, 255, 245, 0, 255 );
218 filledCircleRGBA( main, x0,y0, 5, 255, 225, 0, 255 );
219 filledCircleRGBA( main, x0,y0, 4, 255, 205, 0, 255 );
220 }
221
222 /** Little star drawn in the background.
223 *
224 */
225 void
drawStar(int x,int y,int brightness)226 Canvas::drawStar(int x, int y, int brightness)
227 {
228 pixelRGBA( main, x, y,
229 brightness + rand() % 64,
230 brightness + rand() % 64,
231 brightness + rand() % 64,
232 255 );
233
234 }
235
236 void
drawSonar(Coordinate coord,int size,double percentage,int r,int g,int b,bool circle)237 Canvas::drawSonar(Coordinate coord, int size, double percentage, int r, int g, int b, bool circle)
238 {
239 int x = coord.getXMapped();
240 int y = coord.getYMapped();
241
242 filledCircleRGBA( main, x, y, (int)( size * sin( percentage * M_PI ) ), r, g, b, (int)( ( 255 - 255 * percentage ) * 0.05 ) );
243
244 if( circle )
245 aacircleRGBA( main, x, y, (int)( size * sin( percentage * M_PI ) ), r, g, b, 255 - (int)( 255 * percentage ) );
246
247 }
248
249 void
drawPlayerStat(int size,int index,int previousValue,int currentValue,int r,int g,int b)250 Canvas::drawPlayerStat(int size, int index, int previousValue, int currentValue, int r, int g, int b)
251 {
252 int w = Settings::getScreenWidth();
253 int h = Settings::getScreenHeight();
254
255 aalineRGBA( main, w - size + index - 1, h - previousValue,
256 w - size + index, h - currentValue,
257 r, g, b, index * 2 );
258 }
259
260 void
drawMouseSelection(Coordinate & c1,Coordinate & c2)261 Canvas::drawMouseSelection(Coordinate &c1, Coordinate &c2)
262 {
263 rectangleColor( main, c1.getXMapped(), c1.getYMapped(),
264 c2.getXMapped(), c2.getYMapped(), 0xfee19080 );
265 }
266
267 void
drawCursor(int x,int y)268 Canvas::drawCursor(int x, int y)
269 {
270 aacircleRGBA( main, x,y, 4, 255, 255, 255, 255 );
271 }
272
273 void
initScreen()274 Canvas::initScreen()
275 {
276 if (!sdlGraphics)
277 sdlGraphics = new gcn::SDLGraphics();
278
279 if (!font)
280 font = new Font("font.ttf", 18);
281
282 long flags = SDL_SWSURFACE | SDL_HWSURFACE;
283 if (Settings::getFullscreen())
284 flags |= SDL_FULLSCREEN;
285
286 main = SDL_SetVideoMode( Settings::getScreenWidth(), Settings::getScreenHeight(), 0, flags);
287 sdlGraphics->setTarget(main);
288 }
289
290 void
shutdown()291 Canvas::shutdown()
292 {
293 delete sdlGraphics;
294 SDL_FreeSurface(main);
295 main = NULL;
296 }
297
298 void
updateScreen()299 Canvas::updateScreen()
300 {
301 SDL_Flip(main);
302 }
303
304 gcn::SDLGraphics *
getSDLGraphics()305 Canvas::getSDLGraphics()
306 {
307 return sdlGraphics;
308 }
309