NXEngine v1.0.0.2
[NXEngine.git] / graphics / graphics.cpp
blob6fdc85295c70c42049bbfcd5dad2f5dffa1064e0
2 // graphics routines
3 #include <SDL/SDL.h>
4 #include <SDL/SDL_getenv.h>
5 #include <stdlib.h>
6 #include "graphics.h"
7 #include "tileset.h"
8 #include "sprites.h"
9 #include "../dirnames.h"
10 #include "graphics.fdh"
12 NXSurface *screen = NULL; // created from SDL's screen
13 static NXSurface *drawtarget = NULL; // target of DrawRect etc; almost always screen
14 int screen_bpp = 16; // the default if we can't get video info
16 const NXColor DK_BLUE(0, 0, 0x21); // the popular dk blue backdrop color
17 const NXColor BLACK(0, 0, 0); // pure black, only works if no colorkey
18 const NXColor CLEAR(0, 0, 0); // the transparent/colorkey color
20 static bool is_fullscreen = false;
21 static int current_res = -1;
23 bool Graphics::init(int resolution)
25 const SDL_VideoInfo *info;
27 // it's faster if we create the SDL screen at the bpp of the real screen.
28 // max fps went from 120 to 160 on my X11 system this way.
29 if ((info = SDL_GetVideoInfo()))
31 stat("videoinfo: desktop bpp %d", info->vfmt->BitsPerPixel);
32 if (info->vfmt->BitsPerPixel > 8)
33 screen_bpp = info->vfmt->BitsPerPixel;
36 if (SetResolution(resolution, false))
37 return 1;
39 if (Tileset::Init())
40 return 1;
42 if (Sprites::Init())
43 return 1;
45 return 0;
48 void Graphics::close()
50 stat("Graphics::Close()");
51 SDL_ShowCursor(true);
55 void c------------------------------() {}
58 bool Graphics::InitVideo()
60 SDL_Surface *sdl_screen;
62 stat("Graphics::InitVideo");
63 if (drawtarget == screen) drawtarget = NULL;
64 if (screen) delete screen;
66 uint32_t flags = SDL_SWSURFACE;
67 if (is_fullscreen) flags |= SDL_FULLSCREEN;
69 putenv((char *)"SDL_VIDEO_CENTERED=1");
71 sdl_screen = SDL_SetVideoMode(SCREEN_WIDTH*SCALE, SCREEN_HEIGHT*SCALE, screen_bpp, flags);
72 if (!sdl_screen)
74 staterr("Graphics::InitVideo: error setting video mode");
75 return 1;
78 SDL_WM_SetCaption("NXEngine", NULL);
79 SDL_ShowCursor(is_fullscreen == false);
81 screen = new NXSurface(sdl_screen, false);
82 if (!drawtarget) drawtarget = screen;
83 return 0;
86 bool Graphics::FlushAll()
88 stat("Graphics::FlushAll()");
89 Sprites::FlushSheets();
90 Tileset::Reload();
91 map_flush_graphics();
92 return font_reload();
95 void Graphics::SetFullscreen(bool enable)
97 if (is_fullscreen != enable)
99 is_fullscreen = enable;
100 InitVideo();
101 Graphics::FlushAll();
105 // change the video mode to one of the available resolution codes, currently:
106 // 0 - 640x480, Fullscreen
107 // 1 - Windowed scale x1 (320x240)
108 // 2 - Windowed scale x2 (640x480)
109 // 3 - Windowed scale x3 (960x720)
110 bool Graphics::SetResolution(int r, bool restoreOnFailure)
112 stat("Graphics::SetResolution(%d)", r);
113 if (r == current_res)
114 return 0;
116 int old_res = current_res;
117 int factor;
119 if (r == 0)
121 is_fullscreen = true;
122 factor = 2;
124 else
126 is_fullscreen = false;
127 factor = r;
130 stat("Setting scaling %d and fullscreen=%s", factor, is_fullscreen ? "yes":"no");
131 NXSurface::SetScale(factor);
133 if (Graphics::InitVideo())
135 staterr("Switch to resolution %d failed!", r);
137 if (restoreOnFailure)
139 staterr("Trying to recover old mode %d.", r, old_res);
140 if (Graphics::SetResolution(old_res, false))
142 staterr("Fatal error: vidmode recovery failed!!!");
146 return 1;
149 if (Graphics::FlushAll()) return 1;
150 return 0;
153 // return a pointer to a null-terminated list of available resolutions.
154 const char **Graphics::GetResolutions()
156 static const char *res_str[] =
158 "Fullscreen",
159 "320x240", "640x480", "960x720",
160 NULL
163 return res_str;
167 void c------------------------------() {}
170 // copy a sprite into the current tileset.
171 // used to obtain the images for the star tiles (breakable blocks),
172 // and for animated motion tiles in Waterway.
173 void Graphics::CopySpriteToTile(int spr, int tileno, int offset_x, int offset_y)
175 NXRect srcrect, dstrect;
177 srcrect.x = (sprites[spr].frame[0].dir[0].sheet_offset.x + offset_x);
178 srcrect.y = (sprites[spr].frame[0].dir[0].sheet_offset.y + offset_y);
179 srcrect.w = TILE_W;
180 srcrect.h = TILE_H;
182 dstrect.x = (tileno % 16) * TILE_W;
183 dstrect.y = (tileno / 16) * TILE_H;
184 dstrect.w = TILE_W;
185 dstrect.h = TILE_H;
187 NXSurface *tileset = Tileset::GetSurface();
188 NXSurface *spritesheet = Sprites::get_spritesheet(sprites[spr].spritesheet);
190 if (tileset && spritesheet)
192 // blank out the old tile data with clear
193 tileset->FillRect(&dstrect, CLEAR);
195 // copy the sprite over
196 BlitSurface(spritesheet, &srcrect, tileset, &dstrect);
201 void Graphics::ShowLoadingScreen()
203 NXSurface loading;
204 char fname[MAXPATHLEN];
206 sprintf(fname, "%s/Loading.pbm", data_dir);
207 if (loading.LoadImage(fname))
208 return;
210 int x = (SCREEN_WIDTH / 2) - (loading.Width() / 2);
211 int y = (SCREEN_HEIGHT / 2) - loading.Height();
213 FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0);
214 DrawSurface(&loading, x, y);
215 drawtarget->Flip();
219 void c------------------------------() {}
222 // blit from one surface to another, just like SDL_BlitSurface.
223 void Graphics::BlitSurface(NXSurface *src, NXRect *srcrect, NXSurface *dst, NXRect *dstrect)
225 dst->DrawSurface(src, dstrect->x, dstrect->y, \
226 srcrect->x, srcrect->y, srcrect->w, srcrect->h);
230 void c------------------------------() {}
233 // draw the entire surface to the screen at the given coordinates.
234 void Graphics::DrawSurface(NXSurface *src, int x, int y)
236 drawtarget->DrawSurface(src, x, y);
240 // blit the specified portion of the surface to the screen
241 void Graphics::DrawSurface(NXSurface *src, \
242 int dstx, int dsty, int srcx, int srcy, int wd, int ht)
244 drawtarget->DrawSurface(src, dstx, dsty, srcx, srcy, wd, ht);
248 // blit the specified surface across the screen in a repeating pattern
249 void Graphics::BlitPatternAcross(NXSurface *sfc, int x_dst, int y_dst, int y_src, int height)
251 drawtarget->BlitPatternAcross(sfc, x_dst, y_dst, y_src, height);
255 void c------------------------------() {}
258 void Graphics::DrawRect(int x1, int y1, int x2, int y2, NXColor color)
260 drawtarget->DrawRect(x1, y1, x2, y2, color);
263 void Graphics::FillRect(int x1, int y1, int x2, int y2, NXColor color)
265 drawtarget->FillRect(x1, y1, x2, y2, color);
268 void Graphics::DrawPixel(int x, int y, NXColor color)
270 drawtarget->DrawPixel(x, y, color);
274 void c------------------------------() {}
277 void Graphics::DrawRect(int x1, int y1, int x2, int y2, uint8_t r, uint8_t g, uint8_t b)
279 drawtarget->DrawRect(x1, y1, x2, y2, r, g, b);
282 void Graphics::FillRect(int x1, int y1, int x2, int y2, uint8_t r, uint8_t g, uint8_t b)
284 drawtarget->FillRect(x1, y1, x2, y2, r, g, b);
287 void Graphics::DrawPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)
289 drawtarget->DrawPixel(x, y, r, g, b);
293 void c------------------------------() {}
296 void Graphics::set_clip_rect(int x, int y, int w, int h)
298 drawtarget->set_clip_rect(x, y, w, h);
301 void Graphics::set_clip_rect(NXRect *rect)
303 drawtarget->set_clip_rect(rect);
306 void Graphics::clear_clip_rect()
308 drawtarget->clear_clip_rect();
312 void c------------------------------() {}
315 // change the target surface of operation like DrawRect to something
316 // other than the screen.
317 void Graphics::SetDrawTarget(NXSurface *surface)
319 drawtarget = surface;