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 &center, 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