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