1 /*
2 Copyright (C) 2009 Facundo Domínguez
3
4 This file is part of Spacejunk.
5
6 Spacejunk is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Foobar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Foobar. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef GRAPHIC_H
21 #define GRAPHIC_H
22
23 #include <SDL.h>
24 #include "reference.h"
25 #include "resourcemanager.h"
26
27 #include "vector2d.h"
28
29 #define LOGICAL_WIDTH 640
30 #define LOGICAL_HEIGHT 480
31
32
33 class ImageLoader : public ResourceLoader<SDL_Surface> {
34 std::set<std::string> img_paths;
35 public:
36 SDL_Surface * create(const std::string & id);
37 Parser & parse(Parser & p,std::string * id);
free(SDL_Surface * p)38 void free(SDL_Surface *p) {
39 SDL_FreeSurface(p);
40 };
41 };
42
43 typedef Resource<ImageLoader> RMIMGRef;
44
45 class ImageSetLoader : public ResourceLoaderNonRef<std::pair<Ref<RMIMGRef,delarray>,int> > {
46 std::map<std::string,std::vector<std::string>*> img_sets;
47 public:
48 std::pair<Ref<RMIMGRef,delarray>,int> create(const std::string & id);
49 Parser & parse(Parser & p,std::string * id);
free(std::pair<Ref<RMIMGRef,delarray>,int> & p)50 void free(std::pair<Ref<RMIMGRef,delarray>,int> & p) {
51 p.first=Ref<RMIMGRef,delarray>();
52 };
53 ~ImageSetLoader();
54 };
55
56 typedef ImageSetLoader::ResourceT RMIMGSETRef;
57
getImageSet(const std::string & id)58 inline RMIMGSETRef getImageSet(const std::string & id) {
59 return Singleton<ImageSetLoader>::getInstance()->create(id);
60 }
61
62
63 /**
64 * This class holds all the necesary graphic code for the game.
65 * Classes wich wants to draw themselves onto screen must inherit this
66 * class.
67 *
68 * A Graphic object has an asociated image. This image is rendered on coordinate
69 * system acording to its position (use setPosition to set it).
70 * The postion of an image is the position of its hotspot. The hotspot
71 * is a point specified relative to the upper left corner of the image.
72 * ___________________________________
73 * | |
74 * | X |
75 * | |
76 * | |
77 * |___________________________________|
78 *
79 * We could say here that the hotspot X is at coordinates (1,1) relative
80 * to the upper left corner (0,0).
81 * So if the hotspot is at (30,29) in global coordinates, then the upper
82 * left corner of the image is at (29,28) at global coordinates.
83 *
84 * This class also provides some static methods for managing the graphic system.
85 */
86 class Graphic {
87 private:
88 Ref<SDL_Surface,SDL_FreeSurface> cache;
89 real cache_angle,cache_zoom;
90 SDL_Rect cache_rect;
91 RMIMGSETRef images;
92 RMROTRef rot;
93 private:
94 friend class ZoomRotator;
95 friend class FontRenderer;
96 static float base_scalefactor;
97 static bool updates;
98 static SDL_Surface * screen;
99 static bool fullupdate, alwaysupdate;
100 static void mUpdateRect(SDL_Surface * s,SDL_Rect * r);
101 Uint8 ROT_FLAG;
102
103 protected:
104
105 /** What to draw. */
106 RMIMGRef bmp;
107
108 /**
109 * Creates a graphic without an associated image;
110 * Do not use any drawing method prior to asigning an image to this graphic an its cache.
111 * This constructor is provided for subclases which cannot associate an image at the
112 * begining of constructor execution.
113 */
114 Graphic();
115
116 public:
117 /**
118 * Flags to pass to sdl when setting a video mode.
119 */
120 static Uint32 sdlflags;
121
122 /** Position of the image handle relative to its uper left corner. */
123 Vector2d hotspot;
124
125 /** screen for sdl */
getScreen()126 static SDL_Surface * getScreen() {
127 return screen;
128 };
129
130 static void setScaleFactors();
131 static float getBaseScaleFactorX();
132 static float getBaseScaleFactorY();
133
134 /** screen center, this is used for centering the view of the game
135 * and the level editor.
136 */
137 static Vector2d screencenter;
138 static int screenx;
139 static int screeny;
140 static int screenw;
141 static int screenh;
142
143 /** Converts logical coordinates and lengths to screen coordinates. */
144 static int toScreenx(int x);
145 static int toScreeny(int y);
146 static int toScreenw(int w);
147 static int toScreenh(int h);
148 static int fromScreenx(int x);
149 static int fromScreeny(int y);
150
151 /**
152 * Sets video mode for displaying graphics to a suitable
153 * bitdepth for a resolution of w x h.
154 * If it fails it calls exit(1);
155 */
156 static void set_video_mode(int w, int h);
157
158 /** Sets the palete for the video mode, if it is indexed.
159 */
160 static void setPalette(const std::string & id,int flags=SDL_LOGPAL | SDL_PHYSPAL);
161 static void setPalette(const SDL_Palette * pal);
162 SDL_Palette * getPalette();
163
164 /**
165 * Toggles fullscreen mode.
166 */
167 static void toggleFullscreen();
168 static void updateRect(SDL_Surface * s,SDL_Rect * r);
updateRect(SDL_Rect * r)169 static void updateRect(SDL_Rect * r) {
170 updateRect(getScreen(),r);
171 }
172
173 static void fullUpdate();
isUpdating()174 static bool isUpdating() {
175 return updates;
176 };
177 static void setAlwaysUpdate(bool always);
178
179 /**
180 * Clears the screen taking into account whether it is double buffered.
181 * @param color used to clear the screen.
182 */
183 static void clearScreen(Uint32 color);
184
185 /**
186 * This method indicates we have finish drawing and
187 * we want to flip the buffers.
188 */
189 static void flip(bool full=true);
190
191 /**
192 * toggles updates on or off.
193 */
194 static void toggle_updates(bool on);
195
196 /** Sets the full screen flag. Call set_video_mode after this. */
197 static void setFullscreenFlag(bool full);
198
199 /**
200 * Gets the time since start of program.
201 * @return the amount of miliseconds since program start.
202 */
ticks()203 static unsigned int ticks() {
204 return SDL_GetTicks();
205 }
206
207 /**
208 * Sleeps current thread during the period specified in miliseconds.
209 * @param t the time to sleep.
210 */
sleep(int t)211 static void sleep(int t) {
212 SDL_Delay(t);
213 }
214
215 /**
216 * Draws an arrow in screen coordinates.
217 * @param x1
218 * @param y1
219 * @param x2
220 * @param y2
221 */
222 static void drawArrow(int x1,int y1,int x2,int y2);
223 static void drawArrow(int x1,int y1,int x2,int y2,Uint32 color);
224
225 /**
226 * Draws a circumference.
227 * @param r The radius.
228 * @param center The center in screen coordinates.
229 * @param color The color to use in screen format.
230 */
231 static void drawCircle(Vector2d center,int r,Uint32 color);
232 static void drawRect(Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color);
233 static void drawFilledRect(Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color);
234
235 /**
236 * Draws a circumference around the given graphic.
237 * @param zoom The scaling factor to use over the graphic size.
238 * @param pos The graphic position in screen coordinates.
239 * @param color The color to use in screen format.
240 */
241 void drawSurroundingCircle(Vector2d center,real zoom,Uint32 color);
242
243 /**
244 * Draws a cross around the given graphic.
245 * @param zoom The scaling factor to use over the graphic size.
246 * @param pos The graphic position in screen coordinates.
247 * @param color The color to use in screen format.
248 */
249 void drawSurroundingCross(Vector2d center,real zoom,Uint32 color);
250
251 /**
252 * Loads a graphic from a file.
253 * The hotspot is taken at center of the image.
254 * @param graphicid An identifier of the image to use.
255 * @param cache Use a cache for rotating and zomming the image.
256 * @param isopaque Don't make the image transparent on black regions.
257 */
258 Graphic(const std::string & filepath,bool cache=true,bool isopaque=false,bool prerotate=false);
259
260 /**
261 * This method draws the graphic on to the screen, rotated over its hotspot and
262 * in the given position.
263 * @param pos The position where to put the graphic hotspot in screen coordinates.
264 * @param zoom The zoom factor in which the viewer is looking at.
265 * @param angle How much rotated is the graphic seen from the view point.
266 */
267 void draw(Vector2d pos,real zoom=1,real angle=0);
268 virtual void draw(int x,int y,real zoom=1,real angle=0);
269 virtual void draw(int x,int y,SDL_Rect * r);
270
271 /**
272 * Returns the graphic width.
273 * @return the graphic width.
274 */
275 int getWidth() const;
276
277 /**
278 * Returns the graphic height.
279 * @return the graphic height.
280 */
281 int getHeight() const;
282
283 void setFrame(int i);
getImageCount()284 int getImageCount() {
285 return images.second;
286 };
287
288 /**
289 * Tells whether the pixel at (x,y) has the colorkey color.
290 */
291 bool insideImage(int x,int y) const;
292
293 static SDL_Surface * createSurface(Uint16 w,Uint16 h);
294
295 virtual ~Graphic();
296 };
297
298 class GraphicSeq {
299 private:
300 int sstart,send,remaining,current;
301 int sstep;
302 bool sloop;
303 public:
304 Graphic * seqg;
305 int framestep;
306 bool hold;
307 GraphicSeq(Graphic * g);
308 void setFrameSequence(int start,int end,bool loop,bool forward);
309 void stepSeq(int delta);
310 void nextFrame();
311 };
312
313 class ZoomRotator {
314 private:
315 RMIMGRef img;
316 bool * updated;
317 SDL_Surface ** rot;
318 float zoom;
319 Uint8 ROT_FLAG;
320 public:
321 ZoomRotator(const std::string & id);
322 void draw(int x,int y,float angle,float zoom);
323 ~ZoomRotator();
324 };
325
326
327 /** A loader for Fonts. */
328 class FontLoader : public ResourceLoader<FontRenderer> {
329 private:
330 std::map<std::string,std::string> font_paths;
331 public:
332 FontRenderer * create(const std::string & id);
333 Parser & parse(Parser & p,std::string * id);
free(FontRenderer * p)334 void free(FontRenderer * p) {
335 delete p;
336 };
337 };
338
339 typedef Resource<FontLoader> RMFONTRef;
340
341
342 #define UPDATEbegin {Graphic::toggle_updates(true);
343 #define UPDATEend Graphic::toggle_updates(false);}
344 #define UPDATEOFFbegin {{Graphic::toggle_updates(false);
345 #define UPDATEOFFend Graphic::toggle_updates(true);}}
346 #define UPDATEOFF(code) UPDATEOFFbegin code; UPDATEOFFend
347
348 Uint32 getpixel(SDL_Surface *surface, int x, int y);
349 bool SDLinsideImage(SDL_Surface * surface,int x,int y);
350
351 #endif // GRAPHIC_H
352