From 19b2a317f1a12c2ba23b8729ae7f9ffe9fc6280a Mon Sep 17 00:00:00 2001 From: AllyTally Date: Sat, 7 Jan 2023 14:28:07 -0400 Subject: [PATCH] Move from surfaces to the SDL render system Ever since VVVVVV was initially ported to C++ in 2.0, it has used surfaces from SDL. The downside is, that's all software rendering. This commit moves most things off of surfaces, and all into GPU, by using textures and SDL_Renderer. Pixel-perfect collision has been kept by keeping a copy of sprites as surfaces. There's plans for pixel-perfect collision to use masks instead of reading pixel data directly, but that's out of scope for this commit. - `graphics.reloadresources()` is now called later in `main`, because textures cannot be created without a renderer. - This commit also removes a bunch of surface functions which are no longer needed. - This also recaches target textures in certain places for d3d9. - graphics.images was converted to a fixed-size array. - fillbox and fillboxabs use SDL_RenderDrawRect instead of drawing an outline using four filled rectangles - Update my name in the credits --- desktop_version/CONTRIBUTORS.txt | 2 +- desktop_version/src/Credits.h | 2 +- desktop_version/src/CustomLevels.cpp | 15 +- desktop_version/src/Editor.cpp | 304 ++--- desktop_version/src/Entity.cpp | 3 +- desktop_version/src/Graphics.cpp | 1228 +++++++++++--------- desktop_version/src/Graphics.h | 107 +- desktop_version/src/GraphicsResources.cpp | 278 ++++- desktop_version/src/GraphicsResources.h | 56 +- desktop_version/src/GraphicsUtil.cpp | 372 +----- desktop_version/src/GraphicsUtil.h | 31 +- desktop_version/src/Input.cpp | 3 - desktop_version/src/KeyPoll.cpp | 1 + desktop_version/src/Logic.cpp | 9 +- desktop_version/src/Map.cpp | 2 +- desktop_version/src/Render.cpp | 142 +-- desktop_version/src/RoomnameTranslator.cpp | 5 +- desktop_version/src/Screen.cpp | 139 +-- desktop_version/src/Screen.h | 9 +- desktop_version/src/Script.cpp | 49 +- desktop_version/src/TowerBG.h | 3 +- desktop_version/src/UtilityClass.h | 9 + desktop_version/src/main.cpp | 52 +- desktop_version/src/preloader.cpp | 12 +- 24 files changed, 1446 insertions(+), 1387 deletions(-) diff --git a/desktop_version/CONTRIBUTORS.txt b/desktop_version/CONTRIBUTORS.txt index 194d015d..f587746b 100644 --- a/desktop_version/CONTRIBUTORS.txt +++ b/desktop_version/CONTRIBUTORS.txt @@ -3,9 +3,9 @@ Contributors (Ordered alphabetically by first name.) +* Alexandra Fox * AlexApps99 (@AlexApps99) * Allison Fleischer (AllisonFleischer) -* AllyTally (@AllyTally) * Brian Callahan (@ibara) * Charlie Bruce (@charliebruce) * Christoph Böhmwalder (@chrboe) diff --git a/desktop_version/src/Credits.h b/desktop_version/src/Credits.h index 299018be..e537d0c2 100644 --- a/desktop_version/src/Credits.h +++ b/desktop_version/src/Credits.h @@ -85,9 +85,9 @@ static const char* patrons[] = { /* CONTRIBUTORS.txt, again listed alphabetically (according to `sort`) by first name * Misa is special; she gets to be listed in C++ credits alongside Ethan */ static const char* githubfriends[] = { + "Alexandra Fox", "AlexApps99", "Allison Fleischer", - "AllyTally", "Brian Callahan", "Charlie Bruce", "Christoph Böhmwalder", diff --git a/desktop_version/src/CustomLevels.cpp b/desktop_version/src/CustomLevels.cpp index 11d9b444..e9feafec 100644 --- a/desktop_version/src/CustomLevels.cpp +++ b/desktop_version/src/CustomLevels.cpp @@ -21,6 +21,7 @@ #include "Localization.h" #include "LocalizationStorage.h" #include "Map.h" +#include "Screen.h" #include "Script.h" #include "UtilityClass.h" #include "Vlogging.h" @@ -1539,7 +1540,11 @@ void customlevelclass::generatecustomminimap(void) map.custommmxsize = 240 - (map.custommmxoff * 2); map.custommmysize = 180 - (map.custommmyoff * 2); - FillRect(graphics.images[12], graphics.getRGB(0, 0, 0)); + // Start drawing the minimap + + SDL_Texture* target = SDL_GetRenderTarget(gameScreen.m_renderer); + graphics.set_render_target(graphics.images[IMAGE_CUSTOMMINIMAP]); + graphics.clear(); // Scan over the map size for (int j2 = 0; j2 < mapheight; j2++) @@ -1587,12 +1592,10 @@ void customlevelclass::generatecustomminimap(void) if (tile >= 1) { // Fill in this pixel - FillRect( - graphics.images[12], + graphics.fill_rect( (i2 * 12 * map.customzoom) + i, (j2 * 9 * map.customzoom) + j, - 1, - 1, + 1, 1, graphics.getRGB(tm, tm, tm) ); } @@ -1600,6 +1603,8 @@ void customlevelclass::generatecustomminimap(void) } } } + + graphics.set_render_target(target); } // Return a graphics-ready color based off of the given tileset and tilecol diff --git a/desktop_version/src/Editor.cpp b/desktop_version/src/Editor.cpp index e831d5d1..9201e82c 100644 --- a/desktop_version/src/Editor.cpp +++ b/desktop_version/src/Editor.cpp @@ -22,6 +22,7 @@ #include "Script.h" #include "UtilityClass.h" #include "VFormat.h" +#include "Vlogging.h" editorclass::editorclass(void) { @@ -281,18 +282,28 @@ static int edentat( int xp, int yp ) static void fillbox(const int x, const int y, const int x2, const int y2, const SDL_Color color) { - FillRect(graphics.backBuffer, x, y, x2-x, 1, color); - FillRect(graphics.backBuffer, x, y2-1, x2-x, 1, color); - FillRect(graphics.backBuffer, x, y, 1, y2-y, color); - FillRect(graphics.backBuffer, x2-1, y, 1, y2-y, color); + graphics.set_color(color); + + const SDL_Rect rect = {x, y, x2 - x, y2 - y}; + + const int result = SDL_RenderDrawRect(gameScreen.m_renderer, &rect); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not render rectangle outline: %s", SDL_GetError())); + } } static void fillboxabs(const int x, const int y, const int x2, const int y2, const SDL_Color color) { - FillRect(graphics.backBuffer, x, y, x2, 1, color); - FillRect(graphics.backBuffer, x, y+y2-1, x2, 1, color); - FillRect(graphics.backBuffer, x, y, 1, y2, color); - FillRect(graphics.backBuffer, x+x2-1, y, 1, y2, color); + graphics.set_color(color); + + const SDL_Rect rect = {x, y, x2, y2}; + + const int result = SDL_RenderDrawRect(gameScreen.m_renderer, &rect); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not render rectangle outline: %s", SDL_GetError())); + } } @@ -492,8 +503,8 @@ void editorrender(void) const RoomProperty* const room = cl.getroomprop(ed.levx, ed.levy); //Draw grid + graphics.clear(); - ClearSurface(graphics.backBuffer); for(int j=0; j<30; j++) { for(int i=0; i<40; i++) @@ -566,12 +577,12 @@ void editorrender(void) //left edge if(ed.freewrap((ed.levx*40)-1,j+(ed.levy*30))==1) { - FillRect(graphics.backBuffer, 0,j*8, 2,8, graphics.getRGB(255 - help.glow, 255, 255)); + graphics.fill_rect(0,j*8, 2,8, graphics.getRGB(255 - help.glow, 255, 255)); } //right edge if(ed.freewrap((ed.levx*40)+40,j+(ed.levy*30))==1) { - FillRect(graphics.backBuffer, 318,j*8, 2,8, graphics.getRGB(255 - help.glow, 255, 255)); + graphics.fill_rect(318,j*8, 2,8, graphics.getRGB(255 - help.glow, 255, 255)); } } @@ -579,12 +590,12 @@ void editorrender(void) { if(ed.freewrap((ed.levx*40)+i,(ed.levy*30)-1)==1) { - FillRect(graphics.backBuffer, i*8,0, 8,2, graphics.getRGB(255 - help.glow, 255, 255)); + graphics.fill_rect(i*8,0, 8,2, graphics.getRGB(255 - help.glow, 255, 255)); } if(ed.freewrap((ed.levx*40)+i,30+(ed.levy*30))==1) { - FillRect(graphics.backBuffer, i*8,238, 8,2, graphics.getRGB(255 - help.glow, 255, 255)); + graphics.fill_rect(i*8,238, 8,2, graphics.getRGB(255 - help.glow, 255, 255)); } } @@ -595,7 +606,6 @@ void editorrender(void) // Special case for drawing gray entities bool custom_gray = room->tileset == 3 && room->tilecol == 6; - const SDL_Color gray_ct = {255, 255, 255, 255}; // Draw entities backward to remain accurate with ingame for (int i = customentities.size() - 1; i >= 0; i--) @@ -613,7 +623,7 @@ void editorrender(void) { ed.entcolreal = graphics.getcol(18); } - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),ed.getenemyframe(room->enemytype),ed.entcolreal); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),ed.getenemyframe(room->enemytype),ed.entcolreal); if(customentities[i].p1==0) graphics.Print((customentities[i].x*8)- (ed.levx*40*8)+4,(customentities[i].y*8)- (ed.levy*30*8)+4, "V", 255, 255, 255 - help.glow, false); if(customentities[i].p1==1) graphics.Print((customentities[i].x*8)- (ed.levx*40*8)+4,(customentities[i].y*8)- (ed.levy*30*8)+4, "^", 255, 255, 255 - help.glow, false); if(customentities[i].p1==2) graphics.Print((customentities[i].x*8)- (ed.levx*40*8)+4,(customentities[i].y*8)- (ed.levy*30*8)+4, "<", 255, 255, 255 - help.glow, false); @@ -621,18 +631,13 @@ void editorrender(void) fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),16,16,graphics.getRGB(255,164,255)); break; case 2: //Threadmills & platforms - if (!INBOUNDS_VEC(obj.customplatformtile, graphics.entcolours)) - { - continue; - } tpoint.x = (customentities[i].x*8)- (ed.levx*40*8); tpoint.y = (customentities[i].y*8)- (ed.levy*30*8); drawRect = graphics.tiles_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; for (int j = 0; j < 4; j++) { - if (custom_gray) BlitSurfaceTinted(graphics.entcolours[obj.customplatformtile],NULL, graphics.backBuffer, &drawRect, gray_ct); - else BlitSurfaceStandard(graphics.entcolours[obj.customplatformtile],NULL, graphics.backBuffer, &drawRect); + graphics.draw_grid_tile(custom_gray ? graphics.grphx.im_entcolours_tint : graphics.grphx.im_entcolours, obj.customplatformtile, drawRect.x, drawRect.y, 8, 8); drawRect.x += 8; } @@ -664,8 +669,7 @@ void editorrender(void) drawRect.x += tpoint.x; drawRect.y += tpoint.y; for (int j = 0; j < 4; j++) { - if (custom_gray) BlitSurfaceTinted(graphics.entcolours[obj.customplatformtile],NULL, graphics.backBuffer, &drawRect, gray_ct); - else BlitSurfaceStandard(graphics.entcolours[obj.customplatformtile],NULL, graphics.backBuffer, &drawRect); + graphics.draw_grid_tile(custom_gray ? graphics.grphx.im_entcolours_tint : graphics.grphx.im_entcolours, obj.customplatformtile, drawRect.x, drawRect.y, 8, 8); drawRect.x += 8; } } @@ -682,18 +686,13 @@ void editorrender(void) } break; case 3: //Disappearing Platform - if (!INBOUNDS_VEC(obj.customplatformtile, graphics.entcolours)) - { - continue; - } tpoint.x = (customentities[i].x*8)- (ed.levx*40*8); tpoint.y = (customentities[i].y*8)- (ed.levy*30*8); drawRect = graphics.tiles_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; for (int j = 0; j < 4; j++) { - if (custom_gray) BlitSurfaceTinted(graphics.entcolours[obj.customplatformtile],NULL, graphics.backBuffer, &drawRect, gray_ct); - else BlitSurfaceStandard(graphics.entcolours[obj.customplatformtile],NULL, graphics.backBuffer, &drawRect); + graphics.draw_grid_tile(custom_gray ? graphics.grphx.im_entcolours_tint : graphics.grphx.im_entcolours, obj.customplatformtile, drawRect.x, drawRect.y, 8, 8); drawRect.x += 8; } @@ -701,11 +700,11 @@ void editorrender(void) fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),32,8,graphics.getRGB(255,255,255)); break; case 9: //Shiny Trinket - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),22,196,196,196); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),22,196,196,196); fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),16,16,graphics.getRGB(255, 164, 164)); break; case 10: //Checkpoints - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),20 + customentities[i].p1,196,196,196); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),20 + customentities[i].p1,196,196,196); fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),16,16,graphics.getRGB(255, 164, 164)); break; case 11: //Gravity lines @@ -714,7 +713,7 @@ void editorrender(void) int tx = customentities[i].p2; int tx2 = tx + customentities[i].p3/8; int ty = customentities[i].y % 30; - FillRect(graphics.backBuffer, (tx*8),(ty*8)+4, (tx2-tx)*8,1, graphics.getRGB(194,194,194)); + graphics.fill_rect((tx*8),(ty*8)+4, (tx2-tx)*8,1, graphics.getRGB(194,194,194)); fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),8,8,graphics.getRGB(164,255,164)); } else //Vertical @@ -722,12 +721,12 @@ void editorrender(void) int tx = customentities[i].x % 40; int ty = customentities[i].p2; int ty2 = ty + customentities[i].p3/8; - FillRect(graphics.backBuffer, (tx*8)+3,(ty*8), 1,(ty2-ty)*8, graphics.getRGB(194,194,194)); + graphics.fill_rect((tx*8)+3,(ty*8), 1,(ty2-ty)*8, graphics.getRGB(194,194,194)); fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),8,8,graphics.getRGB(164,255,164)); } break; case 13://Warp tokens - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),18+(ed.entframe%2),196,196,196); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),18+(ed.entframe%2),196,196,196); fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),16,16,graphics.getRGB(255, 164, 164)); if (i == edent_under_cursor) { @@ -740,18 +739,18 @@ void editorrender(void) } break; case 15: //Crewmates - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8)-4,(customentities[i].y*8)- (ed.levy*30*8),144,graphics.crewcolourreal(customentities[i].p1)); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8)-4,(customentities[i].y*8)- (ed.levy*30*8),144,graphics.crewcolourreal(customentities[i].p1)); fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),16,24,graphics.getRGB(164,164,164)); break; case 16: //Start { if(customentities[i].p1==0) //Left { - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8)-4,(customentities[i].y*8)- (ed.levy*30*8),0,graphics.col_crewcyan); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8)-4,(customentities[i].y*8)- (ed.levy*30*8),0,graphics.col_crewcyan); } else if(customentities[i].p1==1) { - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8)-4,(customentities[i].y*8)- (ed.levy*30*8),3,graphics.col_crewcyan); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8)-4,(customentities[i].y*8)- (ed.levy*30*8),3,graphics.col_crewcyan); } fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),16,24,graphics.getRGB(255, 255, 164)); short labelcol = ed.entframe<2 ? 255 : 196; @@ -790,7 +789,7 @@ void editorrender(void) usethistile = 0; // Flipped; usethisy -= 8; } - graphics.drawsprite((customentities[i].x*8)- (ed.levx*40*8), usethisy + 8, usethistile + 16, 96,96,96); + graphics.draw_sprite((customentities[i].x*8)- (ed.levx*40*8), usethisy + 8, usethistile + 16, 96,96,96); fillboxabs((customentities[i].x*8)- (ed.levx*40*8),(customentities[i].y*8)- (ed.levy*30*8),16,24,graphics.getRGB(164,164,164)); if (i == edent_under_cursor) { @@ -862,7 +861,7 @@ void editorrender(void) { if (customentities[i].p1 / 40 == ed.levx && customentities[i].p2 / 30 == ed.levy) { - graphics.drawsprite((customentities[i].p1*8)- (ed.levx*40*8),(customentities[i].p2*8)- (ed.levy*30*8),18+(ed.entframe%2),64,64,64); + graphics.draw_sprite((customentities[i].p1*8)- (ed.levx*40*8),(customentities[i].p2*8)- (ed.levy*30*8),18+(ed.entframe%2),64,64,64); fillboxabs((customentities[i].p1*8)- (ed.levx*40*8),(customentities[i].p2*8)- (ed.levy*30*8),16,16,graphics.getRGB(96, 64, 64)); if(ed.tilex+(ed.levx*40)==customentities[i].p1 && ed.tiley+(ed.levy*30)==customentities[i].p2) { @@ -922,11 +921,12 @@ void editorrender(void) //Draw ghosts (spooky!) if (game.ghostsenabled) { - ClearSurface(graphics.ghostbuffer); + graphics.set_render_target(graphics.ghostTexture); + graphics.set_blendmode(graphics.ghostTexture, SDL_BLENDMODE_BLEND); + graphics.clear(0, 0, 0, 0); for (int i = 0; i < (int)ed.ghosts.size(); i++) { if (i <= ed.currentghosts) { // We don't want all of them to show up at once :) - if (ed.ghosts[i].rx != ed.levx || ed.ghosts[i].ry != ed.levy - || !INBOUNDS_VEC(ed.ghosts[i].frame, graphics.sprites)) + if (ed.ghosts[i].rx != ed.levx || ed.ghosts[i].ry != ed.levy) continue; point tpoint; tpoint.x = ed.ghosts[i].x; @@ -937,10 +937,12 @@ void editorrender(void) SDL_Rect drawRect = graphics.sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - BlitSurfaceColoured(graphics.sprites[ed.ghosts[i].frame],NULL, graphics.ghostbuffer, &drawRect, ct); + graphics.draw_sprite(drawRect.x, drawRect.y, ed.ghosts[i].frame, ct); } } - SDL_BlitSurface(graphics.ghostbuffer, NULL, graphics.backBuffer, NULL); + graphics.set_render_target(graphics.gameTexture); + graphics.set_texture_alpha_mod(graphics.ghostTexture, 128); + graphics.copy_texture(graphics.ghostTexture, NULL, NULL); } //Draw Cursor @@ -1026,11 +1028,19 @@ void editorrender(void) //Draw five lines of the editor const int temp = ed.dmtile - (ed.dmtile % 40) - 80; - FillRect(graphics.backBuffer, 0,-t2,320,40, graphics.getRGB(0,0,0)); - FillRect(graphics.backBuffer, 0,-t2+40,320,2, graphics.getRGB(255,255,255)); - if(room->tileset==0) + graphics.fill_rect(0,-t2,320,40, graphics.getRGB(0,0,0)); + graphics.fill_rect(0,-t2+40,320,2, graphics.getRGB(255,255,255)); + + int texturewidth; + int textureheight; + + if (room->tileset == 0) { - const int numtiles = (((int) graphics.tiles.size()) / 40) * 40; + if (graphics.query_texture(graphics.grphx.im_tiles, NULL, NULL, &texturewidth, &textureheight) != 0) + { + return; + } + const int numtiles = (int) (texturewidth / 8) * (textureheight / 8); for(int i=0; i<40; i++) { @@ -1043,7 +1053,11 @@ void editorrender(void) } else { - const int numtiles = (((int) graphics.tiles2.size()) / 40) * 40; + if (graphics.query_texture(graphics.grphx.im_tiles2, NULL, NULL, &texturewidth, &textureheight) != 0) + { + return; + } + const int numtiles = (int) (texturewidth / 8) * (textureheight / 8); for(int i=0; i<40; i++) { @@ -1064,8 +1078,8 @@ void editorrender(void) short labellen = 2 + graphics.len(loc::gettext("Tile:")); graphics.bprint(2, 45-t2, loc::gettext("Tile:"), 196, 196, 255 - help.glow, false); graphics.bprint(labellen+16, 45-t2, help.String(ed.dmtile), 196, 196, 255 - help.glow, false); - FillRect(graphics.backBuffer, labellen+2,44-t2,10,10, graphics.getRGB(255 - help.glow, 196, 196)); - FillRect(graphics.backBuffer, labellen+3,45-t2,8,8, graphics.getRGB(0,0,0)); + graphics.fill_rect(labellen+2,44-t2,10,10, graphics.getRGB(255 - help.glow, 196, 196)); + graphics.fill_rect(labellen+3,45-t2,8,8, graphics.getRGB(0,0,0)); if(room->tileset==0) { @@ -1081,8 +1095,8 @@ void editorrender(void) short labellen = 2 + graphics.len(loc::gettext("Tile:")); graphics.bprint(2, 12, loc::gettext("Tile:"), 196, 196, 255 - help.glow, false); graphics.bprint(labellen+16, 12, help.String(ed.dmtile), 196, 196, 255 - help.glow, false); - FillRect(graphics.backBuffer, labellen+2,11,10,10, graphics.getRGB(255 - help.glow, 196, 196)); - FillRect(graphics.backBuffer, labellen+3,12,8,8, graphics.getRGB(0,0,0)); + graphics.fill_rect(labellen+2,11,10,10, graphics.getRGB(255 - help.glow, 196, 196)); + graphics.fill_rect(labellen+3,12,8,8, graphics.getRGB(0,0,0)); if(room->tileset==0) { @@ -1143,16 +1157,16 @@ void editorrender(void) message = graphics.string_wordwrap(message, 312, &lines); short textheight = 8*lines; - FillRect(graphics.backBuffer, 0,238-textheight,320,240, graphics.getRGB(32,32,32)); - FillRect(graphics.backBuffer, 0,239-textheight,320,240, graphics.getRGB(0,0,0)); + graphics.fill_rect(0,238-textheight,320,240, graphics.getRGB(32,32,32)); + graphics.fill_rect(0,239-textheight,320,240, graphics.getRGB(0,0,0)); graphics.PrintWrap(4, 240-textheight, message, 255,255,255, false, 8, 312); } else if(ed.scripteditmod) { //Elaborate C64 BASIC menu goes here! - FillRect(graphics.backBuffer, 0,0,320,240, graphics.getRGB(123, 111, 218)); - FillRect(graphics.backBuffer, 14,16,292,208, graphics.getRGB(61, 48, 162)); + graphics.fill_rect(0,0,320,240, graphics.getRGB(123, 111, 218)); + graphics.fill_rect(14,16,292,208, graphics.getRGB(61, 48, 162)); switch(ed.scripthelppage) { case 0: @@ -1189,7 +1203,7 @@ void editorrender(void) case 1: { //Current scriptname - FillRect(graphics.backBuffer, 14,226,292,12, graphics.getRGB(61, 48, 162)); + graphics.fill_rect(14,226,292,12, graphics.getRGB(61, 48, 162)); char namebuffer[SCREEN_WIDTH_CHARS + 1]; vformat_buf( namebuffer, sizeof(namebuffer), @@ -1223,7 +1237,7 @@ void editorrender(void) } else { - ClearSurface(graphics.backBuffer); + graphics.clear(); } int tr = graphics.titlebg.r - (help.glow / 4) - int(fRandom() * 4); @@ -1245,8 +1259,8 @@ void editorrender(void) std::string wrapped = graphics.string_wordwrap(ed.textdesc, 312, &lines); short textheight = 8*lines+8; - FillRect(graphics.backBuffer, 0, 238-textheight, 320, 240, graphics.getRGB(32, 32, 32)); - FillRect(graphics.backBuffer, 0, 239-textheight, 320, 240, graphics.getRGB(0, 0, 0)); + graphics.fill_rect(0, 238-textheight, 320, 240, graphics.getRGB(32, 32, 32)); + graphics.fill_rect(0, 239-textheight, 320, 240, graphics.getRGB(0, 0, 0)); graphics.PrintWrap(4, 240-textheight, wrapped, 255, 255, 255, false, 8, 312); std::string input = key.keybuffer; if (ed.entframe < 2) @@ -1262,8 +1276,8 @@ void editorrender(void) else if(ed.warpmod) { //placing warp token - FillRect(graphics.backBuffer, 0,221,320,240, graphics.getRGB(32,32,32)); - FillRect(graphics.backBuffer, 0,222,320,240, graphics.getRGB(0,0,0)); + graphics.fill_rect(0,221,320,240, graphics.getRGB(32,32,32)); + graphics.fill_rect(0,222,320,240, graphics.getRGB(0,0,0)); graphics.Print(4, 224, loc::gettext("Left click to place warp destination"), 196, 196, 255 - help.glow, false); graphics.Print(4, 232, loc::gettext("Right click to cancel"), 196, 196, 255 - help.glow, false); } @@ -1271,8 +1285,8 @@ void editorrender(void) { if(ed.spacemod) { - FillRect(graphics.backBuffer, 0,208,320,240, graphics.getRGB(32,32,32)); - FillRect(graphics.backBuffer, 0,209,320,240, graphics.getRGB(0,0,0)); + graphics.fill_rect(0,208,320,240, graphics.getRGB(32,32,32)); + graphics.fill_rect(0,209,320,240, graphics.getRGB(0,0,0)); //Draw little icons for each thingy int tx=6, ty=211, tg=32; @@ -1281,9 +1295,9 @@ void editorrender(void) { for(int i=0; i<10; i++) { - FillRect(graphics.backBuffer, 4+(i*tg), 209,20,20,graphics.getRGB(32,32,32)); + graphics.fill_rect(4+(i*tg), 209,20,20,graphics.getRGB(32,32,32)); } - FillRect(graphics.backBuffer, 4+(ed.drawmode*tg), 209,20,20,graphics.getRGB(64,64,64)); + graphics.fill_rect(4+(ed.drawmode*tg), 209,20,20,graphics.getRGB(64,64,64)); //0: graphics.drawtile(tx,ty,83); graphics.drawtile(tx+8,ty,83); @@ -1300,10 +1314,10 @@ void editorrender(void) graphics.drawtile(tx+4,ty+4,8); //3: tx+=tg; - graphics.drawsprite(tx,ty,22,196,196,196); + graphics.draw_sprite(tx,ty,22,196,196,196); //4: tx+=tg; - graphics.drawsprite(tx,ty,21,196,196,196); + graphics.draw_sprite(tx,ty,21,196,196,196); //5: tx+=tg; graphics.drawtile(tx,ty+4,3); @@ -1318,10 +1332,10 @@ void editorrender(void) graphics.drawtile(tx+8,ty+4,1); //8: tx+=tg; - graphics.drawsprite(tx,ty,78+ed.entframe,196,196,196); + graphics.draw_sprite(tx,ty,78+ed.entframe,196,196,196); //9: tx+=tg; - FillRect(graphics.backBuffer, tx+2,ty+8,12,1,graphics.getRGB(255,255,255)); + graphics.fill_rect(tx+2,ty+8,12,1,graphics.getRGB(255,255,255)); for (int i = 0; i < 10; i++) { @@ -1339,9 +1353,9 @@ void editorrender(void) { for(int i=0; i<7; i++) { - FillRect(graphics.backBuffer, 4+(i*tg), 209,20,20,graphics.getRGB(32,32,32)); + graphics.fill_rect(4+(i*tg), 209,20,20,graphics.getRGB(32,32,32)); } - FillRect(graphics.backBuffer, 4+((ed.drawmode-10)*tg), 209,20,20,graphics.getRGB(64,64,64)); + graphics.fill_rect(4+((ed.drawmode-10)*tg), 209,20,20,graphics.getRGB(64,64,64)); //10: graphics.Print(tx,ty,"A",196, 196, 255 - help.glow, false); graphics.Print(tx+8,ty,"B",196, 196, 255 - help.glow, false); @@ -1349,22 +1363,22 @@ void editorrender(void) graphics.Print(tx+8,ty+8,"D",196, 196, 255 - help.glow, false); //11: tx+=tg; - graphics.drawsprite(tx,ty,17,196,196,196); + graphics.draw_sprite(tx,ty,17,196,196,196); //12: tx+=tg; fillboxabs(tx+4,ty+4,8,8,graphics.getRGB(96,96,96)); //13: tx+=tg; - graphics.drawsprite(tx,ty,18+(ed.entframe%2),196,196,196); + graphics.draw_sprite(tx,ty,18+(ed.entframe%2),196,196,196); //14: tx+=tg; - FillRect(graphics.backBuffer, tx+6,ty+2,4,12,graphics.getRGB(255,255,255)); + graphics.fill_rect(tx+6,ty+2,4,12,graphics.getRGB(255,255,255)); //15: tx+=tg; - graphics.drawsprite(tx,ty,186,graphics.col_crewblue); + graphics.draw_sprite(tx,ty,186,graphics.col_crewblue); //16: tx+=tg; - graphics.drawsprite(tx,ty,184,graphics.col_crewcyan); + graphics.draw_sprite(tx,ty,184,graphics.col_crewcyan); for (int i = 0; i < 7; i++) { @@ -1446,30 +1460,27 @@ void editorrender(void) break; } int toolnamelen = graphics.len(toolname); - FillRect(graphics.backBuffer, 0,197,toolnamelen+8,11, graphics.getRGB(32,32,32)); - FillRect(graphics.backBuffer, 0,198,toolnamelen+7,10, graphics.getRGB(0,0,0)); + graphics.fill_rect(0,197,toolnamelen+8,11, graphics.getRGB(32,32,32)); + graphics.fill_rect(0,198,toolnamelen+7,10, graphics.getRGB(0,0,0)); graphics.bprint(2,199, toolname, 196, 196, 255 - help.glow); - FillRect(graphics.backBuffer, 260,197,80,11, graphics.getRGB(32,32,32)); - FillRect(graphics.backBuffer, 261,198,80,10, graphics.getRGB(0,0,0)); + graphics.fill_rect(260,197,80,11, graphics.getRGB(32,32,32)); + graphics.fill_rect(261,198,80,10, graphics.getRGB(0,0,0)); graphics.bprint(268,199, "("+help.String(ed.levx+1)+","+help.String(ed.levy+1)+")",196, 196, 255 - help.glow, false); } else { - //FillRect(graphics.backBuffer, 0,230,72,240, graphics.RGB(32,32,32)); - //FillRect(graphics.backBuffer, 0,231,71,240, graphics.RGB(0,0,0)); + //graphics.fill_rect(0,230,72,240, graphics.RGB(32,32,32)); + //graphics.fill_rect(0,231,71,240, graphics.RGB(0,0,0)); if(room->roomname!="") { - if (graphics.translucentroomname) - { - graphics.footerrect.y = 230+ed.roomnamehide; - SDL_BlitSurface(graphics.footerbuffer, NULL, graphics.backBuffer, &graphics.footerrect); - } - else - { - FillRect(graphics.backBuffer, 0,230+ed.roomnamehide,320,10, graphics.getRGB(0,0,0)); - } + graphics.footerrect.y = 230 + ed.roomnamehide; + + graphics.set_blendmode(SDL_BLENDMODE_BLEND); + graphics.fill_rect(&graphics.footerrect, graphics.getRGBA(0, 0, 0, graphics.translucentroomname ? 127 : 255)); + graphics.set_blendmode(SDL_BLENDMODE_NONE); + graphics.bprint(5,231+ed.roomnamehide,room->roomname, 196, 196, 255 - help.glow, true); graphics.bprint(4, 222, loc::gettext("SPACE ^ SHIFT ^"), 196, 196, 255 - help.glow, false); graphics.bprint(268,222, "("+help.String(ed.levx+1)+","+help.String(ed.levy+1)+")",196, 196, 255 - help.glow, false); @@ -1505,12 +1516,12 @@ void editorrender(void) } fillboxabs(0, 117,menuwidth+17,140,graphics.getRGB(64,64,64)); - FillRect(graphics.backBuffer, 0,118,menuwidth+16,140, graphics.getRGB(0,0,0)); + graphics.fill_rect(0,118,menuwidth+16,140, graphics.getRGB(0,0,0)); for (size_t i = 0; i < SDL_arraysize(shiftmenuoptions); i++) graphics.Print(4, 120+i*10, shiftmenuoptions[i], 164,164,164,false); fillboxabs(220, 207,100,60,graphics.getRGB(64,64,64)); - FillRect(graphics.backBuffer, 221,208,160,60, graphics.getRGB(0,0,0)); + graphics.fill_rect(221,208,160,60, graphics.getRGB(0,0,0)); graphics.Print(224, 210, loc::gettext("S: Save Map"),164,164,164,false); graphics.Print(224, 220, loc::gettext("L: Load Map"),164,164,164,false); } @@ -1584,8 +1595,8 @@ void editorrender(void) short banner_y = 120 - textheight/2 - 5; float alpha = graphics.lerp(ed.oldnotedelay, ed.notedelay); - FillRect(graphics.backBuffer, 0, banner_y, 320, 10+textheight, graphics.getRGB(92,92,92)); - FillRect(graphics.backBuffer, 0, banner_y+1, 320, 8+textheight, graphics.getRGB(0,0,0)); + graphics.fill_rect(0, banner_y, 320, 10+textheight, graphics.getRGB(92,92,92)); + graphics.fill_rect(0, banner_y+1, 320, 8+textheight, graphics.getRGB(0,0,0)); graphics.PrintWrap(0,banner_y+5, wrapped, 196-((45.0f-alpha)*4), 196-((45.0f-alpha)*4), 196-((45.0f-alpha)*4), true); } @@ -1857,14 +1868,13 @@ static void editormenuactionpress(void) break; case 4: //Load level - ed.settingsmod=false; - graphics.backgrounddrawn=false; + ed.settingsmod = false; map.nexttowercolour(); ed.keydelay = 6; ed.getlin(TEXT_LOAD, loc::gettext("Enter map filename to load:"), &(ed.filename)); - game.mapheld=true; - graphics.backgrounddrawn=false; + game.mapheld = true; + graphics.backgrounddrawn = false; break; case 5: //Save level @@ -1873,8 +1883,8 @@ static void editormenuactionpress(void) ed.keydelay = 6; ed.getlin(TEXT_SAVE, loc::gettext("Enter map filename to save as:"), &(ed.filename)); - game.mapheld=true; - graphics.backgrounddrawn=false; + game.mapheld = true; + graphics.backgrounddrawn = false; break; case 6: /* Game options */ @@ -1938,14 +1948,15 @@ static void editormenuactionpress(void) ed.keydelay = 6; ed.getlin(TEXT_SAVE, loc::gettext("Enter map filename to save as:"), &(ed.filename)); - game.mapheld=true; - graphics.backgrounddrawn=false; + game.mapheld = true; + graphics.backgrounddrawn = false; break; case 1: //Quit without saving music.playef(11); music.fadeout(); graphics.fademode = FADE_START_FADEOUT; + graphics.backgrounddrawn = false; break; case 2: //Go back to editor @@ -2076,7 +2087,6 @@ void editorinput(void) { ed.settingsmod = true; } - graphics.backgrounddrawn=false; if (ed.settingsmod) { @@ -2540,15 +2550,26 @@ void editorinput(void) else if (key.keymap[SDLK_LCTRL] || key.keymap[SDLK_RCTRL]) { // Ctrl modifiers - int numtiles; + int texturewidth; + int textureheight; + if (cl.getroomprop(ed.levx, ed.levy)->tileset == 0) { - numtiles = (((int) graphics.tiles.size()) / 40) * 40; + if (graphics.query_texture(graphics.grphx.im_tiles, NULL, NULL, &texturewidth, &textureheight) != 0) + { + return; + } } else { - numtiles = (((int) graphics.tiles2.size()) / 40) * 40; + if (graphics.query_texture(graphics.grphx.im_tiles2, NULL, NULL, &texturewidth, &textureheight) != 0) + { + return; + } } + + const int numtiles = (int) (texturewidth / 8) * (textureheight / 8); + ed.dmtileeditor=10; if(left_pressed) { @@ -2583,13 +2604,11 @@ void editorinput(void) if (key.keymap[SDLK_F1]) { ed.switch_tileset(true); - graphics.backgrounddrawn = false; ed.keydelay = 6; } if (key.keymap[SDLK_F2]) { ed.switch_tilecol(true); - graphics.backgrounddrawn = false; ed.keydelay = 6; } if (key.keymap[SDLK_F3]) @@ -2600,7 +2619,6 @@ void editorinput(void) if (key.keymap[SDLK_w]) { ed.switch_warpdir(true); - graphics.backgrounddrawn = false; ed.keydelay = 6; } @@ -2659,13 +2677,11 @@ void editorinput(void) if(key.keymap[SDLK_F1]) { ed.switch_tileset(false); - graphics.backgrounddrawn = false; ed.keydelay = 6; } if(key.keymap[SDLK_F2]) { ed.switch_tilecol(false); - graphics.backgrounddrawn = false; ed.keydelay = 6; } if(key.keymap[SDLK_F3]) @@ -2703,11 +2719,11 @@ void editorinput(void) cl.setroomdirectmode(ed.levx, ed.levy, 1); ed.note=loc::gettext("Direct Mode Enabled"); } - graphics.backgrounddrawn=false; + graphics.backgrounddrawn = false; - ed.notedelay=45; - ed.updatetiles=true; - ed.keydelay=6; + ed.notedelay = 45; + ed.updatetiles = true; + ed.keydelay = 6; } if(key.keymap[SDLK_1]) ed.drawmode=0; if(key.keymap[SDLK_2]) ed.drawmode=1; @@ -2730,7 +2746,6 @@ void editorinput(void) if(key.keymap[SDLK_w]) { ed.switch_warpdir(false); - graphics.backgrounddrawn = false; ed.keydelay = 6; } if(key.keymap[SDLK_e]) @@ -2848,7 +2863,6 @@ void editorinput(void) } music.haltdasmusik(); - graphics.backgrounddrawn=false; ed.returneditoralpha = 1000; // Let's start it higher than 255 since it gets clamped ed.oldreturneditoralpha = 1000; script.startgamemode(Start_EDITORPLAYTESTING); @@ -2891,45 +2905,45 @@ void editorinput(void) if(up_pressed) { - ed.keydelay=6; - graphics.backgrounddrawn=false; + ed.keydelay = 6; ed.levy--; - ed.updatetiles=true; - ed.changeroom=true; + ed.updatetiles = true; + ed.changeroom = true; + graphics.backgrounddrawn = false; } else if(down_pressed) { - ed.keydelay=6; - graphics.backgrounddrawn=false; + ed.keydelay = 6; ed.levy++; - ed.updatetiles=true; - ed.changeroom=true; + ed.updatetiles = true; + ed.changeroom = true; + graphics.backgrounddrawn = false; } else if(left_pressed) { - ed.keydelay=6; - graphics.backgrounddrawn=false; + ed.keydelay = 6; ed.levx--; - ed.updatetiles=true; - ed.changeroom=true; + ed.updatetiles = true; + ed.changeroom = true; + graphics.backgrounddrawn = false; } else if(right_pressed) { - ed.keydelay=6; - graphics.backgrounddrawn=false; + ed.keydelay = 6; ed.levx++; - ed.updatetiles=true; - ed.changeroom=true; + ed.updatetiles = true; + ed.changeroom = true; + graphics.backgrounddrawn = false; } - if(ed.levx<0) ed.levx+=cl.mapwidth; - if(ed.levx>= cl.mapwidth) ed.levx-=cl.mapwidth; - if(ed.levy<0) ed.levy+=cl.mapheight; - if(ed.levy>=cl.mapheight) ed.levy-=cl.mapheight; - if(key.keymap[SDLK_SPACE]) + if (ed.levx < 0) ed.levx += cl.mapwidth; + if (ed.levx >= cl.mapwidth) ed.levx -= cl.mapwidth; + if (ed.levy < 0) ed.levy += cl.mapheight; + if (ed.levy >= cl.mapheight) ed.levy -= cl.mapheight; + if (key.keymap[SDLK_SPACE]) { ed.spacemod = !ed.spacemod; - ed.keydelay=6; + ed.keydelay = 6; } } @@ -4248,6 +4262,8 @@ void editorclass::switch_tileset(const bool reversed) note = buffer; notedelay = 45; updatetiles = true; + + graphics.backgrounddrawn = false; } void editorclass::switch_tilecol(const bool reversed) @@ -4270,6 +4286,8 @@ void editorclass::switch_tilecol(const bool reversed) notedelay = 45; note = loc::gettext("Tileset Colour Changed"); updatetiles = true; + + graphics.backgrounddrawn = false; } void editorclass::clamp_tilecol(const int rx, const int ry, const bool wrap) @@ -4381,6 +4399,8 @@ void editorclass::switch_warpdir(const bool reversed) } notedelay = 45; + + graphics.backgrounddrawn = false; } #endif /* NO_CUSTOM_LEVELS and NO_EDITOR */ diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index 6ac1d4d2..912213bd 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -4785,7 +4785,8 @@ void entityclass::collisioncheck(int i, int j, bool scm /*= false*/) colpoint2.y = entities[j].yp; int drawframe1 = entities[i].collisiondrawframe; int drawframe2 = entities[j].drawframe; - std::vector& spritesvec = graphics.flipmode ? graphics.flipsprites : graphics.sprites; + + std::vector& spritesvec = graphics.flipmode ? graphics.flipsprites_surf : graphics.sprites_surf; if (INBOUNDS_VEC(drawframe1, spritesvec) && INBOUNDS_VEC(drawframe2, spritesvec) && graphics.Hitest(spritesvec[drawframe1], colpoint1, spritesvec[drawframe2], colpoint2)) diff --git a/desktop_version/src/Graphics.cpp b/desktop_version/src/Graphics.cpp index 7aa0d470..a5ed0b0c 100644 --- a/desktop_version/src/Graphics.cpp +++ b/desktop_version/src/Graphics.cpp @@ -29,7 +29,6 @@ void Graphics::init(void) setRect(prect, 0, 0, 4, 4); setRect(line_rect, 0,0,0,0); setRect(tele_rect,0,0,96,96); - setRect(towerbuffer_rect, 8, 8, 320, 240); //We initialise a few things @@ -81,6 +80,7 @@ void Graphics::init(void) backboxint[i] = bint; } backoffset = 0; + foregrounddrawn = false; backgrounddrawn = false; warpskip = 0; @@ -103,18 +103,15 @@ void Graphics::init(void) ingame_fademode = FADE_NONE; // initialize everything else to zero - backBuffer = NULL; - foregrounddrawn = false; - foregroundBuffer = NULL; - backgrounddrawn = false; m = 0; linedelay = 0; - menubuffer = NULL; - menuoffbuffer = NULL; - warpbuffer = NULL; - warpbuffer_lerp = NULL; - footerbuffer = NULL; - ghostbuffer = NULL; + gameTexture = NULL; + gameplayTexture = NULL; + menuTexture = NULL; + ghostTexture = NULL; + tempTexture = NULL; + backgroundTexture = NULL; + foregroundTexture = NULL; towerbg = TowerBG(); titlebg = TowerBG(); trinketr = 0; @@ -160,101 +157,56 @@ void Graphics::init(void) void Graphics::destroy(void) { - #define CLEAR_ARRAY(name) \ - for (size_t i = 0; i < name.size(); i += 1) \ - { \ - VVV_freefunc(SDL_FreeSurface, name[i]); \ - } \ - name.clear(); +#define CLEAR_ARRAY(name) \ + for (size_t i = 0; i < name.size(); i += 1) \ + { \ + VVV_freefunc(SDL_FreeSurface, name[i]); \ + } \ + name.clear(); - CLEAR_ARRAY(tiles) - CLEAR_ARRAY(tiles2) - CLEAR_ARRAY(tiles3) - CLEAR_ARRAY(entcolours) - CLEAR_ARRAY(sprites) - CLEAR_ARRAY(flipsprites) - CLEAR_ARRAY(tele) - CLEAR_ARRAY(bfont) - CLEAR_ARRAY(flipbfont) + CLEAR_ARRAY(sprites_surf) + CLEAR_ARRAY(flipsprites_surf) - #undef CLEAR_ARRAY +#undef CLEAR_ARRAY } -void Graphics::create_buffers(const SDL_PixelFormat* fmt) +void Graphics::create_buffers(void) { - #define CREATE_SURFACE(w, h) \ - SDL_CreateRGBSurface( \ - SDL_SWSURFACE, \ - w, h, \ - fmt->BitsPerPixel, \ - fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask \ - ) - backBuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS); - SDL_SetSurfaceBlendMode(backBuffer, SDL_BLENDMODE_NONE); +#define CREATE_TEXTURE_WITH_DIMENSIONS(w, h) \ + SDL_CreateTexture( \ + gameScreen.m_renderer, \ + SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, \ + (w), (h) \ + ) +#define CREATE_TEXTURE \ + CREATE_TEXTURE_WITH_DIMENSIONS(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS) +#define CREATE_SCROLL_TEXTURE \ + CREATE_TEXTURE_WITH_DIMENSIONS(SCREEN_WIDTH_PIXELS + 16, SCREEN_WIDTH_PIXELS + 16) - footerbuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS, 10); - SDL_SetSurfaceBlendMode(footerbuffer, SDL_BLENDMODE_BLEND); - SDL_SetSurfaceAlphaMod(footerbuffer, 127); - FillRect(footerbuffer, 0, 0, 0); - - roomname_translator::dimbuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS); - SDL_SetSurfaceBlendMode(roomname_translator::dimbuffer, SDL_BLENDMODE_BLEND); - SDL_SetSurfaceAlphaMod(roomname_translator::dimbuffer, 96); - FillRect(roomname_translator::dimbuffer, 0, 0, 0); - - ghostbuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS); - SDL_SetSurfaceBlendMode(ghostbuffer, SDL_BLENDMODE_BLEND); - SDL_SetSurfaceAlphaMod(ghostbuffer, 127); - - foregroundBuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS); - SDL_SetSurfaceBlendMode(foregroundBuffer, SDL_BLENDMODE_BLEND); - - menubuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS); - SDL_SetSurfaceBlendMode(menubuffer, SDL_BLENDMODE_NONE); - - warpbuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS + 16, SCREEN_HEIGHT_PIXELS + 16); - SDL_SetSurfaceBlendMode(warpbuffer, SDL_BLENDMODE_NONE); - - warpbuffer_lerp = CREATE_SURFACE(SCREEN_WIDTH_PIXELS + 16, SCREEN_HEIGHT_PIXELS + 16); - SDL_SetSurfaceBlendMode(warpbuffer_lerp, SDL_BLENDMODE_NONE); - - towerbg.buffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS + 16, SCREEN_HEIGHT_PIXELS + 16); - SDL_SetSurfaceBlendMode(towerbg.buffer, SDL_BLENDMODE_NONE); - - towerbg.buffer_lerp = CREATE_SURFACE(SCREEN_WIDTH_PIXELS + 16, SCREEN_HEIGHT_PIXELS + 16); - SDL_SetSurfaceBlendMode(towerbg.buffer_lerp, SDL_BLENDMODE_NONE); - - titlebg.buffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS + 16, SCREEN_HEIGHT_PIXELS + 16); - SDL_SetSurfaceBlendMode(titlebg.buffer, SDL_BLENDMODE_NONE); - - titlebg.buffer_lerp = CREATE_SURFACE(SCREEN_WIDTH_PIXELS + 16, SCREEN_HEIGHT_PIXELS + 16); - SDL_SetSurfaceBlendMode(titlebg.buffer_lerp, SDL_BLENDMODE_NONE); - - menuoffbuffer = CREATE_SURFACE(SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS); - SDL_SetSurfaceBlendMode(menuoffbuffer, SDL_BLENDMODE_NONE); - - #undef CREATE_SURFACE + gameTexture = CREATE_TEXTURE; + gameplayTexture = CREATE_TEXTURE; + menuTexture = CREATE_TEXTURE; + ghostTexture = CREATE_TEXTURE; + tempTexture = CREATE_TEXTURE; + foregroundTexture = CREATE_TEXTURE; + backgroundTexture = CREATE_SCROLL_TEXTURE; + towerbg.texture = CREATE_SCROLL_TEXTURE; + titlebg.texture = CREATE_SCROLL_TEXTURE; + +#undef CREATE_SCROLL_TEXTURE +#undef CREATE_TEXTURE +#undef CREATE_TEXTURE_WITH_DIMENSIONS } void Graphics::destroy_buffers(void) { -#define FREE_SURFACE(SURFACE) VVV_freefunc(SDL_FreeSurface, SURFACE) - - FREE_SURFACE(backBuffer); - FREE_SURFACE(footerbuffer); - FREE_SURFACE(roomname_translator::dimbuffer); - FREE_SURFACE(ghostbuffer); - FREE_SURFACE(foregroundBuffer); - FREE_SURFACE(menubuffer); - FREE_SURFACE(warpbuffer); - FREE_SURFACE(warpbuffer_lerp); - FREE_SURFACE(towerbg.buffer); - FREE_SURFACE(towerbg.buffer_lerp); - FREE_SURFACE(titlebg.buffer); - FREE_SURFACE(titlebg.buffer_lerp); - FREE_SURFACE(menuoffbuffer); - -#undef FREE_SURFACE + VVV_freefunc(SDL_DestroyTexture, gameTexture); + VVV_freefunc(SDL_DestroyTexture, gameplayTexture); + VVV_freefunc(SDL_DestroyTexture, menuTexture); + VVV_freefunc(SDL_DestroyTexture, ghostTexture); + VVV_freefunc(SDL_DestroyTexture, tempTexture); + VVV_freefunc(SDL_DestroyTexture, foregroundTexture); + VVV_freefunc(SDL_DestroyTexture, backgroundTexture); } int Graphics::font_idx(uint32_t ch) @@ -281,15 +233,7 @@ int Graphics::font_idx(uint32_t ch) void Graphics::drawspritesetcol(int x, int y, int t, int c) { - if (!INBOUNDS_VEC(t, sprites)) - { - return; - } - SDL_Rect rect; - setRect(rect,x,y,sprites_rect.w,sprites_rect.h); - const SDL_Color ct = getcol(c); - - BlitSurfaceColoured(sprites[t],NULL,backBuffer, &rect, ct); + draw_grid_tile(grphx.im_sprites, t, x, y, sprites_rect.w, sprites_rect.h, getcol(c)); } void Graphics::updatetitlecolours(void) @@ -355,12 +299,6 @@ void Graphics::updatetitlecolours(void) bool Graphics::Makebfont(void) { - PROCESS_TILESHEET(bfont, 8, - { - SDL_Surface* TempFlipped = FlipSurfaceVerticle(temp); - flipbfont.push_back(TempFlipped); - }) - unsigned char* charmap = NULL; size_t length; if (FILESYSTEM_areAssetsInSameRealDir("graphics/font.png", "graphics/font.txt")) @@ -400,27 +338,10 @@ int Graphics::bfontlen(uint32_t ch) } } -bool Graphics::MakeTileArray(void) -{ - PROCESS_TILESHEET(tiles, 8, {}) - PROCESS_TILESHEET(tiles2, 8, {}) - PROCESS_TILESHEET(tiles3, 8, {}) - PROCESS_TILESHEET(entcolours, 8, {}) - - return true; -} - -bool Graphics::maketelearray(void) -{ - PROCESS_TILESHEET_RENAME(teleporter, tele, 96, {}) - - return true; -} - bool Graphics::MakeSpriteArray(void) { - PROCESS_TILESHEET(sprites, 32, {}) - PROCESS_TILESHEET(flipsprites, 32, {}) + PROCESS_TILESHEET(sprites_surf, 32, {}) + PROCESS_TILESHEET(flipsprites_surf, 32, {}) return true; } @@ -477,38 +398,6 @@ void Graphics::map_option(int opt, int num_opts, const std::string& text, bool s } } -static void print_char( - SDL_Surface* const buffer, - SDL_Surface* const font, - const int x, - const int y, - const int scale, - const SDL_Color color -) { - SDL_Rect font_rect = {x, y, 8*scale, 8*scale}; - SDL_Surface* surface; - - if (scale > 1) - { - surface = ScaleSurface(font, 8 * scale, 8 * scale); - if (surface == NULL) - { - return; - } - } - else - { - surface = font; - } - - BlitSurfaceColoured(surface, NULL, buffer, &font_rect, color); - - if (scale > 1) - { - VVV_freefunc(SDL_FreeSurface, surface); - } -} - void Graphics::do_print( const int x, const int y, @@ -519,8 +408,6 @@ void Graphics::do_print( int a, const int scale ) { - std::vector& font = flipmode ? flipbfont : bfont; - int position = 0; std::string::const_iterator iter = text.begin(); @@ -529,17 +416,12 @@ void Graphics::do_print( b = SDL_clamp(b, 0, 255); a = SDL_clamp(a, 0, 255); - const SDL_Color ct = getRGBA(r, g, b, a); - while (iter != text.end()) { const uint32_t character = utf8::unchecked::next(iter); const int idx = font_idx(character); - if (INBOUNDS_VEC(idx, font)) - { - print_char(backBuffer, font[idx], x + position, y, scale, ct); - } + draw_grid_tile(grphx.im_bfont, idx, (x + position), y, 8, 8, r, g, b, a, scale, scale * (flipmode ? -1 : 1)); position += bfontlen(character) * scale; } @@ -1007,28 +889,228 @@ void Graphics::printcrewnamestatus( int x, int y, int t, bool rescued ) Print(x, y, status_text, r, g, b, false); } -void Graphics::drawsprite( int x, int y, int t, int r, int g, int b ) +int Graphics::set_render_target(SDL_Texture* texture) { - if (!INBOUNDS_VEC(t, sprites)) + const int result = SDL_SetRenderTarget(gameScreen.m_renderer, texture); + if (result != 0) { - WHINE_ONCE("drawsprite() out-of-bounds!"); - return; + WHINE_ONCE_ARGS(("Could not set render target: %s", SDL_GetError())); } - - SDL_Rect rect = {x, y, sprites_rect.w, sprites_rect.h}; - BlitSurfaceColoured(sprites[t], NULL, backBuffer, &rect, getRGB(r, g, b)); + return result; } -void Graphics::drawsprite(int x, int y, int t, const SDL_Color color) +int Graphics::set_texture_color_mod(SDL_Texture* texture, const Uint8 r, const Uint8 g, const Uint8 b) { - if (!INBOUNDS_VEC(t, sprites)) + const int result = SDL_SetTextureColorMod(texture, r, g, b); + if (result != 0) { - WHINE_ONCE("drawsprite() out-of-bounds!"); - return; + WHINE_ONCE_ARGS(("Could not set texture color mod: %s", SDL_GetError())); + } + return result; +} + +int Graphics::set_texture_alpha_mod(SDL_Texture* texture, const Uint8 alpha) +{ + const int result = SDL_SetTextureAlphaMod(texture, alpha); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not set texture alpha mod: %s", SDL_GetError())); + } + return result; +} + +int Graphics::query_texture(SDL_Texture* texture, Uint32* format, int* access, int* w, int* h) +{ + const int result = SDL_QueryTexture(texture, format, access, w, h); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not query texture: %s", SDL_GetError())); + } + return result; +} + +int Graphics::set_blendmode(const SDL_BlendMode blendmode) +{ + const int result = SDL_SetRenderDrawBlendMode(gameScreen.m_renderer, blendmode); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not set draw mode: %s", SDL_GetError())); + } + return result; +} + +int Graphics::set_blendmode(SDL_Texture* texture, const SDL_BlendMode blendmode) +{ + const int result = SDL_SetTextureBlendMode(texture, blendmode); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not set texture blend mode: %s", SDL_GetError())); + } + return result; +} + +int Graphics::clear(const int r, const int g, const int b, const int a) +{ + set_color(r, g, b, a); + + const int result = SDL_RenderClear(gameScreen.m_renderer); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not clear current render target: %s", SDL_GetError())); + } + return result; +} + +int Graphics::clear() +{ + return clear(0, 0, 0, 255); +} + +int Graphics::copy_texture(SDL_Texture* texture, const SDL_Rect* src, const SDL_Rect* dest) +{ + const int result = SDL_RenderCopy(gameScreen.m_renderer, texture, src, dest); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not copy texture: %s", SDL_GetError())); + } + return result; +} + +int Graphics::copy_texture(SDL_Texture* texture, const SDL_Rect* src, const SDL_Rect* dest, const double angle, const SDL_Point* center, const SDL_RendererFlip flip) +{ + const int result = SDL_RenderCopyEx(gameScreen.m_renderer, texture, src, dest, angle, center, flip); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not copy texture: %s", SDL_GetError())); + } + return result; +} + +int Graphics::set_color(const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a) +{ + const int result = SDL_SetRenderDrawColor(gameScreen.m_renderer, r, g, b, a); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not set draw color: %s", SDL_GetError())); + } + return result; +} + +int Graphics::set_color(const Uint8 r, const Uint8 g, const Uint8 b) +{ + return set_color(r, g, b, 255); +} + +int Graphics::set_color(const SDL_Color color) +{ + return set_color(color.r, color.g, color.b, color.a); +} + +int Graphics::fill_rect(const SDL_Rect* rect, const int r, const int g, const int b, const int a) +{ + set_color(r, g, b, a); + + const int result = SDL_RenderFillRect(gameScreen.m_renderer, rect); + if (result != 0) + { + WHINE_ONCE_ARGS(("Could not draw filled rectangle: %s", SDL_GetError())); + } + return result; +} + +int Graphics::fill_rect(const int r, const int g, const int b, const int a) +{ + return fill_rect(NULL, r, g, b, a); +} + +int Graphics::fill_rect(const SDL_Rect* rect, const int r, const int g, const int b) +{ + return fill_rect(rect, r, g, b, 255); +} + +int Graphics::fill_rect(const int r, const int g, const int b) +{ + return fill_rect(NULL, r, g, b, 255); +} + +int Graphics::fill_rect(const SDL_Rect* rect, const SDL_Color color) +{ + return fill_rect(rect, color.r, color.g, color.b, color.a); +} + +int Graphics::fill_rect(const int x, const int y, const int w, const int h, const int r, const int g, const int b, const int a) +{ + const SDL_Rect rect = {x, y, w, h}; + return fill_rect(&rect, r, g, b, a); +} + +int Graphics::fill_rect(const int x, const int y, const int w, const int h, const int r, const int g, const int b) +{ + return fill_rect(x, y, w, h, r, g, b, 255); +} + +int Graphics::fill_rect(const SDL_Color color) +{ + return fill_rect(NULL, color); +} + +int Graphics::fill_rect(const int x, const int y, const int w, const int h, const SDL_Color color) +{ + return fill_rect(x, y, w, h, color.r, color.g, color.b, color.a); +} + +void Graphics::draw_sprite(const int x, const int y, const int t, const int r, const int g, const int b) +{ + draw_grid_tile(grphx.im_sprites, t, x, y, sprites_rect.w, sprites_rect.h, r, g, b); +} + +void Graphics::draw_sprite(const int x, const int y, const int t, const SDL_Color color) +{ + draw_grid_tile(grphx.im_sprites, t, x, y, sprites_rect.w, sprites_rect.h, color); +} + +void Graphics::scroll_texture(SDL_Texture* texture, const int x, const int y) +{ + SDL_Rect texture_rect = {0, 0, 0, 0}; + SDL_QueryTexture(texture, NULL, NULL, &texture_rect.w, &texture_rect.h); + + if (x < 0) + { + for (int i = 0; i < texture_rect.w; i -= x) + { + const SDL_Rect src = {i, 0, x * -1, texture_rect.h}; + const SDL_Rect dest = {i + x, 0, x * -1, texture_rect.h}; + copy_texture(texture, &src, &dest); + } + } + else if (x > 0) + { + for (int i = texture_rect.w; i > 0; i -= x) + { + const SDL_Rect src = {i - x, 0, x, texture_rect.h}; + const SDL_Rect dest = {i, 0, x, texture_rect.h}; + copy_texture(texture, &src, &dest); + } } - SDL_Rect rect = {x, y, sprites_rect.w, sprites_rect.h}; - BlitSurfaceColoured(sprites[t], NULL, backBuffer, &rect, color); + if (y < 0) + { + for (int i = 0; i < texture_rect.h; i -= y) + { + const SDL_Rect src = {0, i, texture_rect.w, y * -1}; + const SDL_Rect dest = {0, i + y, texture_rect.w, y * -1}; + copy_texture(texture, &src, &dest); + } + } + else if (y > 0) + { + for (int i = texture_rect.h; i > 0; i -= y) + { + const SDL_Rect src = {0, i - y, texture_rect.w, y}; + const SDL_Rect dest = {0, i, texture_rect.w, y}; + copy_texture(texture, &src, &dest); + } + } } #ifndef NO_CUSTOM_LEVELS @@ -1042,48 +1124,30 @@ bool Graphics::shouldrecoloroneway(const int tilenum, const bool mounted) void Graphics::drawtile( int x, int y, int t ) { - if (!INBOUNDS_VEC(t, tiles)) - { - WHINE_ONCE("drawtile() out-of-bounds!"); - return; - } - - SDL_Rect rect = {x, y, tiles_rect.w, tiles_rect.h}; - #if !defined(NO_CUSTOM_LEVELS) if (shouldrecoloroneway(t, tiles1_mounted)) { - const SDL_Color thect = cl.getonewaycol(); - BlitSurfaceTinted(tiles[t], NULL, backBuffer, &rect, thect); + draw_grid_tile(grphx.im_tiles_tint, t, x, y, tiles_rect.w, tiles_rect.h, cl.getonewaycol()); } else #endif { - BlitSurfaceStandard(tiles[t], NULL, backBuffer, &rect); + draw_grid_tile(grphx.im_tiles, t, x, y, tiles_rect.w, tiles_rect.h); } } void Graphics::drawtile2( int x, int y, int t ) { - if (!INBOUNDS_VEC(t, tiles2)) - { - WHINE_ONCE("drawtile2() out-of-bounds!"); - return; - } - - SDL_Rect rect = {x, y, tiles_rect.w, tiles_rect.h}; - #if !defined(NO_CUSTOM_LEVELS) if (shouldrecoloroneway(t, tiles2_mounted)) { - const SDL_Color thect = cl.getonewaycol(); - BlitSurfaceTinted(tiles2[t], NULL, backBuffer, &rect, thect); + draw_grid_tile(grphx.im_tiles2_tint, t, x, y, tiles_rect.w, tiles_rect.h, cl.getonewaycol()); } else #endif { - BlitSurfaceStandard(tiles2[t], NULL, backBuffer, &rect); + draw_grid_tile(grphx.im_tiles2, t, x, y, tiles_rect.w, tiles_rect.h); } } @@ -1092,42 +1156,31 @@ void Graphics::drawtile2( int x, int y, int t ) void Graphics::drawtile3( int x, int y, int t, int off, int height_subtract /*= 0*/ ) { t += off * 30; - if (!INBOUNDS_VEC(t, tiles3)) + + // Can't use drawgridtile because we want to draw a slice of the tile, + // so do the logic ourselves (except include height_subtract in the final call) + + int width; + if (query_texture(grphx.im_tiles3, NULL, NULL, &width, NULL) != 0) { - WHINE_ONCE("drawtile3() out-of-bounds!"); return; } - SDL_Rect src_rect = { 0, 0, tiles_rect.w, tiles_rect.h - height_subtract }; - SDL_Rect rect = {x, y, tiles_rect.w, tiles_rect.h}; - BlitSurfaceStandard(tiles3[t], &src_rect, backBuffer, &rect); + const int x2 = (t % (width / 8)) * 8; + const int y2 = (t / (width / 8)) * 8; + draw_texture_part(grphx.im_tiles3, x, y, x2, y2, 8, 8 - height_subtract, 1, 1); } void Graphics::drawtowertile( int x, int y, int t ) { - if (!INBOUNDS_VEC(t, tiles2)) - { - WHINE_ONCE("drawtowertile() out-of-bounds!"); - return; - } - x += 8; - y += 8; - SDL_Rect rect = {x, y, tiles_rect.w, tiles_rect.h}; - BlitSurfaceStandard(tiles2[t], NULL, warpbuffer, &rect); + draw_grid_tile(grphx.im_tiles2, t, x, y, tiles_rect.w, tiles_rect.h); } void Graphics::drawtowertile3( int x, int y, int t, TowerBG& bg_obj ) { - t += bg_obj.colstate*30; - if (!INBOUNDS_VEC(t, tiles3)) - { - WHINE_ONCE("drawtowertile3() out-of-bounds!"); - return; - } - x += 8; - y += 8; - SDL_Rect rect = {x, y, tiles_rect.w, tiles_rect.h}; - BlitSurfaceStandard(tiles3[t], NULL, bg_obj.buffer, &rect); + t += bg_obj.colstate * 30; + + draw_grid_tile(grphx.im_tiles3, t, x, y, tiles_rect.w, tiles_rect.h); } void Graphics::drawgui(void) @@ -1230,11 +1283,11 @@ void Graphics::drawgui(void) { if (flipmode) { - drawimage(5, 0, 180, true); + drawimage(IMAGE_FLIPLEVELCOMPLETE, 0, 180, true); } else { - drawimage(0, 0, 12, true); + drawimage(IMAGE_LEVELCOMPLETE, 0, 12, true); } } } @@ -1266,11 +1319,11 @@ void Graphics::drawgui(void) { if (flipmode) { - drawimage(6, 0, 180, true); + drawimage(IMAGE_FLIPGAMECOMPLETE, 0, 180, true); } else { - drawimage(4, 0, 12, true); + drawimage(IMAGE_GAMECOMPLETE, 0, 12, true); } } } @@ -1278,27 +1331,27 @@ void Graphics::drawgui(void) if (textboxes[i].r == 175 && textboxes[i].g == 175) { //purple guy - drawsprite(crew_xp, crew_yp, crew_sprite, 220- help.glow/4 - textboxes[i].rand, 120- help.glow/4, 210 - help.glow/4); + draw_sprite(crew_xp, crew_yp, crew_sprite, 220- help.glow/4 - textboxes[i].rand, 120- help.glow/4, 210 - help.glow/4); } else if (textboxes[i].r == 175 && textboxes[i].b == 175) { //red guy - drawsprite(crew_xp, crew_yp, crew_sprite, 255 - help.glow/8, 70 - help.glow/4, 70 - help.glow / 4); + draw_sprite(crew_xp, crew_yp, crew_sprite, 255 - help.glow/8, 70 - help.glow/4, 70 - help.glow / 4); } else if (textboxes[i].r == 175) { //green guy - drawsprite(crew_xp, crew_yp, crew_sprite, 120 - help.glow / 4 - textboxes[i].rand, 220 - help.glow / 4, 120 - help.glow / 4); + draw_sprite(crew_xp, crew_yp, crew_sprite, 120 - help.glow / 4 - textboxes[i].rand, 220 - help.glow / 4, 120 - help.glow / 4); } else if (textboxes[i].g == 175) { //yellow guy - drawsprite(crew_xp, crew_yp, crew_sprite, 220- help.glow/4 - textboxes[i].rand, 210 - help.glow/4, 120- help.glow/4); + draw_sprite(crew_xp, crew_yp, crew_sprite, 220- help.glow/4 - textboxes[i].rand, 210 - help.glow/4, 120- help.glow/4); } else if (textboxes[i].b == 175) { //blue guy - drawsprite(crew_xp, crew_yp, crew_sprite, 75, 75, 255- help.glow/4 - textboxes[i].rand); + draw_sprite(crew_xp, crew_yp, crew_sprite, 75, 75, 255- help.glow/4 - textboxes[i].rand); } } } @@ -1330,85 +1383,172 @@ void Graphics::updatetextboxes(void) void Graphics::drawimagecol( int t, int xp, int yp, const SDL_Color ct, bool cent/*= false*/ ) { - if (!INBOUNDS_VEC(t, images) || images[t] == NULL) + if (!INBOUNDS_ARR(t, images) || images[t] == NULL) { return; } SDL_Rect trect; - point tpoint; + trect.x = xp; + trect.y = yp; + + if (query_texture(images[t], NULL, NULL, &trect.w, &trect.h) != 0) + { + return; + } + if (cent) { - tpoint.x = 160 - int(images[t]->w / 2); - tpoint.y = yp; - trect.x = tpoint.x ; - trect.y = tpoint.y; - trect.w = images[t]->w; - trect.h= images[t]->h; - BlitSurfaceColoured(images[t], NULL, backBuffer, &trect, ct); - + trect.x = (int) ((SCREEN_WIDTH_PIXELS - trect.w) / 2); } - else - { - trect.x = xp; - trect.y = yp; - trect.w = images[t]->w; - trect.h = images[t]->h; - BlitSurfaceColoured(images[t], NULL, backBuffer, &trect, ct); - } + set_texture_color_mod(images[t], ct.r, ct.g, ct.b); + draw_texture(images[t], trect.x, trect.y); + set_texture_color_mod(images[t], 255, 255, 255); } void Graphics::drawimage( int t, int xp, int yp, bool cent/*=false*/ ) { - if (!INBOUNDS_VEC(t, images) || images[t] == NULL) + if (!INBOUNDS_ARR(t, images) || images[t] == NULL) { return; } SDL_Rect trect; + + trect.x = xp; + trect.y = yp; + + if (query_texture(images[t], NULL, NULL, &trect.w, &trect.h) != 0) + { + return; + } + if (cent) { - trect.x = 160 - int(images[t]->w / 2); - trect.y = yp; - trect.w = images[t]->w; - trect.h = images[t]->h; - BlitSurfaceStandard(images[t], NULL, backBuffer, &trect); + trect.x = (int) ((SCREEN_WIDTH_PIXELS - trect.w) / 2); } - else - { - trect.x = xp; - trect.y = yp; - trect.w = images[t]->w; - trect.h= images[t]->h; - - BlitSurfaceStandard(images[t], NULL, backBuffer, &trect); - } + draw_texture(images[t], trect.x, trect.y); } -void Graphics::drawpartimage( int t, int xp, int yp, int wp, int hp) +void Graphics::drawpartimage(const int t, const int xp, const int yp, const int wp, const int hp) { - if (!INBOUNDS_VEC(t, images) || images[t] == NULL) - { - return; - } + if (!INBOUNDS_ARR(t, images) || images[t] == NULL) + { + return; + } + draw_texture_part(images[t], xp, yp, 0, 0, wp, hp, 1, 1); +} - SDL_Rect trect; +void Graphics::draw_texture(SDL_Texture* image, const int x, const int y) +{ + int w, h; - trect.x = xp; - trect.y = yp; - trect.w = wp; - trect.h= hp; + if (query_texture(image, NULL, NULL, &w, &h) != 0) + { + return; + } - SDL_Rect trect2; + const SDL_Rect dstrect = {x, y, w, h}; - trect2.x = 0; - trect2.y = 0; - trect2.w = wp; - trect2.h= hp; + copy_texture(image, NULL, &dstrect); +} - BlitSurfaceStandard(images[t], &trect2, backBuffer, &trect); +void Graphics::draw_texture_part(SDL_Texture* image, const int x, const int y, const int x2, const int y2, const int w, const int h, const int scalex, const int scaley) +{ + const SDL_Rect srcrect = {x2, y2, w, h}; + + int flip = SDL_FLIP_NONE; + + if (scalex < 0) + { + flip |= SDL_FLIP_HORIZONTAL; + } + if (scaley < 0) + { + flip |= SDL_FLIP_VERTICAL; + } + + const SDL_Rect dstrect = {x, y, w * SDL_abs(scalex), h * SDL_abs(scaley)}; + + copy_texture(image, &srcrect, &dstrect, 0, NULL, (SDL_RendererFlip) flip); +} + +void Graphics::draw_grid_tile(SDL_Texture* texture, const int t, const int x, const int y, const int width, const int height, const int scalex, const int scaley) +{ + int tex_width; + + if (query_texture(texture, NULL, NULL, &tex_width, NULL) != 0) + { + return; + } + + const int x2 = (t % (tex_width / width)) * width; + const int y2 = (t / (tex_width / width)) * height; + draw_texture_part(texture, x, y, x2, y2, width, height, scalex, scaley); +} + +void Graphics::draw_grid_tile( + SDL_Texture* texture, const int t, + const int x, const int y, const int width, const int height +) { + draw_grid_tile(texture, t, x, y, width, height, 1, 1); +} + +void Graphics::draw_grid_tile( + SDL_Texture* texture, const int t, + const int x, const int y, const int width, const int height, + const int r, const int g, const int b, const int a, + const int scalex, const int scaley +) { + set_texture_color_mod(texture, r, g, b); + set_texture_alpha_mod(texture, a); + draw_grid_tile(texture, t, x, y, width, height, scalex, scaley); + set_texture_color_mod(texture, 255, 255, 255); + set_texture_alpha_mod(texture, 255); +} + +void Graphics::draw_grid_tile( + SDL_Texture* texture, const int t, + const int x, const int y, const int width, const int height, + const int r, const int g, const int b, const int a +) { + draw_grid_tile(texture, t, x, y, width, height, r, g, b, a, 1, 1); +} + +void Graphics::draw_grid_tile( + SDL_Texture* texture, const int t, + const int x, const int y, const int width, const int height, + const int r, const int g, const int b, + const int scalex, const int scaley +) { + draw_grid_tile(texture, t, x, y, width, height, r, g, b, 255, scalex, scaley); +} + +void Graphics::draw_grid_tile( + SDL_Texture* texture, const int t, + const int x, const int y, const int width, const int height, + const int r, const int g, const int b +) { + draw_grid_tile(texture, t, x, y, width, height, r, g, b, 255); +} + +void Graphics::draw_grid_tile( + SDL_Texture* texture, const int t, + const int x, const int y, const int width, const int height, + const SDL_Color color, + const int scalex, const int scaley +) { + draw_grid_tile(texture, t, x, y, width, height, color.r, color.g, color.b, color.a, scalex, scaley); +} + +void Graphics::draw_grid_tile( + SDL_Texture* texture, const int t, + const int x, const int y, const int width, const int height, + const SDL_Color color +) { + draw_grid_tile(texture, t, x, y, width, height, color, 1, 1); } void Graphics::cutscenebars(void) @@ -1416,14 +1556,14 @@ void Graphics::cutscenebars(void) const int usethispos = lerp(oldcutscenebarspos, cutscenebarspos); if (showcutscenebars) { - FillRect(backBuffer, 0, 0, usethispos, 16, 0, 0, 0); - FillRect(backBuffer, 360-usethispos, 224, usethispos, 16, 0, 0, 0); + fill_rect(0, 0, usethispos, 16, 0, 0, 0); + fill_rect(360-usethispos, 224, usethispos, 16, 0, 0, 0); } else if (cutscenebarspos > 0) //disappearing { //draw - FillRect(backBuffer, 0, 0, usethispos, 16, 0, 0, 0); - FillRect(backBuffer, 360-usethispos, 224, usethispos, 16, 0, 0, 0); + fill_rect(0, 0, usethispos, 16, 0, 0, 0); + fill_rect(360-usethispos, 224, usethispos, 16, 0, 0, 0); } } @@ -1457,22 +1597,22 @@ void Graphics::drawcrewman( int x, int y, int t, bool act, bool noshift /*=false { if (flipmode) { - drawsprite(x, y, 14, col_crewinactive); + draw_sprite(x, y, 14, col_crewinactive); } else { - drawsprite(x, y, 12, col_crewinactive); + draw_sprite(x, y, 12, col_crewinactive); } } else { if (flipmode) { - drawsprite(x - 8, y, 14, col_crewinactive); + draw_sprite(x - 8, y, 14, col_crewinactive); } else { - drawsprite(x - 8, y, 12, col_crewinactive); + draw_sprite(x - 8, y, 12, col_crewinactive); } } } @@ -1483,22 +1623,22 @@ void Graphics::drawcrewman( int x, int y, int t, bool act, bool noshift /*=false switch(t) { case 0: - drawsprite(x, y, crewframe, col_crewcyan); + draw_sprite(x, y, crewframe, col_crewcyan); break; case 1: - drawsprite(x, y, crewframe, col_crewpurple); + draw_sprite(x, y, crewframe, col_crewpurple); break; case 2: - drawsprite(x, y, crewframe, col_crewyellow); + draw_sprite(x, y, crewframe, col_crewyellow); break; case 3: - drawsprite(x, y, crewframe, col_crewred); + draw_sprite(x, y, crewframe, col_crewred); break; case 4: - drawsprite(x, y, crewframe, col_crewgreen); + draw_sprite(x, y, crewframe, col_crewgreen); break; case 5: - drawsprite(x, y, crewframe, col_crewblue); + draw_sprite(x, y, crewframe, col_crewblue); break; } @@ -1517,7 +1657,7 @@ void Graphics::drawpixeltextbox( ) { int k; - FillRect(backBuffer, x, y, w, h, r/6, g/6, b/6); + fill_rect(x, y, w, h, r/6, g/6, b/6); /* Horizontal tiles */ for (k = 0; k < w/8 - 2; ++k) @@ -1682,18 +1822,18 @@ void Graphics::drawfade(void) { case FADE_FULLY_BLACK: case FADE_START_FADEIN: - ClearSurface(backBuffer); + fill_rect(0, 0, 0); break; case FADE_FADING_OUT: for (size_t i = 0; i < SDL_arraysize(fadebars); i++) { - FillRect(backBuffer, fadebars[i], i * 16, usethisamount, 16, 0, 0, 0); + fill_rect(fadebars[i], i * 16, usethisamount, 16, 0, 0, 0); } break; case FADE_FADING_IN: for (size_t i = 0; i < SDL_arraysize(fadebars); i++) { - FillRect(backBuffer, fadebars[i]-usethisamount, i * 16, 500, 16, 0, 0, 0); + fill_rect(fadebars[i]-usethisamount, i * 16, 500, 16, 0, 0, 0); } break; case FADE_NONE: @@ -1858,22 +1998,11 @@ void Graphics::drawmenu(int cr, int cg, int cb, enum Menu::MenuName menu) void Graphics::drawcoloredtile( - const int x, - const int y, + const int x, const int y, const int t, - const int r, - const int g, - const int b + const int r, const int g, const int b ) { - SDL_Rect rect; - - if (!INBOUNDS_VEC(t, tiles)) - { - return; - } - - setRect(rect, x, y, tiles_rect.w, tiles_rect.h); - BlitSurfaceColoured(tiles[t], NULL, backBuffer, &rect, getRGB(r, g, b)); + draw_grid_tile(grphx.im_tiles_white, t, x, y, tiles_rect.w, tiles_rect.h, r, g, b); } @@ -1937,40 +2066,40 @@ void Graphics::drawgravityline( int t ) switch(linestate) { case 0: - FillRect(backBuffer,line_rect, getRGB(200-20, 200-20, 200-20)); + fill_rect(&line_rect, getRGB(200-20, 200-20, 200-20)); break; case 1: - FillRect(backBuffer,line_rect, getRGB(245-30, 245-30, 225-30)); + fill_rect(&line_rect, getRGB(245-30, 245-30, 225-30)); break; case 2: - FillRect(backBuffer,line_rect, getRGB(225-30, 245-30, 245-30)); + fill_rect(&line_rect, getRGB(225-30, 245-30, 245-30)); break; case 3: - FillRect(backBuffer,line_rect, getRGB(200-20, 200-20, 164-10)); + fill_rect(&line_rect, getRGB(200-20, 200-20, 164-10)); break; case 4: - FillRect(backBuffer,line_rect, getRGB(196-20, 255-30, 224-20)); + fill_rect(&line_rect, getRGB(196-20, 255-30, 224-20)); break; case 5: - FillRect(backBuffer,line_rect, getRGB(196-20, 235-30, 205-20)); + fill_rect(&line_rect, getRGB(196-20, 235-30, 205-20)); break; case 6: - FillRect(backBuffer,line_rect, getRGB(164-10, 164-10, 164-10)); + fill_rect(&line_rect, getRGB(164-10, 164-10, 164-10)); break; case 7: - FillRect(backBuffer,line_rect, getRGB(205-20, 245-30, 225-30)); + fill_rect(&line_rect, getRGB(205-20, 245-30, 225-30)); break; case 8: - FillRect(backBuffer,line_rect, getRGB(225-30, 255-30, 205-20)); + fill_rect(&line_rect, getRGB(225-30, 255-30, 205-20)); break; case 9: - FillRect(backBuffer,line_rect, getRGB(245-30, 245-30, 245-30)); + fill_rect(&line_rect, getRGB(245-30, 245-30, 245-30)); break; } } else { - FillRect(backBuffer,line_rect, getRGB(96, 96, 96)); + fill_rect(&line_rect, getRGB(96, 96, 96)); } } @@ -2138,9 +2267,9 @@ void Graphics::drawentity(const int i, const int yoff) const bool custom_gray = false; #endif - std::vector& tilesvec = (map.custommode && !map.finalmode) ? entcolours : tiles; - - std::vector& spritesvec = flipmode ? flipsprites : sprites; + SDL_Texture* sprites = flipmode ? grphx.im_flipsprites : grphx.im_sprites; + SDL_Texture* tiles = (map.custommode && !map.finalmode) ? grphx.im_entcolours : grphx.im_tiles; + SDL_Texture* tiles_tint = (map.custommode && !map.finalmode) ? grphx.im_entcolours_tint : grphx.im_tiles_tint; const int xp = lerp(obj.entities[i].lerpoldxp, obj.entities[i].xp); const int yp = lerp(obj.entities[i].lerpoldyp, obj.entities[i].yp); @@ -2150,10 +2279,6 @@ void Graphics::drawentity(const int i, const int yoff) case 0: { // Sprites - if (!INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec)) - { - return; - } tpoint.x = xp; tpoint.y = yp - yoff; const SDL_Color ct = obj.entities[i].realcol; @@ -2161,7 +2286,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct); + + draw_grid_tile(sprites, obj.entities[i].drawframe, drawRect.x, drawRect.y, 32, 32, ct); //screenwrapping! point wrappedPoint; @@ -2198,45 +2324,39 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += wrappedPoint.x; drawRect.y += tpoint.y; - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct); + draw_grid_tile(sprites, obj.entities[i].drawframe, drawRect.x, drawRect.y, 32, 32, ct); } if (wrapY && map.warpy) { drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += wrappedPoint.y; - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct); + draw_grid_tile(sprites, obj.entities[i].drawframe, drawRect.x, drawRect.y, 32, 32, ct); } if (wrapX && wrapY && map.warpx && map.warpy) { drawRect = sprites_rect; drawRect.x += wrappedPoint.x; drawRect.y += wrappedPoint.y; - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, ct); + draw_grid_tile(sprites, obj.entities[i].drawframe, drawRect.x, drawRect.y, 32, 32, ct); } break; } case 1: // Tiles - if (!INBOUNDS_VEC(obj.entities[i].drawframe, tiles)) - { - return; - } tpoint.x = xp; tpoint.y = yp - yoff; drawRect = tiles_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - BlitSurfaceStandard(tiles[obj.entities[i].drawframe],NULL, backBuffer, &drawRect); + + draw_grid_tile(grphx.im_tiles, obj.entities[i].drawframe, drawRect.x, drawRect.y, 8, 8); break; case 2: case 8: { // Special: Moving platform, 4 tiles or 8 tiles - if (!INBOUNDS_VEC(obj.entities[i].drawframe, tilesvec)) - { - return; - } + tpoint.x = xp; tpoint.y = yp - yoff; int thiswidth = 4; @@ -2252,12 +2372,11 @@ void Graphics::drawentity(const int i, const int yoff) drawRect.x += 8 * ii; if (custom_gray) { - const SDL_Color temp_ct = {255, 255, 255, 255}; - BlitSurfaceTinted(tilesvec[obj.entities[i].drawframe], NULL, backBuffer, &drawRect, temp_ct); + draw_grid_tile(tiles_tint, obj.entities[i].drawframe, drawRect.x, drawRect.y, 8, 8); } else { - BlitSurfaceStandard(tilesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect); + draw_grid_tile(tiles, obj.entities[i].drawframe, drawRect.x, drawRect.y, 8, 8); } } break; @@ -2265,11 +2384,14 @@ void Graphics::drawentity(const int i, const int yoff) case 3: // Big chunky pixels! prect.x = xp; prect.y = yp - yoff; - FillRect(backBuffer, prect, obj.entities[i].realcol); + fill_rect(&prect, obj.entities[i].realcol); break; case 4: // Small pickups - drawhuetile(xp, yp - yoff, obj.entities[i].tile, obj.entities[i].realcol); + { + const SDL_Color color = obj.entities[i].realcol; + drawcoloredtile(xp, yp - yoff, obj.entities[i].tile, color.r, color.g, color.b); break; + } case 5: //Horizontal Line { int oldw = obj.entities[i].w; @@ -2307,10 +2429,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec)) - { - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(sprites, obj.entities[i].drawframe, drawRect.x, drawRect.y, 32, 32, ct); tpoint.x = xp+32; tpoint.y = yp - yoff; @@ -2318,10 +2438,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(obj.entities[i].drawframe+1, spritesvec)) - { - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe+1],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(sprites, obj.entities[i].drawframe + 1, drawRect.x, drawRect.y, 32, 32, ct); tpoint.x = xp; tpoint.y = yp+32 - yoff; @@ -2329,10 +2447,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(obj.entities[i].drawframe+12, spritesvec)) - { - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe+12],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(sprites, obj.entities[i].drawframe + 12, drawRect.x, drawRect.y, 32, 32, ct); tpoint.x = xp+32; tpoint.y = yp+32 - yoff; @@ -2340,10 +2456,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(obj.entities[i].drawframe+13, spritesvec)) - { - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe + 13],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(sprites, obj.entities[i].drawframe + 13, drawRect.x, drawRect.y, 32, 32, ct); break; } case 10: // 2x1 Sprite @@ -2356,10 +2470,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec)) - { - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(sprites, obj.entities[i].drawframe, drawRect.x, drawRect.y, 32, 32, ct); tpoint.x = xp+32; tpoint.y = yp - yoff; @@ -2367,14 +2479,12 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(obj.entities[i].drawframe+1, spritesvec)) - { - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe+1],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(sprites, obj.entities[i].drawframe + 1, drawRect.x, drawRect.y, 32, 32, ct); break; } case 11: //The fucking elephant - drawimagecol(3, xp, yp - yoff, obj.entities[i].realcol); + drawimagecol(IMAGE_ELEPHANT, xp, yp - yoff, obj.entities[i].realcol); break; case 12: // Regular sprites that don't wrap { @@ -2385,11 +2495,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = sprites_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec)) - { - BlitSurfaceColoured(spritesvec[obj.entities[i].drawframe],NULL, backBuffer, &drawRect, ct); - } + draw_grid_tile(sprites, obj.entities[i].drawframe, drawRect.x, drawRect.y, 32, 32, ct); //if we're outside the screen, we need to draw indicators @@ -2410,10 +2517,8 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = tiles_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(1167, tiles)) - { - BlitSurfaceColoured(tiles[1167],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(grphx.im_tiles_white, 1167, drawRect.x, drawRect.y, 8, 8, ct); } else if (obj.entities[i].xp > 340 && obj.entities[i].vx < 0) @@ -2433,29 +2538,15 @@ void Graphics::drawentity(const int i, const int yoff) drawRect = tiles_rect; drawRect.x += tpoint.x; drawRect.y += tpoint.y; - if (INBOUNDS_VEC(1166, tiles)) - { - BlitSurfaceColoured(tiles[1166],NULL, backBuffer, &drawRect, ct); - } + + draw_grid_tile(grphx.im_tiles_white, 1166, drawRect.x, drawRect.y, 8, 8, ct); } break; } case 13: { //Special for epilogue: huge hero! - if (!INBOUNDS_VEC(obj.entities[i].drawframe, spritesvec)) - { - return; - } - - tpoint.x = xp; tpoint.y = yp - yoff; - setRect(drawRect, xp, yp - yoff, sprites_rect.x * 6, sprites_rect.y * 6); - SDL_Surface* TempSurface = ScaleSurface( spritesvec[obj.entities[i].drawframe], 6 * sprites_rect.w,6* sprites_rect.h ); - BlitSurfaceColoured(TempSurface, NULL, backBuffer, &drawRect, obj.entities[i].realcol); - VVV_freefunc(SDL_FreeSurface, TempSurface); - - - + draw_grid_tile(grphx.im_sprites, obj.entities[i].drawframe, xp, yp - yoff, sprites_rect.w, sprites_rect.h, obj.entities[i].realcol, 6, 6); break; } } @@ -2467,7 +2558,7 @@ void Graphics::drawbackground( int t ) { case 1: //Starfield - ClearSurface(backBuffer); + fill_rect(0, 0, 0); for (int i = 0; i < numstars; i++) { stars[i].w = 2; @@ -2476,11 +2567,11 @@ void Graphics::drawbackground( int t ) star_rect.x = lerp(star_rect.x + starsspeed[i], star_rect.x); if (starsspeed[i] <= 6) { - FillRect(backBuffer,star_rect, getRGB(0x22,0x22,0x22)); + fill_rect(&star_rect, getRGB(0x22,0x22,0x22)); } else { - FillRect(backBuffer,star_rect, getRGB(0x55,0x55,0x55)); + fill_rect(&star_rect, getRGB(0x55,0x55,0x55)); } } break; @@ -2556,7 +2647,7 @@ void Graphics::drawbackground( int t ) } break; } - FillRect(backBuffer,bcol2); + fill_rect(bcol2); for (int i = 0; i < numbackboxes; i++) { @@ -2629,27 +2720,35 @@ void Graphics::drawbackground( int t ) backboxrect.x = lerp(backboxes[i].x - backboxvx[i], backboxes[i].x); backboxrect.y = lerp(backboxes[i].y - backboxvy[i], backboxes[i].y); - FillRect(backBuffer, backboxrect, bcol); + fill_rect(&backboxrect, bcol); backboxrect.x += 1; backboxrect.y += 1; backboxrect.w -= 2; backboxrect.h -= 2; - FillRect(backBuffer,backboxrect, bcol2); + fill_rect(&backboxrect, bcol2); } break; } case 3: //Warp zone (horizontal) - ClearSurface(backBuffer); - BlitSurfaceStandard(warpbuffer, NULL, warpbuffer_lerp, NULL); - ScrollSurface(warpbuffer_lerp, lerp(0, -3), 0); - BlitSurfaceStandard(warpbuffer_lerp, &towerbuffer_rect, backBuffer, NULL); + { + clear(); + + const int offset = (int) lerp(0, -3); + const SDL_Rect srcRect = {8 + offset, 0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS}; + + copy_texture(backgroundTexture, &srcRect, NULL); break; + } case 4: //Warp zone (vertical) - ClearSurface(backBuffer); - SDL_BlitSurface(warpbuffer, NULL, warpbuffer_lerp, NULL); - ScrollSurface(warpbuffer_lerp, 0, lerp(0, -3)); - SDL_BlitSurface(warpbuffer_lerp, &towerbuffer_rect, backBuffer, NULL); + { + clear(); + + const int offset = (int) lerp(0, -3); + const SDL_Rect srcRect = {0, 8 + offset, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS}; + + copy_texture(backgroundTexture, &srcRect, NULL); break; + } case 5: { //Warp zone, central @@ -2698,18 +2797,18 @@ void Graphics::drawbackground( int t ) const SDL_Rect warprect = {160 - temp, 120 - temp, temp * 2, temp * 2}; if (i % 2 == warpskip) { - FillRect(backBuffer, warprect, warpbcol); + fill_rect(&warprect, warpbcol); } else { - FillRect(backBuffer, warprect, warpfcol); + fill_rect(&warprect, warpfcol); } } break; } case 6: //Final Starfield - ClearSurface(backBuffer); + fill_rect(0, 0, 0); for (int i = 0; i < numstars; i++) { stars[i].w = 2; @@ -2718,11 +2817,11 @@ void Graphics::drawbackground( int t ) star_rect.y = lerp(star_rect.y + starsspeed[i], star_rect.y); if (starsspeed[i] <= 8) { - FillRect(backBuffer, star_rect, getRGB(0x22, 0x22, 0x22)); + fill_rect(&star_rect, getRGB(0x22, 0x22, 0x22)); } else { - FillRect(backBuffer, star_rect, getRGB(0x55, 0x55, 0x55)); + fill_rect(&star_rect, getRGB(0x55, 0x55, 0x55)); } } break; @@ -2757,7 +2856,7 @@ void Graphics::drawbackground( int t ) } break; default: - ClearSurface(backBuffer); + fill_rect(0, 0, 0); break; } @@ -2825,17 +2924,20 @@ void Graphics::updatebackground(int t) case 3: //Warp zone (horizontal) { const int temp = 680 + (rcol * 3); - backoffset+=3; + backoffset += 3; if (backoffset >= 16) backoffset -= 16; + SDL_Texture* target = SDL_GetRenderTarget(gameScreen.m_renderer); + set_render_target(backgroundTexture); + if (backgrounddrawn) { - ScrollSurface(warpbuffer, -3, 0 ); + scroll_texture(backgroundTexture, -3, 0); for (int j = 0; j < 15; j++) { for (int i = 0; i < 2; i++) { - drawtowertile(317 - backoffset + (i * 16), (j * 16), temp+40); //20*16 = 320 + drawtowertile(317 - backoffset + (i * 16), (j * 16), temp + 40); //20*16 = 320 drawtowertile(317 - backoffset + (i * 16) + 8, (j * 16), temp + 41); drawtowertile(317 - backoffset + (i * 16), (j * 16) + 8, temp + 80); drawtowertile(317 - backoffset + (i * 16) + 8, (j * 16) + 8, temp + 81); @@ -2846,12 +2948,12 @@ void Graphics::updatebackground(int t) { //draw the whole thing for the first time! backoffset = 0; - ClearSurface(warpbuffer); + clear(); for (int j = 0; j < 15; j++) { for (int i = 0; i < 21; i++) { - drawtowertile((i * 16) - backoffset - 3, (j * 16), temp+40); + drawtowertile((i * 16) - backoffset - 3, (j * 16), temp + 40); drawtowertile((i * 16) - backoffset + 8 - 3, (j * 16), temp + 41); drawtowertile((i * 16) - backoffset - 3, (j * 16) + 8, temp + 80); drawtowertile((i * 16) - backoffset + 8 - 3, (j * 16) + 8, temp + 81); @@ -2859,17 +2961,21 @@ void Graphics::updatebackground(int t) } backgrounddrawn = true; } + set_render_target(target); break; } case 4: //Warp zone (vertical) { const int temp = 760 + (rcol * 3); - backoffset+=3; + backoffset += 3; if (backoffset >= 16) backoffset -= 16; + SDL_Texture* target = SDL_GetRenderTarget(gameScreen.m_renderer); + set_render_target(backgroundTexture); + if (backgrounddrawn) { - ScrollSurface(warpbuffer,0,-3); + scroll_texture(backgroundTexture, 0, -3); for (int j = 0; j < 2; j++) { for (int i = 0; i < 21; i++) @@ -2885,19 +2991,20 @@ void Graphics::updatebackground(int t) { //draw the whole thing for the first time! backoffset = 0; - ClearSurface(warpbuffer); + clear(); for (int j = 0; j < 16; j++) { for (int i = 0; i < 21; i++) { - drawtowertile((i * 16), (j * 16)- backoffset - 3, temp+40); - drawtowertile((i * 16)+ 8, (j * 16)- backoffset - 3, temp + 41); - drawtowertile((i * 16), (j * 16)- backoffset + 8 - 3, temp + 80); - drawtowertile((i * 16)+ 8, (j * 16)- backoffset + 8 - 3, temp + 81); + drawtowertile((i * 16), (j * 16) - backoffset - 3, temp + 40); + drawtowertile((i * 16) + 8, (j * 16) - backoffset - 3, temp + 41); + drawtowertile((i * 16), (j * 16) - backoffset + 8 - 3, temp + 80); + drawtowertile((i * 16) + 8, (j * 16) - backoffset + 8 - 3, temp + 81); } } backgrounddrawn = true; } + set_render_target(target); break; } case 5: @@ -2932,15 +3039,20 @@ void Graphics::drawmap(void) { if (!foregrounddrawn) { - ClearSurface(foregroundBuffer); - if(map.tileset==0) + SDL_Texture* target = SDL_GetRenderTarget(gameScreen.m_renderer); + + set_render_target(foregroundTexture); + set_blendmode(foregroundTexture, SDL_BLENDMODE_BLEND); + clear(0, 0, 0, 0); + + if (map.tileset == 0) { for (int j = 0; j < 30; j++) { for (int i = 0; i < 40; i++) { const int tile = map.contents[TILE_IDX(i, j)]; - if(tile>0) drawforetile(i * 8, j * 8, tile); + if (tile > 0) drawforetile(i * 8, j * 8, tile); } } } @@ -2951,7 +3063,7 @@ void Graphics::drawmap(void) for (int it = 0; it < 40; it++) { const int tile = map.contents[TILE_IDX(it, jt)]; - if(tile>0) drawforetile2(it * 8, jt * 8, tile); + if (tile > 0) drawforetile2(it * 8, jt * 8, tile); } } } @@ -2962,39 +3074,47 @@ void Graphics::drawmap(void) for (int i = 0; i < 40; i++) { const int tile = map.contents[TILE_IDX(i, j)]; - if(tile>0) drawforetile3(i * 8, j * 8, tile,map.rcol); + if (tile > 0) drawforetile3(i * 8, j * 8, tile, map.rcol); } } } + set_render_target(target); foregrounddrawn = true; } - SDL_BlitSurface(foregroundBuffer, NULL, backBuffer, NULL); + copy_texture(foregroundTexture, NULL, NULL); } void Graphics::drawfinalmap(void) { - if (!foregrounddrawn) { - ClearSurface(foregroundBuffer); - if(map.tileset==0){ + if (!foregrounddrawn) + { + SDL_Texture* target = SDL_GetRenderTarget(gameScreen.m_renderer); + + set_render_target(foregroundTexture); + set_blendmode(foregroundTexture, SDL_BLENDMODE_BLEND); + clear(0, 0, 0, 0); + if (map.tileset == 0) { for (int j = 0; j < 30; j++) { for (int i = 0; i < 40; i++) { - if((map.contents[TILE_IDX(i, j)])>0) - drawforetile(i * 8, j * 8, map.finalat(i,j)); - } - } - }else if (map.tileset == 1) { - for (int j = 0; j < 30; j++) { - for (int i = 0; i < 40; i++) { - if((map.contents[TILE_IDX(i, j)])>0) - drawforetile2(i * 8, j * 8, map.finalat(i,j)); + if ((map.contents[TILE_IDX(i, j)]) > 0) + drawforetile(i * 8, j * 8, map.finalat(i, j)); } } } - foregrounddrawn=true; + else if (map.tileset == 1) { + for (int j = 0; j < 30; j++) { + for (int i = 0; i < 40; i++) { + if ((map.contents[TILE_IDX(i, j)]) > 0) + drawforetile2(i * 8, j * 8, map.finalat(i, j)); + } + } + } + set_render_target(target); + foregrounddrawn = true; } - SDL_BlitSurface(foregroundBuffer, NULL, backBuffer, NULL); + copy_texture(foregroundTexture, NULL, NULL); } void Graphics::drawtowermap(void) @@ -3026,20 +3146,26 @@ void Graphics::drawtowerspikes(void) void Graphics::drawtowerbackground(const TowerBG& bg_obj) { - ClearSurface(backBuffer); - SDL_BlitSurface(bg_obj.buffer, NULL, bg_obj.buffer_lerp, NULL); - ScrollSurface(bg_obj.buffer_lerp, 0, lerp(0, -bg_obj.bscroll)); - SDL_BlitSurface(bg_obj.buffer_lerp, &towerbuffer_rect, backBuffer, NULL); + clear(); + + const int offset = (int) lerp(0, -bg_obj.bscroll); + const SDL_Rect srcRect = {0, 8 + offset, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS}; + + copy_texture(bg_obj.texture, &srcRect, NULL); } void Graphics::updatetowerbackground(TowerBG& bg_obj) { if (bg_obj.bypos < 0) bg_obj.bypos += 120 * 8; + SDL_Texture* target = SDL_GetRenderTarget(gameScreen.m_renderer); + set_render_target(bg_obj.texture); + if (bg_obj.tdrawback) { int off = bg_obj.scrolldir == 0 ? 0 : bg_obj.bscroll; //Draw the whole thing; needed for every colour cycle! + clear(); for (int j = -1; j < 32; j++) { for (int i = 0; i < 40; i++) @@ -3054,13 +3180,13 @@ void Graphics::updatetowerbackground(TowerBG& bg_obj) else { //just update the bottom - ScrollSurface(bg_obj.buffer, 0, -bg_obj.bscroll); + scroll_texture(bg_obj.texture, 0, -bg_obj.bscroll); if (bg_obj.scrolldir == 0) { for (int i = 0; i < 40; i++) { int temp = map.tower.backat(i, -1, bg_obj.bypos); - drawtowertile3(i * 8, -1*8 - (bg_obj.bypos % 8), temp, bg_obj); + drawtowertile3(i * 8, -1 * 8 - (bg_obj.bypos % 8), temp, bg_obj); temp = map.tower.backat(i, 0, bg_obj.bypos); drawtowertile3(i * 8, -(bg_obj.bypos % 8), temp, bg_obj); } @@ -3070,16 +3196,17 @@ void Graphics::updatetowerbackground(TowerBG& bg_obj) for (int i = 0; i < 40; i++) { int temp = map.tower.backat(i, 29, bg_obj.bypos); - drawtowertile3(i * 8, 29*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); + drawtowertile3(i * 8, 29 * 8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); temp = map.tower.backat(i, 30, bg_obj.bypos); - drawtowertile3(i * 8, 30*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); + drawtowertile3(i * 8, 30 * 8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); temp = map.tower.backat(i, 31, bg_obj.bypos); - drawtowertile3(i * 8, 31*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); + drawtowertile3(i * 8, 31 * 8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); temp = map.tower.backat(i, 32, bg_obj.bypos); - drawtowertile3(i * 8, 32*8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); + drawtowertile3(i * 8, 32 * 8 - (bg_obj.bypos % 8) - bg_obj.bscroll, temp, bg_obj); } } } + set_render_target(target); } SDL_Color Graphics::getcol( int t ) @@ -3251,31 +3378,18 @@ SDL_Color Graphics::getcol( int t ) void Graphics::menuoffrender(void) { - const int usethisoffset = lerp(oldmenuoffset, menuoffset); - SDL_Rect offsetRect = {0, usethisoffset, backBuffer->w, backBuffer->h}; - - BlitSurfaceStandard(backBuffer, NULL, menubuffer, NULL); - BlitSurfaceStandard(menuoffbuffer, NULL, backBuffer, NULL); - BlitSurfaceStandard(menubuffer, NULL, backBuffer, &offsetRect); - - gameScreen.UpdateScreen(backBuffer, NULL); - ClearSurface(backBuffer); -} - -void Graphics::drawhuetile(const int x, const int y, const int tile, const SDL_Color ct) -{ - if (!INBOUNDS_VEC(tile, tiles)) + if (copy_texture(gameplayTexture, NULL, NULL) != 0) { return; } - point tpoint; - tpoint.x = x; - tpoint.y = y; + const int offset = (int) lerp(oldmenuoffset, menuoffset); + const SDL_Rect offsetRect = {0, offset, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS}; - SDL_Rect rect; - setRect(rect,tpoint.x,tpoint.y,tiles_rect.w, tiles_rect.h); - BlitSurfaceColoured(tiles[tile], NULL, backBuffer, &rect, ct); + if (copy_texture(menuTexture, NULL, &offsetRect) != 0) + { + return; + } } SDL_Color Graphics::huetilegetcol(const int t) @@ -3441,15 +3555,31 @@ int Graphics::crewcolour(const int t) void Graphics::flashlight(void) { - FillRect(backBuffer, 0xBB, 0xBB, 0xBB, 0xBB); + set_blendmode(SDL_BLENDMODE_NONE); + + fill_rect(0xBB, 0xBB, 0xBB, 0xBB); } void Graphics::screenshake(void) { - SDL_Rect shakeRect = {screenshake_x, screenshake_y, backBuffer->w, backBuffer->h}; - gameScreen.UpdateScreen(backBuffer, &shakeRect); + if (gameScreen.badSignalEffect) + { + ApplyFilter(); + } - ClearSurface(backBuffer); + set_render_target(tempTexture); + set_blendmode(SDL_BLENDMODE_NONE); + clear(); + + const SDL_Rect shake = {screenshake_x, screenshake_y, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS}; + + copy_texture(gameTexture, NULL, &shake); + + set_render_target(gameTexture); + clear(); + + set_render_target(NULL); + copy_texture(tempTexture, NULL, NULL); } void Graphics::updatescreenshake(void) @@ -3460,7 +3590,16 @@ void Graphics::updatescreenshake(void) void Graphics::render(void) { - gameScreen.UpdateScreen(backBuffer, NULL); + if (gameScreen.badSignalEffect) + { + ApplyFilter(); + } + + set_render_target(NULL); + set_blendmode(SDL_BLENDMODE_NONE); + clear(); + + copy_texture(gameTexture, NULL, NULL, 0, NULL, flipmode ? SDL_FLIP_VERTICAL : SDL_FLIP_NONE); } void Graphics::renderwithscreeneffects(void) @@ -3554,20 +3693,14 @@ void Graphics::bigbrprint(int x, int y, const std::string& s, int r, int g, int void Graphics::drawtele(int x, int y, int t, const SDL_Color color) { SDL_Rect telerect; - setRect(telerect, x , y, tele_rect.w, tele_rect.h ); - if (INBOUNDS_VEC(0, tele)) - { - BlitSurfaceColoured(tele[0], NULL, backBuffer, &telerect, getRGB(16, 16, 16)); - } + setRect(telerect, x, y, tele_rect.w, tele_rect.h); + + draw_grid_tile(grphx.im_teleporter, 0, x, y, tele_rect.w, tele_rect.h, 16, 16, 16); if (t > 9) t = 8; if (t < 1) t = 1; - setRect(telerect, x , y, tele_rect.w, tele_rect.h ); - if (INBOUNDS_VEC(t, tele)) - { - BlitSurfaceColoured(tele[t], NULL, backBuffer, &telerect, color); - } + draw_grid_tile(grphx.im_teleporter, t, x, y, tele_rect.w, tele_rect.h, color); } SDL_Color Graphics::getRGBA(const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a) @@ -3593,63 +3726,37 @@ SDL_Color Graphics::RGBf(int r, int g, int b) void Graphics::drawforetile(int x, int y, int t) { - if (!INBOUNDS_VEC(t, tiles)) - { - WHINE_ONCE("drawforetile() out-of-bounds!"); - return; - } - - SDL_Rect rect; - setRect(rect, x,y,tiles_rect.w, tiles_rect.h); - #if !defined(NO_CUSTOM_LEVELS) if (shouldrecoloroneway(t, tiles1_mounted)) { - const SDL_Color thect = cl.getonewaycol(); - BlitSurfaceTinted(tiles[t], NULL, foregroundBuffer, &rect, thect); + draw_grid_tile(grphx.im_tiles_tint, t, x, y, tiles_rect.w, tiles_rect.h, cl.getonewaycol()); } else #endif { - BlitSurfaceStandard(tiles[t],NULL, foregroundBuffer, &rect ); + draw_grid_tile(grphx.im_tiles, t, x, y, tiles_rect.w, tiles_rect.h); } } void Graphics::drawforetile2(int x, int y, int t) { - if (!INBOUNDS_VEC(t, tiles2)) - { - WHINE_ONCE("drawforetile2() out-of-bounds!"); - return; - } - - SDL_Rect rect; - setRect(rect, x,y,tiles_rect.w, tiles_rect.h); - #if !defined(NO_CUSTOM_LEVELS) if (shouldrecoloroneway(t, tiles2_mounted)) { - const SDL_Color thect = cl.getonewaycol(); - BlitSurfaceTinted(tiles2[t], NULL, foregroundBuffer, &rect, thect); + draw_grid_tile(grphx.im_tiles2_tint, t, x, y, tiles_rect.w, tiles_rect.h, cl.getonewaycol()); } else #endif { - BlitSurfaceStandard(tiles2[t],NULL, foregroundBuffer, &rect ); + draw_grid_tile(grphx.im_tiles2, t, x, y, tiles_rect.w, tiles_rect.h); } } void Graphics::drawforetile3(int x, int y, int t, int off) { t += off * 30; - if (!INBOUNDS_VEC(t, tiles3)) - { - WHINE_ONCE("drawforetile3() out-of-bounds!"); - return; - } - SDL_Rect rect; - setRect(rect, x,y,tiles_rect.w, tiles_rect.h); - BlitSurfaceStandard(tiles3[t],NULL, foregroundBuffer, &rect ); + + draw_grid_tile(grphx.im_tiles3, t, x, y, tiles_rect.w, tiles_rect.h); } void Graphics::drawrect(int x, int y, int w, int h, int r, int g, int b) @@ -3660,21 +3767,21 @@ void Graphics::drawrect(int x, int y, int w, int h, int r, int g, int b) madrect.y = y; madrect.w = w; madrect.h = 1; - FillRect(backBuffer, madrect, getRGB(r, g, b)); + fill_rect(&madrect, getRGB(r, g, b)); madrect.w = 1; madrect.h = h; - FillRect(backBuffer, madrect, getRGB(r, g, b)); + fill_rect(&madrect, getRGB(r, g, b)); madrect.x = x + w - 1; madrect.w = 1; madrect.h = h; - FillRect(backBuffer, madrect, getRGB(r, g, b)); + fill_rect(&madrect, getRGB(r, g, b)); madrect.x = x; madrect.y = y + h - 1; madrect.w = w; madrect.h = 1; - FillRect(backBuffer, madrect, getRGB(r, g, b)); + fill_rect(&madrect, getRGB(r, g, b)); } bool Graphics::onscreen(int t) @@ -3689,27 +3796,23 @@ bool Graphics::reloadresources(void) destroy(); - MAYBE_FAIL(MakeTileArray()); MAYBE_FAIL(MakeSpriteArray()); - MAYBE_FAIL(maketelearray()); MAYBE_FAIL(Makebfont()); - images.clear(); + images[IMAGE_LEVELCOMPLETE] = grphx.im_image0; + images[IMAGE_MINIMAP] = grphx.im_image1; + images[IMAGE_COVERED] = grphx.im_image2; + images[IMAGE_ELEPHANT] = grphx.im_image3; + images[IMAGE_GAMECOMPLETE] = grphx.im_image4; + images[IMAGE_FLIPLEVELCOMPLETE] = grphx.im_image5; + images[IMAGE_FLIPGAMECOMPLETE] = grphx.im_image6; - images.push_back(grphx.im_image0); - images.push_back(grphx.im_image1); - images.push_back(grphx.im_image2); - images.push_back(grphx.im_image3); - images.push_back(grphx.im_image4); - images.push_back(grphx.im_image5); - images.push_back(grphx.im_image6); - - images.push_back(grphx.im_image7); - images.push_back(grphx.im_image8); - images.push_back(grphx.im_image9); - images.push_back(grphx.im_image10); - images.push_back(grphx.im_image11); - images.push_back(grphx.im_image12); + images[IMAGE_SITE] = grphx.im_image7; + images[IMAGE_SITE2] = grphx.im_image8; + images[IMAGE_SITE3] = grphx.im_image9; + images[IMAGE_ENDING] = grphx.im_image10; + images[IMAGE_SITE4] = grphx.im_image11; + images[IMAGE_CUSTOMMINIMAP] = grphx.im_image12; gameScreen.LoadIcon(); @@ -3756,14 +3859,9 @@ SDL_Color Graphics::crewcolourreal(int t) void Graphics::render_roomname(const char* roomname, int r, int g, int b) { footerrect.y = 230; - if (translucentroomname) - { - SDL_BlitSurface(footerbuffer, NULL, backBuffer, &footerrect); - bprint(5, 231, roomname, r, g, b, true); - } - else - { - FillRect(backBuffer, footerrect, 0, 0, 0); - Print(5, 231, roomname, r, g, b, true); - } + + set_blendmode(SDL_BLENDMODE_BLEND); + fill_rect(&footerrect, getRGBA(0, 0, 0, translucentroomname ? 127 : 255)); + bprint(5, 231, roomname, r, g, b, true); + set_blendmode(SDL_BLENDMODE_NONE); } diff --git a/desktop_version/src/Graphics.h b/desktop_version/src/Graphics.h index 17969d1a..e1be7195 100644 --- a/desktop_version/src/Graphics.h +++ b/desktop_version/src/Graphics.h @@ -21,6 +21,24 @@ enum FadeBars FADE_FADING_IN }; +enum ImageNames +{ + IMAGE_LEVELCOMPLETE, + IMAGE_MINIMAP, + IMAGE_COVERED, + IMAGE_ELEPHANT, + IMAGE_GAMECOMPLETE, + IMAGE_FLIPLEVELCOMPLETE, + IMAGE_FLIPGAMECOMPLETE, + IMAGE_SITE, + IMAGE_SITE2, + IMAGE_SITE3, + IMAGE_ENDING, + IMAGE_SITE4, + IMAGE_CUSTOMMINIMAP, + NUM_IMAGES +}; + #define FADEMODE_IS_FADING(mode) ((mode) != FADE_NONE && (mode) != FADE_FULLY_BLACK) class Graphics @@ -29,7 +47,7 @@ public: void init(void); void destroy(void); - void create_buffers(const SDL_PixelFormat* fmt); + void create_buffers(void); void destroy_buffers(void); GraphicsResources grphx; @@ -39,18 +57,13 @@ public: bool Makebfont(void); - void drawhuetile(int x, int y, int t, SDL_Color ct); SDL_Color huetilegetcol(int t); SDL_Color bigchunkygetcol(int t); void drawgravityline(int t); - bool MakeTileArray(void); - bool MakeSpriteArray(void); - bool maketelearray(void); - void drawcoloredtile(int x, int y, int t, int r, int g, int b); void drawmenu(int cr, int cg, int cb, enum Menu::MenuName menu); @@ -134,17 +147,63 @@ public: void drawimagecol(int t, int xp, int yp, SDL_Color ct, bool cent= false); + void draw_texture(SDL_Texture* image, int x, int y); + + void draw_texture_part(SDL_Texture* image, int x, int y, int x2, int y2, int w, int h, int scalex, int scaley); + + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, int scalex, int scaley); + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height); + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, int r, int g, int b, int a, int scalex, int scaley); + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, int r, int g, int b, int a); + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, int r, int g, int b, int scalex, int scaley); + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, int r, int g, int b); + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, SDL_Color color, int scalex, int scaley); + void draw_grid_tile(SDL_Texture* texture, int t, int x, int y, int width, int height, SDL_Color color); + void updatetextboxes(void); void drawgui(void); - void drawsprite(int x, int y, int t, int r, int g, int b); - void drawsprite(int x, int y, int t, SDL_Color color); + void draw_sprite(int x, int y, int t, int r, int g, int b); + void draw_sprite(int x, int y, int t, SDL_Color color); + + void scroll_texture(SDL_Texture* texture, int x, int y); void printcrewname(int x, int y, int t); void printcrewnamedark(int x, int y, int t); void printcrewnamestatus(int x, int y, int t, bool rescued); + int set_render_target(SDL_Texture* texture); + + int set_texture_color_mod(SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b); + + int set_texture_alpha_mod(SDL_Texture* texture, Uint8 alpha); + + int query_texture(SDL_Texture* texture, Uint32* format, int* access, int* w, int* h); + + int set_blendmode(SDL_BlendMode blendmode); + int set_blendmode(SDL_Texture* texture, SDL_BlendMode blendmode); + + int clear(int r, int g, int b, int a); + int clear(); + + int copy_texture(SDL_Texture* texture, const SDL_Rect* src, const SDL_Rect* dest); + int copy_texture(SDL_Texture* texture, const SDL_Rect* src, const SDL_Rect* dest, double angle, const SDL_Point* center, SDL_RendererFlip flip); + + int set_color(Uint8 r, Uint8 g, Uint8 b, Uint8 a); + int set_color(Uint8 r, Uint8 g, Uint8 b); + int set_color(SDL_Color color); + + int fill_rect(const SDL_Rect* rect, int r, int g, int b, int a); + int fill_rect(int x, int y, int w, int h, int r, int g, int b, int a); + int fill_rect(int x, int y, int w, int h, int r, int g, int b); + int fill_rect(int r, int g, int b, int a); + int fill_rect(const SDL_Rect* rect, int r, int g, int b); + int fill_rect(int r, int g, int b); + int fill_rect(const SDL_Rect* rect, SDL_Color color); + int fill_rect(int x, int y, int w, int h, SDL_Color color); + int fill_rect(SDL_Color color); + void map_tab(int opt, const char* text, bool selected = false); void map_option(int opt, int num_opts, const std::string& text, bool selected = false); @@ -261,28 +320,22 @@ public: int m; - std::vector images; + std::vector sprites_surf; + std::vector flipsprites_surf; - std::vector tele; - std::vector tiles; - std::vector tiles2; - std::vector tiles3; - std::vector entcolours; - std::vector sprites; - std::vector flipsprites; - std::vector bfont; - std::vector flipbfont; + SDL_Texture* images[NUM_IMAGES]; bool flipmode; bool setflipmode; bool notextoutline; - //buffer objects. //TODO refactor buffer objects - SDL_Surface* backBuffer; - SDL_Surface* menubuffer; - SDL_Surface* foregroundBuffer; - SDL_Surface* menuoffbuffer; - SDL_Surface* warpbuffer; - SDL_Surface* warpbuffer_lerp; + + SDL_Texture* gameTexture; + SDL_Texture* tempTexture; + SDL_Texture* gameplayTexture; + SDL_Texture* menuTexture; + SDL_Texture* ghostTexture; + SDL_Texture* backgroundTexture; + SDL_Texture* foregroundTexture; TowerBG towerbg; TowerBG titlebg; @@ -291,11 +344,9 @@ public: SDL_Rect sprites_rect; SDL_Rect line_rect; SDL_Rect tele_rect; - SDL_Rect towerbuffer_rect; SDL_Rect prect; SDL_Rect footerrect; - SDL_Surface* footerbuffer; int linestate, linedelay; int backoffset; @@ -340,8 +391,6 @@ public: std::map font_positions; - SDL_Surface* ghostbuffer; - #ifndef GAME_DEFINITION float inline lerp(const float v0, const float v1) { diff --git a/desktop_version/src/GraphicsResources.cpp b/desktop_version/src/GraphicsResources.cpp index 4d742bd5..fb1f4fc9 100644 --- a/desktop_version/src/GraphicsResources.cpp +++ b/desktop_version/src/GraphicsResources.cpp @@ -2,7 +2,9 @@ #include "Alloc.h" #include "FileSystemUtils.h" +#include "GraphicsUtil.h" #include "Vlogging.h" +#include "Screen.h" // Used to load PNG data extern "C" @@ -17,19 +19,15 @@ extern "C" extern const char* lodepng_error_text(unsigned code); } -/* Don't declare `static`, this is used elsewhere */ -SDL_Surface* LoadImage(const char *filename) +static SDL_Surface* LoadImageRaw(const char* filename, unsigned char** data) { //Temporary storage for the image that's loaded SDL_Surface* loadedImage = NULL; - //The optimized image that will be used - SDL_Surface* optimizedImage = NULL; - unsigned char *data; unsigned int width, height; unsigned int error; - unsigned char *fileIn; + unsigned char* fileIn; size_t length; FILESYSTEM_loadAssetToMemory(filename, &fileIn, &length, false); if (fileIn == NULL) @@ -37,7 +35,7 @@ SDL_Surface* LoadImage(const char *filename) SDL_assert(0 && "Image file missing!"); return NULL; } - error = lodepng_decode32(&data, &width, &height, fileIn, length); + error = lodepng_decode32(data, &width, &height, fileIn, length); VVV_free(fileIn); if (error != 0) @@ -47,7 +45,7 @@ SDL_Surface* LoadImage(const char *filename) } loadedImage = SDL_CreateRGBSurfaceWithFormatFrom( - data, + *data, width, height, 32, @@ -55,61 +53,260 @@ SDL_Surface* LoadImage(const char *filename) SDL_PIXELFORMAT_ABGR8888 ); + return loadedImage; +} + +static SDL_Surface* LoadSurfaceFromRaw(SDL_Surface* loadedImage) +{ + SDL_Surface* optimizedImage = SDL_ConvertSurfaceFormat( + loadedImage, + SDL_PIXELFORMAT_ARGB8888, + 0 + ); + SDL_SetSurfaceBlendMode(optimizedImage, SDL_BLENDMODE_BLEND); + return optimizedImage; +} + +/* Can't be static, used in Screen.h */ +SDL_Surface* LoadImageSurface(const char* filename) +{ + unsigned char* data; + + SDL_Surface* loadedImage = LoadImageRaw(filename, &data); + + SDL_Surface* optimizedImage = LoadSurfaceFromRaw(loadedImage); if (loadedImage != NULL) { - optimizedImage = SDL_ConvertSurfaceFormat( - loadedImage, - SDL_PIXELFORMAT_ARGB8888, - 0 - ); VVV_freefunc(SDL_FreeSurface, loadedImage); - VVV_free(data); - SDL_SetSurfaceBlendMode(optimizedImage, SDL_BLENDMODE_BLEND); - return optimizedImage; } - else + + VVV_free(data); + + if (optimizedImage == NULL) { VVV_free(data); vlog_error("Image not found: %s", filename); SDL_assert(0 && "Image not found! See stderr."); + } + + return optimizedImage; +} + +static SDL_Texture* LoadTextureFromRaw(const char* filename, SDL_Surface* loadedImage, const TextureLoadType loadtype) +{ + if (loadedImage == NULL) + { return NULL; } + + // Modify the surface with the load type. + // This could be done in LoadImageRaw, however currently, surfaces are only used for + // pixel perfect collision (which will be changed later) and the window icon. + + switch (loadtype) + { + case TEX_WHITE: + SDL_LockSurface(loadedImage); + for (int y = 0; y < loadedImage->h; y++) + { + for (int x = 0; x < loadedImage->w; x++) + { + SDL_Color color = ReadPixel(loadedImage, x, y); + color.r = 255; + color.g = 255; + color.b = 255; + DrawPixel(loadedImage, x, y, color); + } + } + SDL_UnlockSurface(loadedImage); + break; + case TEX_GRAYSCALE: + SDL_LockSurface(loadedImage); + for (int y = 0; y < loadedImage->h; y++) + { + for (int x = 0; x < loadedImage->w; x++) + { + SDL_Color color = ReadPixel(loadedImage, x, y); + + // Magic numbers used for grayscaling (eyes perceive certain colors brighter than others) + Uint8 r = color.r * 0.299; + Uint8 g = color.g * 0.587; + Uint8 b = color.b * 0.114; + + const double gray = SDL_floor(r + g + b + 0.5); + + color.r = gray; + color.g = gray; + color.b = gray; + + DrawPixel(loadedImage, x, y, color); + } + } + SDL_UnlockSurface(loadedImage); + break; + default: + break; + } + + //Create texture from surface pixels + SDL_Texture* texture = SDL_CreateTextureFromSurface(gameScreen.m_renderer, loadedImage); + if (texture == NULL) + { + vlog_error("Failed creating texture: %s. SDL error: %s\n", filename, SDL_GetError()); + } + + return texture; +} + +static SDL_Texture* LoadImage(const char *filename, const TextureLoadType loadtype) +{ + unsigned char* data; + + SDL_Surface* loadedImage = LoadImageRaw(filename, &data); + + SDL_Texture* texture = LoadTextureFromRaw(filename, loadedImage, loadtype); + + if (loadedImage != NULL) + { + VVV_freefunc(SDL_FreeSurface, loadedImage); + } + + VVV_free(data); + + if (texture == NULL) + { + vlog_error("Image not found: %s", filename); + SDL_assert(0 && "Image not found! See stderr."); + } + + return texture; +} + +static SDL_Texture* LoadImage(const char* filename) +{ + return LoadImage(filename, TEX_COLOR); +} + +/* Any unneeded variants can be NULL */ +static void LoadVariants(const char* filename, SDL_Texture** colored, SDL_Texture** white, SDL_Texture** grayscale) +{ + unsigned char* data; + SDL_Surface* loadedImage = LoadImageRaw(filename, &data); + + if (colored != NULL) + { + *colored = LoadTextureFromRaw(filename, loadedImage, TEX_COLOR); + if (*colored == NULL) + { + vlog_error("Image not found: %s", filename); + SDL_assert(0 && "Image not found! See stderr."); + } + } + + if (grayscale != NULL) + { + *grayscale = LoadTextureFromRaw(filename, loadedImage, TEX_GRAYSCALE); + if (*grayscale == NULL) + { + vlog_error("Image not found: %s", filename); + SDL_assert(0 && "Image not found! See stderr."); + } + } + + if (white != NULL) + { + *white = LoadTextureFromRaw(filename, loadedImage, TEX_WHITE); + if (*white == NULL) + { + vlog_error("Image not found: %s", filename); + SDL_assert(0 && "Image not found! See stderr."); + } + } + + if (loadedImage != NULL) + { + VVV_freefunc(SDL_FreeSurface, loadedImage); + } + + VVV_free(data); +} + +/* The pointers `texture` and `surface` cannot be NULL */ +static void LoadSprites(const char* filename, SDL_Texture** texture, SDL_Surface** surface) +{ + unsigned char* data; + SDL_Surface* loadedImage = LoadImageRaw(filename, &data); + + *texture = LoadTextureFromRaw(filename, loadedImage, TEX_WHITE); + if (*texture == NULL) + { + vlog_error("Image not found: %s", filename); + SDL_assert(0 && "Image not found! See stderr."); + } + + *surface = LoadSurfaceFromRaw(loadedImage); + if (*surface == NULL) + { + vlog_error("Image not found: %s", filename); + SDL_assert(0 && "Image not found! See stderr."); + } + + if (loadedImage != NULL) + { + VVV_freefunc(SDL_FreeSurface, loadedImage); + } + + VVV_free(data); } void GraphicsResources::init(void) { - im_tiles = LoadImage("graphics/tiles.png"); - im_tiles2 = LoadImage("graphics/tiles2.png"); - im_tiles3 = LoadImage("graphics/tiles3.png"); - im_entcolours = LoadImage("graphics/entcolours.png"); - im_sprites = LoadImage("graphics/sprites.png"); - im_flipsprites = LoadImage("graphics/flipsprites.png"); - im_bfont = LoadImage("graphics/font.png"); - im_teleporter = LoadImage("graphics/teleporter.png"); + LoadVariants("graphics/tiles.png", &im_tiles, &im_tiles_white, &im_tiles_tint); + LoadVariants("graphics/tiles2.png", &im_tiles2, NULL, &im_tiles2_tint); + LoadVariants("graphics/entcolours.png", &im_entcolours, NULL, &im_entcolours_tint); - im_image0 = LoadImage("graphics/levelcomplete.png"); - im_image1 = LoadImage("graphics/minimap.png"); - im_image2 = LoadImage("graphics/covered.png"); - im_image3 = LoadImage("graphics/elephant.png"); - im_image4 = LoadImage("graphics/gamecomplete.png"); - im_image5 = LoadImage("graphics/fliplevelcomplete.png"); - im_image6 = LoadImage("graphics/flipgamecomplete.png"); - im_image7 = LoadImage("graphics/site.png"); - im_image8 = LoadImage("graphics/site2.png"); - im_image9 = LoadImage("graphics/site3.png"); - im_image10 = LoadImage("graphics/ending.png"); - im_image11 = LoadImage("graphics/site4.png"); - im_image12 = LoadImage("graphics/minimap.png"); + LoadSprites("graphics/sprites.png", &im_sprites, &im_sprites_surf); + LoadSprites("graphics/flipsprites.png", &im_flipsprites, &im_flipsprites_surf); + + im_tiles3 = LoadImage("graphics/tiles3.png"); + im_bfont = LoadImage("graphics/font.png", TEX_WHITE); + im_teleporter = LoadImage("graphics/teleporter.png", TEX_WHITE); + + im_image0 = LoadImage("graphics/levelcomplete.png"); + im_image1 = LoadImage("graphics/minimap.png"); + im_image2 = LoadImage("graphics/covered.png"); + im_image3 = LoadImage("graphics/elephant.png", TEX_WHITE); + im_image4 = LoadImage("graphics/gamecomplete.png"); + im_image5 = LoadImage("graphics/fliplevelcomplete.png"); + im_image6 = LoadImage("graphics/flipgamecomplete.png"); + im_image7 = LoadImage("graphics/site.png", TEX_WHITE); + im_image8 = LoadImage("graphics/site2.png", TEX_WHITE); + im_image9 = LoadImage("graphics/site3.png", TEX_WHITE); + im_image10 = LoadImage("graphics/ending.png"); + im_image11 = LoadImage("graphics/site4.png", TEX_WHITE); + + im_image12 = SDL_CreateTexture(gameScreen.m_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 240, 180); + + if (im_image12 == NULL) + { + vlog_error("Failed to create minimap texture: %s", SDL_GetError()); + SDL_assert(0 && "Failed to create minimap texture! See stderr."); + return; + } } void GraphicsResources::destroy(void) { -#define CLEAR(img) VVV_freefunc(SDL_FreeSurface, img) +#define CLEAR(img) VVV_freefunc(SDL_DestroyTexture, img) CLEAR(im_tiles); + CLEAR(im_tiles_white); + CLEAR(im_tiles_tint); CLEAR(im_tiles2); + CLEAR(im_tiles2_tint); CLEAR(im_tiles3); CLEAR(im_entcolours); + CLEAR(im_entcolours_tint); CLEAR(im_sprites); CLEAR(im_flipsprites); CLEAR(im_bfont); @@ -129,4 +326,7 @@ void GraphicsResources::destroy(void) CLEAR(im_image11); CLEAR(im_image12); #undef CLEAR + + VVV_freefunc(SDL_FreeSurface, im_sprites_surf); + VVV_freefunc(SDL_FreeSurface, im_flipsprites_surf); } diff --git a/desktop_version/src/GraphicsResources.h b/desktop_version/src/GraphicsResources.h index 9a46706a..f95fd66d 100644 --- a/desktop_version/src/GraphicsResources.h +++ b/desktop_version/src/GraphicsResources.h @@ -3,33 +3,47 @@ #include +enum TextureLoadType +{ + TEX_COLOR, + TEX_WHITE, + TEX_GRAYSCALE +}; + class GraphicsResources { public: void init(void); void destroy(void); - SDL_Surface* im_tiles; - SDL_Surface* im_tiles2; - SDL_Surface* im_tiles3; - SDL_Surface* im_entcolours; - SDL_Surface* im_sprites; - SDL_Surface* im_flipsprites; - SDL_Surface* im_bfont; - SDL_Surface* im_teleporter; - SDL_Surface* im_image0; - SDL_Surface* im_image1; - SDL_Surface* im_image2; - SDL_Surface* im_image3; - SDL_Surface* im_image4; - SDL_Surface* im_image5; - SDL_Surface* im_image6; - SDL_Surface* im_image7; - SDL_Surface* im_image8; - SDL_Surface* im_image9; - SDL_Surface* im_image10; - SDL_Surface* im_image11; - SDL_Surface* im_image12; + SDL_Surface* im_sprites_surf; + SDL_Surface* im_flipsprites_surf; + + SDL_Texture* im_tiles; + SDL_Texture* im_tiles_white; + SDL_Texture* im_tiles_tint; + SDL_Texture* im_tiles2; + SDL_Texture* im_tiles2_tint; + SDL_Texture* im_tiles3; + SDL_Texture* im_entcolours; + SDL_Texture* im_entcolours_tint; + SDL_Texture* im_sprites; + SDL_Texture* im_flipsprites; + SDL_Texture* im_bfont; + SDL_Texture* im_teleporter; + SDL_Texture* im_image0; + SDL_Texture* im_image1; + SDL_Texture* im_image2; + SDL_Texture* im_image3; + SDL_Texture* im_image4; + SDL_Texture* im_image5; + SDL_Texture* im_image6; + SDL_Texture* im_image7; + SDL_Texture* im_image8; + SDL_Texture* im_image9; + SDL_Texture* im_image10; + SDL_Texture* im_image11; + SDL_Texture* im_image12; }; #endif /* GRAPHICSRESOURCES_H */ diff --git a/desktop_version/src/GraphicsUtil.cpp b/desktop_version/src/GraphicsUtil.cpp index 845d7de5..ea2d9eb2 100644 --- a/desktop_version/src/GraphicsUtil.cpp +++ b/desktop_version/src/GraphicsUtil.cpp @@ -3,8 +3,12 @@ #include #include "Alloc.h" +#include "Constants.h" #include "Graphics.h" #include "Maths.h" +#include "Screen.h" +#include "UtilityClass.h" +#include "Vlogging.h" @@ -52,20 +56,6 @@ static SDL_Surface* RecreateSurfaceWithDimensions( return retval; } -static SDL_Surface* RecreateSurface(SDL_Surface* surface) -{ - if (surface == NULL) - { - return NULL; - } - - return RecreateSurfaceWithDimensions( - surface, - surface->w, - surface->h - ); -} - SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, int height ) { // Create an SDL_Rect with the area of the _surface @@ -89,7 +79,7 @@ SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, i return preSurface; } -static void DrawPixel(SDL_Surface* surface, const int x, const int y, const SDL_Color color) +void DrawPixel(SDL_Surface* surface, const int x, const int y, const SDL_Color color) { const SDL_PixelFormat* fmt = surface->format; const int bpp = fmt->BytesPerPixel; @@ -130,188 +120,6 @@ SDL_Color ReadPixel(const SDL_Surface* surface, const int x, const int y) return color; } -SDL_Surface * ScaleSurface( SDL_Surface *_surface, int Width, int Height, SDL_Surface * Dest ) -{ - if(!_surface || !Width || !Height) - return 0; - - SDL_Surface *_ret; - if(Dest == NULL) - { - _ret = RecreateSurfaceWithDimensions(_surface, Width, Height); - if(_ret == NULL) - { - return NULL; - } - - } - else - { - _ret = Dest; - } - - SDL_BlitScaled(_surface, NULL, _ret, NULL); - - return _ret; -} - -SDL_Surface * FlipSurfaceVerticle(SDL_Surface* _src) -{ - SDL_Surface * ret = RecreateSurface(_src); - if(ret == NULL) - { - return NULL; - } - - for(Sint32 y = 0; y < _src->h; y++) - { - for(Sint32 x = 0; x < _src->w; x++) - { - DrawPixel(ret, x ,(_src->h-1) - y ,ReadPixel(_src, x, y)); - } - - - } - - return ret; -} - -void BlitSurfaceStandard( SDL_Surface* _src, SDL_Rect* _srcRect, SDL_Surface* _dest, SDL_Rect* _destRect ) -{ - SDL_BlitSurface( _src, _srcRect, _dest, _destRect ); -} - -static void BlitSurfaceTransform( - SDL_Surface* src, - const SDL_Rect* src_rect, - SDL_Surface* dest, - SDL_Rect* dest_rect, - SDL_Color (*transform)(SDL_Color pixel, SDL_Color color), - const SDL_Color color -) { - if (src == NULL || dest == NULL || transform == NULL) - { - return; - } - if (color.a == 0) - { - return; - } - - SDL_Rect orig_rect; - if (src_rect == NULL) - { - setRect(orig_rect, 0, 0, src->w, src->h); - } - else - { - orig_rect = *src_rect; - } - int blit_x; - int blit_y; - if (dest_rect == NULL) - { - blit_x = 0; - blit_y = 0; - } - else - { - blit_x = dest_rect->x; - blit_y = dest_rect->y; - } - - /* FIXME: Find a way to do this without allocating... */ - SDL_Surface* tempsurface = RecreateSurfaceWithDimensions(src, orig_rect.w, orig_rect.h); - if (tempsurface == NULL) - { - return; - } - SDL_SetSurfaceBlendMode(tempsurface, SDL_BLENDMODE_BLEND); - - for (int x = 0; x < orig_rect.w; x++) - { - for (int y = 0; y < orig_rect.h; y++) - { - if (blit_x + x < 0 || blit_y + y < 0 || - blit_x + x >= dest->w || blit_y + y >= dest->h) - { - continue; - } - - const SDL_Color pixel = ReadPixel(src, orig_rect.x + x, orig_rect.y + y); - if (pixel.a == 0) - { - continue; - } - - const SDL_Color result = transform(pixel, color); - DrawPixel(tempsurface, x, y, result); - } - } - - SDL_Rect final_rect = {blit_x, blit_y, 0, 0}; - SDL_BlitSurface(tempsurface, NULL, dest, &final_rect); - VVV_freefunc(SDL_FreeSurface, tempsurface); -} - -static SDL_Color transform_color(const SDL_Color pixel, const SDL_Color color) -{ - const float div1 = pixel.a / 255.0f; - const float div2 = color.a / 255.0f; - const Uint8 alpha = (div1 * div2) * 255.0f; - const SDL_Color result = {color.r, color.g, color.b, alpha}; - return result; -} - -void BlitSurfaceColoured( - SDL_Surface* src, - const SDL_Rect* src_rect, - SDL_Surface* dest, - SDL_Rect* dest_rect, - const SDL_Color color -) { - return BlitSurfaceTransform( - src, src_rect, dest, dest_rect, transform_color, color - ); -} - -static SDL_Color transform_tint(const SDL_Color pixel, const SDL_Color color) -{ - double red = pixel.r * 0.299; - double green = pixel.g * 0.587; - double blue = pixel.b * 0.114; - - const double gray = SDL_floor(red + green + blue + 0.5); - - red = gray * color.r / 255.0; - green = gray * color.g / 255.0; - blue = gray * color.b / 255.0; - - red = SDL_clamp(red, 0, 255); - green = SDL_clamp(green, 0, 255); - blue = SDL_clamp(blue, 0, 255); - - const float div1 = pixel.a / 255.0f; - const float div2 = color.a / 255.0f; - const Uint8 alpha = (div1 * div2) * 255.0f; - - const SDL_Color result = {(Uint8) red, (Uint8) green, (Uint8) blue, alpha}; - return result; -} - -void BlitSurfaceTinted( - SDL_Surface* src, - const SDL_Rect* src_rect, - SDL_Surface* dest, - SDL_Rect* dest_rect, - const SDL_Color color -) { - return BlitSurfaceTransform( - src, src_rect, dest, dest_rect, transform_tint, color - ); -} - - static int oldscrollamount = 0; static int scrollamount = 0; static bool isscrolling = 0; @@ -336,15 +144,40 @@ void UpdateFilter(void) } } -SDL_Surface* ApplyFilter(SDL_Surface* src) +void ApplyFilter(void) { - SDL_Surface* ret = RecreateSurface(src); + // Copy the screen to a temporary surface + SDL_Surface* src = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0); + if (src == NULL) + { + return; + } + + const int result = SDL_RenderReadPixels(gameScreen.m_renderer, NULL, 0, src->pixels, src->pitch); + if (result != 0) + { + SDL_FreeSurface(src); + WHINE_ONCE_ARGS(("Could not read pixels from renderer: %s", SDL_GetError())); + return; + } + + Uint32 rawFormat; + + if (graphics.query_texture(graphics.gameTexture, &rawFormat, NULL, NULL, NULL) != 0) + { + return; + } + + SDL_PixelFormat* format = SDL_AllocFormat(rawFormat); + + // Have a second surface to do work on + SDL_Surface* dest = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0); const int red_offset = rand() % 4; - for (int x = 0; x < ret->w; x++) + for (int x = 0; x < src->w; x++) { - for (int y = 0; y < ret->h; y++) + for (int y = 0; y < src->h; y++) { const int sampley = (y + (int) graphics.lerp(oldscrollamount, scrollamount)) % 240; @@ -389,137 +222,14 @@ SDL_Surface* ApplyFilter(SDL_Surface* src) blue = SDL_max(blue - (distX + distY), 0); const SDL_Color color = {red, green, blue, pixel.a}; - DrawPixel(ret, x, y, color); + DrawPixel(dest, x, y, color); } } - return ret; -} - -void FillRect( SDL_Surface* _surface, const int _x, const int _y, const int _w, const int _h, const int r, int g, int b ) -{ - SDL_Rect rect = {_x, _y, _w, _h}; - Uint32 color = SDL_MapRGB(_surface->format, r, g, b); - SDL_FillRect(_surface, &rect, color); -} - -void FillRect( SDL_Surface* _surface, const int r, int g, int b ) -{ - Uint32 color = SDL_MapRGB(_surface->format, r, g, b); - SDL_FillRect(_surface, NULL, color); -} - -void FillRect( SDL_Surface* _surface, SDL_Rect& _rect, const int r, int g, int b ) -{ - Uint32 color = SDL_MapRGB(_surface->format, r, g, b); - SDL_FillRect(_surface, &_rect, color); -} - -void FillRect(SDL_Surface* surface, const SDL_Rect rect, const SDL_Color color) -{ - const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a); - SDL_FillRect(surface, &rect, mapped); -} - -void FillRect(SDL_Surface* surface, const SDL_Color color) -{ - const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a); - SDL_FillRect(surface, NULL, mapped); -} - -void FillRect(SDL_Surface* surface, const int x, const int y, const int w, const int h, const SDL_Color color) -{ - const SDL_Rect rect = {x, y, w, h}; - const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a); - SDL_FillRect(surface, &rect, mapped); -} - -void FillRect(SDL_Surface* surface, const int r, const int g, const int b, const int a) -{ - const Uint32 mapped = SDL_MapRGBA(surface->format, r, g, b, a); - SDL_FillRect(surface, NULL, mapped); -} - -void ClearSurface(SDL_Surface* surface) -{ - SDL_FillRect(surface, NULL, 0x00000000); -} - -void ScrollSurface( SDL_Surface* _src, int _pX, int _pY ) -{ - SDL_Surface* part1 = NULL; - - SDL_Rect rect1; - SDL_Rect rect2; - //scrolling up; - if(_pY < 0) - { - setRect(rect2, 0, 0, _src->w, _src->h - _pY); - - part1 = GetSubSurface(_src, rect2.x, rect2.y, rect2.w, rect2.h); - - SDL_Rect destrect1; - - SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); - - setRect(destrect1, 0, _pY, _pX, _src->h); - - SDL_BlitSurface (part1, NULL, _src, &destrect1); - } - - else if(_pY > 0) - { - - setRect(rect1, 0, 0, _src->w, _src->h - _pY); - - part1 = GetSubSurface(_src, rect1.x, rect1.y, rect1.w, rect1.h); - - SDL_Rect destrect1; - - SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); - - setRect(destrect1, _pX, _pY, _src->w, _src->h - _pY); - - SDL_BlitSurface (part1, NULL, _src, &destrect1); - - } - - //Right - else if(_pX <= 0) - { - setRect(rect2, 0, 0, _src->w - _pX, _src->h ); - - part1 = GetSubSurface(_src, rect2.x, rect2.y, rect2.w, rect2.h); - - SDL_Rect destrect1; - - SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); - - setRect(destrect1, _pX, 0, _src->w - _pX, _src->h); - - SDL_BlitSurface (part1, NULL, _src, &destrect1); - } - - else if(_pX > 0) - { - - setRect(rect1, _pX, 0, _src->w - _pX, _src->h ); - - part1 = GetSubSurface(_src, rect1.x, rect1.y, rect1.w, rect1.h); - - SDL_Rect destrect1; - - SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); - - setRect(destrect1, 0, 0, _src->w - _pX, _src->h); - - SDL_BlitSurface (part1, NULL, _src, &destrect1); - - } - //Cleanup temp surface - if (part1) - { - VVV_freefunc(SDL_FreeSurface, part1); - } - + SDL_FreeFormat(format); + + SDL_UpdateTexture(graphics.gameTexture, NULL, dest->pixels, dest->pitch); + + SDL_FreeSurface(src); + SDL_FreeSurface(dest); } diff --git a/desktop_version/src/GraphicsUtil.h b/desktop_version/src/GraphicsUtil.h index 321c8493..c4544d9c 100644 --- a/desktop_version/src/GraphicsUtil.h +++ b/desktop_version/src/GraphicsUtil.h @@ -7,36 +7,11 @@ void setRect(SDL_Rect& _r, int x, int y, int w, int h); SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, int height ); +void DrawPixel(SDL_Surface* surface, int x, int y, SDL_Color color); + SDL_Color ReadPixel(const SDL_Surface* surface, int x, int y); -SDL_Surface * ScaleSurface( SDL_Surface *Surface, int Width, int Height, SDL_Surface * Dest = NULL ); - -void BlitSurfaceStandard( SDL_Surface* _src, SDL_Rect* _srcRect, SDL_Surface* _dest, SDL_Rect* _destRect ); - -void BlitSurfaceColoured(SDL_Surface* src, const SDL_Rect* src_rect, SDL_Surface* dest, SDL_Rect* dest_rect, SDL_Color color); - -void BlitSurfaceTinted(SDL_Surface* src, const SDL_Rect* src_rect, SDL_Surface* dest, SDL_Rect* dest_rect, SDL_Color color); - -void FillRect( SDL_Surface* surface, const int x, const int y, const int w, const int h, const int r, int g, int b ); - -void FillRect( SDL_Surface* surface, const int r, int g, int b ); - -void FillRect( SDL_Surface* surface, SDL_Rect& rect, const int r, int g, int b ); - -void FillRect(SDL_Surface* surface, SDL_Rect rect, SDL_Color color); - -void FillRect(SDL_Surface* surface, SDL_Color color); - -void FillRect(SDL_Surface* surface, int x, int y, int w, int h, SDL_Color color); - -void FillRect(SDL_Surface* surface, int r, int g, int b, int a); - -void ClearSurface(SDL_Surface* surface); - -void ScrollSurface(SDL_Surface* _src, int pX, int py); - -SDL_Surface * FlipSurfaceVerticle(SDL_Surface* _src); void UpdateFilter(void); -SDL_Surface* ApplyFilter( SDL_Surface* _src ); +void ApplyFilter(void); #endif /* GRAPHICSUTIL_H */ diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index b19fb3a5..d95237bd 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -3072,9 +3072,6 @@ static void mapmenuactionpress(const bool version2_2) case 11: //quit to menu - //Kill contents of offset render buffer, since we do that for some reason. - //This fixes an apparent frame flicker. - ClearSurface(graphics.menuoffbuffer); graphics.fademode = FADE_START_FADEOUT; music.fadeout(); map.nexttowercolour(); diff --git a/desktop_version/src/KeyPoll.cpp b/desktop_version/src/KeyPoll.cpp index 34775b48..ee63c44f 100644 --- a/desktop_version/src/KeyPoll.cpp +++ b/desktop_version/src/KeyPoll.cpp @@ -361,6 +361,7 @@ void KeyPoll::Poll(void) } } SDL_DisableScreenSaver(); + gameScreen.recacheTextures(); break; case SDL_WINDOWEVENT_FOCUS_LOST: if (!game.disablepause) diff --git a/desktop_version/src/Logic.cpp b/desktop_version/src/Logic.cpp index b001e992..a2545729 100644 --- a/desktop_version/src/Logic.cpp +++ b/desktop_version/src/Logic.cpp @@ -1406,15 +1406,18 @@ void gamelogic(void) if (map.finalmode && map.final_colormode) { map.final_aniframedelay--; - if(map.final_aniframedelay==0) + if (map.final_aniframedelay == 0) { - graphics.foregrounddrawn=false; + graphics.foregrounddrawn = false; } - if (map.final_aniframedelay <= 0) { + if (map.final_aniframedelay <= 0) + { map.final_aniframedelay = 2; map.final_aniframe++; if (map.final_aniframe >= 4) + { map.final_aniframe = 0; + } } } diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index feffedb8..3fc40b34 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -1085,7 +1085,7 @@ void mapclass::gotoroom(int rx, int ry) //Do we need to reload the background? bool redrawbg = game.roomx != game.prevroomx || game.roomy != game.prevroomy; - if(redrawbg) + if (redrawbg) { graphics.backgrounddrawn = false; //Used for background caching speedup } diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index cee3cadb..a147e720 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -147,12 +147,12 @@ static void menurender(void) case Menu::mainmenu: { const int temp = 50; - graphics.drawsprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 3 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 3 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); #if defined(MAKEANDPLAY) const char* editionlabel = loc::gettext("MAKE AND PLAY EDITION"); graphics.Print(264-graphics.len(editionlabel),temp+35,editionlabel,tr, tg, tb); @@ -435,16 +435,16 @@ static void menurender(void) graphics.Print( -1, 50, loc::gettext("VVVVVV is a game by"), tr, tg, tb, true); graphics.bigprint( 40, 65, "Terry Cavanagh", tr, tg, tb, true, 2); - graphics.drawimagecol(7, -1, 86, graphics.getRGB(tr, tg, tb), true); + graphics.drawimagecol(IMAGE_SITE, -1, 86, graphics.getRGB(tr, tg, tb), true); graphics.Print( -1, 120, loc::gettext("and features music by"), tr, tg, tb, true); graphics.bigprint( 40, 135, "Magnus Pålsson", tr, tg, tb, true, 2); - graphics.drawimagecol(8, -1, 156, graphics.getRGB(tr, tg, tb), true); + graphics.drawimagecol(IMAGE_SITE2, -1, 156, graphics.getRGB(tr, tg, tb), true); break; case Menu::credits2: graphics.Print( -1, 50, loc::gettext("Roomnames are by"), tr, tg, tb, true); graphics.bigprint( 40, 65, "Bennett Foddy", tr, tg, tb, true); - graphics.drawimagecol(9, -1, 86, graphics.getRGB(tr, tg, tb), true); + graphics.drawimagecol(IMAGE_SITE3, -1, 86, graphics.getRGB(tr, tg, tb), true); graphics.Print( -1, 110, loc::gettext("C++ version by"), tr, tg, tb, true); graphics.bigprint( 40, 125, "Simon Roth", tr, tg, tb, true); graphics.bigprint( 40, 145, "Ethan Lee", tr, tg, tb, true); @@ -713,7 +713,7 @@ static void menurender(void) int box_x = SDL_min(10, (320-overflow.max_w_px)/2); int box_h = overflow.max_h_px - SDL_max(0, 10-loc::get_langmeta()->font_h); - FillRect(graphics.backBuffer, box_x-1, 30-1, overflow.max_w_px+2, box_h+2, tr/3, tg/3, tb/3); + graphics.fill_rect(box_x-1, 30-1, overflow.max_w_px+2, box_h+2, tr/3, tg/3, tb/3); int wraplimit; if (overflow.multiline) @@ -1029,7 +1029,7 @@ static void menurender(void) graphics.bigprint(-1, 30, loc::gettext("Text Outline"), tr, tg, tb, true); int next_y = graphics.PrintWrap(-1, 65, loc::gettext("Disables outline on game text."), tr, tg, tb, true); - FillRect(graphics.backBuffer, 0, next_y-4, 320, 16, tr, tg, tb); + graphics.fill_rect(0, next_y-4, 320, 16, tr, tg, tb); if (!graphics.notextoutline) { @@ -1142,8 +1142,8 @@ static void menurender(void) ); graphics.Print(262-graphics.len(buffer), 132-20, buffer, 255 - (help.glow / 2), 255 - (help.glow / 2), 255 - (help.glow / 2)); - graphics.drawsprite(34, 126-20, 50, graphics.col_clock); - graphics.drawsprite(270, 126-20, 22, graphics.col_trinket); + graphics.draw_sprite(34, 126-20, 50, graphics.col_clock); + graphics.draw_sprite(270, 126-20, 22, graphics.col_trinket); break; } case 1: @@ -1166,8 +1166,8 @@ static void menurender(void) ); graphics.Print(262-graphics.len(buffer), 132-20, buffer, 255 - (help.glow / 2), 255 - (help.glow / 2), 255 - (help.glow / 2)); - graphics.drawsprite(34, 126-20, 50, graphics.col_clock); - graphics.drawsprite(270, 126-20, 22, graphics.col_trinket); + graphics.draw_sprite(34, 126-20, 50, graphics.col_clock); + graphics.draw_sprite(270, 126-20, 22, graphics.col_trinket); break; } } @@ -1597,9 +1597,7 @@ static void menurender(void) void titlerender(void) { - - ClearSurface(graphics.backBuffer); - + graphics.clear(); if (!game.menustart) { tr = graphics.col_tr; @@ -1607,12 +1605,12 @@ void titlerender(void) tb = graphics.col_tb; int temp = 50; - graphics.drawsprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 3 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 3 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); #if defined(MAKEANDPLAY) const char* editionlabel = loc::gettext("MAKE AND PLAY EDITION"); graphics.Print(264-graphics.len(editionlabel),temp+35,editionlabel,tr, tg, tb); @@ -1650,7 +1648,7 @@ void titlerender(void) void gamecompleterender(void) { - ClearSurface(graphics.backBuffer); + graphics.clear(); if(!game.colourblindmode) graphics.drawtowerbackground(graphics.titlebg); @@ -1665,12 +1663,12 @@ void gamecompleterender(void) if (graphics.onscreen(220 + position)) { int temp = 220 + position; - graphics.drawsprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 3 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); - graphics.drawsprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 3 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 4 * 32, temp, 23, tr, tg, tb); + graphics.draw_sprite((160 - 96) + 5 * 32, temp, 23, tr, tg, tb); } if (graphics.onscreen(290 + position)) graphics.bigprint( -1, 290 + position, loc::gettext("Starring"), tr, tg, tb, true, 2); @@ -1802,9 +1800,9 @@ void gamecompleterender(void) void gamecompleterender2(void) { - ClearSurface(graphics.backBuffer); + graphics.clear(); - graphics.drawimage(10, 0, 0); + graphics.drawimage(IMAGE_ENDING, 0, 0); for (int j = 0; j < 30; j++) { @@ -1814,18 +1812,18 @@ void gamecompleterender2(void) { if (i > game.creditposx) { - FillRect(graphics.backBuffer, i * 8, j * 8, 8, 8, 0, 0, 0); + graphics.fill_rect(i * 8, j * 8, 8, 8, 0, 0, 0); } } if (j > game.creditposy) { - FillRect(graphics.backBuffer, i * 8, j * 8, 8, 8, 0, 0, 0); + graphics.fill_rect(i * 8, j * 8, 8, 8, 0, 0, 0); } } } - FillRect(graphics.backBuffer, graphics.lerp(game.oldcreditposx * 8, game.creditposx * 8) + 8, game.creditposy * 8, 8, 8, 0, 0, 0); + graphics.fill_rect(graphics.lerp(game.oldcreditposx * 8, game.creditposx * 8) + 8, game.creditposy * 8, 8, 8, 0, 0, 0); graphics.drawfade(); @@ -1855,12 +1853,11 @@ static const char* interact_prompt( void gamerender(void) { - - + graphics.set_render_target(graphics.gameplayTexture); + graphics.set_color(0, 0, 0, 255); if(!game.blackout) { - if (map.towermode) { if (!game.colourblindmode) @@ -1869,7 +1866,7 @@ void gamerender(void) } else { - ClearSurface(graphics.backBuffer); + graphics.clear(); } graphics.drawtowermap(); } @@ -1881,7 +1878,7 @@ void gamerender(void) } else { - ClearSurface(graphics.backBuffer); + graphics.clear(); } if ((map.finalmode || map.custommode) && map.final_colormode) { @@ -1962,7 +1959,10 @@ void gamerender(void) graphics.cutscenebars(); graphics.drawfade(); - BlitSurfaceStandard(graphics.backBuffer, NULL, graphics.menuoffbuffer, NULL); + + graphics.set_render_target(graphics.gameTexture); + + graphics.copy_texture(graphics.gameplayTexture, NULL, NULL); graphics.drawgui(); if (graphics.flipmode) @@ -2280,13 +2280,13 @@ static void rendermap(void) if (map.custommode && map.customshowmm) { graphics.drawpixeltextbox(35 + map.custommmxoff, 16 + map.custommmyoff, map.custommmxsize + 10, map.custommmysize + 10, 65, 185, 207); - graphics.drawpartimage(graphics.minimap_mounted ? 1 : 12, 40 + map.custommmxoff, 21 + map.custommmyoff, map.custommmxsize, map.custommmysize); + graphics.drawpartimage(graphics.minimap_mounted ? IMAGE_MINIMAP : IMAGE_CUSTOMMINIMAP, 40 + map.custommmxoff, 21 + map.custommmyoff, map.custommmxsize, map.custommmysize); return; } #endif /* NO_CUSTOM_LEVELS */ graphics.drawpixeltextbox(35, 16, 250, 190, 65, 185, 207); - graphics.drawimage(1, 40, 21, false); + graphics.drawimage(IMAGE_MINIMAP, 40, 21, false); } static void rendermapfog(void) @@ -2304,7 +2304,7 @@ static void rendermapfog(void) { for (int y = 0; y < data.zoom; y++) { - graphics.drawimage(2, data.xoff + 40 + (x * 12) + (i * (12 * data.zoom)), data.yoff + 21 + (y * 9) + (j * (9 * data.zoom)), false); + graphics.drawimage(IMAGE_COVERED, data.xoff + 40 + (x * 12) + (i * (12 * data.zoom)), data.yoff + 21 + (y * 9) + (j * (9 * data.zoom)), false); } } } @@ -2383,12 +2383,13 @@ static void rendermapcursor(const bool flashing) void maprender(void) { - ClearSurface(graphics.backBuffer); + graphics.set_render_target(graphics.menuTexture); + graphics.clear(); draw_roomname_menu(); //Background color - FillRect(graphics.backBuffer,0, 12, 320, 240, 10, 24, 26 ); + graphics.fill_rect(0, 12, 320, 240, 10, 24, 26 ); //Menubar: graphics.drawtextbox( -10, 212, 43, 3, 65, 185, 207); @@ -2458,7 +2459,7 @@ void maprender(void) { for (int i = 0; i < 20; i++) { - graphics.drawimage(2, 40 + (i * 12), 21 + (j * 9), false); + graphics.drawimage(IMAGE_COVERED, 40 + (i * 12), 21 + (j * 9), false); } } graphics.bprint(-1, 105, loc::gettext("NO SIGNAL"), 245, 245, 245, true); @@ -2746,8 +2747,8 @@ void maprender(void) ); graphics.Print(262 - graphics.len(buffer), FLIP(132, 8), buffer, 255 - help.glow/2, 255 - help.glow/2, 255 - help.glow/2); - graphics.drawsprite(34, FLIP(126, 17), 50, graphics.col_clock); - graphics.drawsprite(270, FLIP(126, 17), 22, graphics.col_trinket); + graphics.draw_sprite(34, FLIP(126, 17), 50, graphics.col_clock); + graphics.draw_sprite(270, FLIP(126, 17), 22, graphics.col_trinket); break; } case 10: @@ -2851,19 +2852,7 @@ void maprender(void) } - - - - // We need to draw the black screen above the menu in order to disguise it - // being jankily brought down in glitchrunner mode when exiting to the title - // Otherwise, there's no reason to obscure the menu - if (GlitchrunnerMode_less_than_or_equal(Glitchrunner2_2) - || FADEMODE_IS_FADING(graphics.fademode) - || game.fadetomenu - || game.fadetolab) - { - graphics.drawfade(); - } + graphics.set_render_target(graphics.gameTexture); if (graphics.resumegamemode || graphics.menuoffset > 0 || graphics.oldmenuoffset > 0) { @@ -2871,22 +2860,38 @@ void maprender(void) } else { - graphics.renderwithscreeneffects(); + graphics.copy_texture(graphics.menuTexture, NULL, NULL); } + + // We need to draw the black screen above the menu in order to disguise it + // being jankily brought down in glitchrunner mode when exiting to the title + // Otherwise, there's no reason to obscure the menu + if (GlitchrunnerMode_less_than_or_equal(Glitchrunner2_2) + || FADEMODE_IS_FADING(graphics.fademode) + || game.fadetomenu + || game.fadetolab) + { + graphics.drawfade(); + } + + + graphics.renderwithscreeneffects(); } #undef FLIP void teleporterrender(void) { - ClearSurface(graphics.backBuffer); + graphics.set_render_target(graphics.menuTexture); + graphics.clear(); + const int telex = map.teleporters[game.teleport_to_teleporter].x; const int teley = map.teleporters[game.teleport_to_teleporter].y; draw_roomname_menu(); //Background color - FillRect(graphics.backBuffer, 0, 12, 320, 240, 10, 24, 26); + graphics.fill_rect(0, 12, 320, 240, 10, 24, 26); rendermap(); rendermapfog(); @@ -2944,6 +2949,7 @@ void teleporterrender(void) if (game.advancetext) graphics.bprint(5, 5, loc::gettext("- Press ACTION to advance text -"), 220 - (help.glow), 220 - (help.glow), 255 - (help.glow / 2), true); } + graphics.set_render_target(graphics.gameTexture); if (graphics.resumegamemode || graphics.menuoffset > 0 || graphics.oldmenuoffset > 0) { @@ -2951,6 +2957,8 @@ void teleporterrender(void) } else { - graphics.render(); + graphics.copy_texture(graphics.menuTexture, NULL, NULL); } + + graphics.render(); } diff --git a/desktop_version/src/RoomnameTranslator.cpp b/desktop_version/src/RoomnameTranslator.cpp index 326df873..51c0e612 100644 --- a/desktop_version/src/RoomnameTranslator.cpp +++ b/desktop_version/src/RoomnameTranslator.cpp @@ -3,6 +3,7 @@ #include "Constants.h" #include "Game.h" #include "Graphics.h" +#include "GraphicsUtil.h" #include "KeyPoll.h" #include "Localization.h" #include "LocalizationMaint.h" @@ -54,7 +55,9 @@ namespace roomname_translator fullscreen_rect.y = 0; fullscreen_rect.w = 320; fullscreen_rect.h = 240; - SDL_BlitSurface(dimbuffer, NULL, graphics.backBuffer, &fullscreen_rect); + graphics.set_blendmode(SDL_BLENDMODE_BLEND); + graphics.fill_rect(0, 0, 0, 96); + graphics.set_blendmode(SDL_BLENDMODE_NONE); if (help_screen) { graphics.bprint(0, 0, "=== Room name translation mode help ===", 255,255,255); diff --git a/desktop_version/src/Screen.cpp b/desktop_version/src/Screen.cpp index f159dbdb..bb428ab4 100644 --- a/desktop_version/src/Screen.cpp +++ b/desktop_version/src/Screen.cpp @@ -7,8 +7,10 @@ #include "Constants.h" #include "FileSystemUtils.h" #include "Game.h" +#include "Graphics.h" #include "GraphicsUtil.h" #include "InterimVersion.h" +#include "Render.h" #include "Vlogging.h" void ScreenSettings_default(struct ScreenSettings* _this) @@ -26,8 +28,6 @@ void Screen::init(const struct ScreenSettings* settings) { m_window = NULL; m_renderer = NULL; - m_screenTexture = NULL; - m_screen = NULL; isWindowed = !settings->fullscreen; scalingMode = settings->scalingMode; isFiltered = settings->linearFilter; @@ -46,13 +46,18 @@ void Screen::init(const struct ScreenSettings* settings) // Uncomment this next line when you need to debug -flibit // SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER, "software", SDL_HINT_OVERRIDE); - SDL_CreateWindowAndRenderer( + + m_window = SDL_CreateWindow( + "VVVVVV", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH_PIXELS * 2, SCREEN_HEIGHT_PIXELS * 2, - SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI, - &m_window, - &m_renderer + SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI ); + + m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + #ifdef INTERIM_VERSION_EXISTS /* Branch name limits are ill-defined but on GitHub it's ~256 chars * ( https://stackoverflow.com/a/24014513/ ). @@ -66,25 +71,6 @@ void Screen::init(const struct ScreenSettings* settings) LoadIcon(); - // FIXME: This surface should be the actual backbuffer! -flibit - m_screen = SDL_CreateRGBSurface( - 0, - SCREEN_WIDTH_PIXELS, - SCREEN_HEIGHT_PIXELS, - 32, - 0x00FF0000, - 0x0000FF00, - 0x000000FF, - 0xFF000000 - ); - m_screenTexture = SDL_CreateTexture( - m_renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, - SCREEN_WIDTH_PIXELS, - SCREEN_HEIGHT_PIXELS - ); - badSignalEffect = settings->badSignal; ResizeScreen(settings->windowWidth, settings->windowHeight); @@ -93,8 +79,6 @@ void Screen::init(const struct ScreenSettings* settings) void Screen::destroy(void) { /* Order matters! */ - VVV_freefunc(SDL_DestroyTexture, m_screenTexture); - VVV_freefunc(SDL_FreeSurface, m_screen); VVV_freefunc(SDL_DestroyRenderer, m_renderer); VVV_freefunc(SDL_DestroyWindow, m_window); } @@ -121,11 +105,11 @@ void Screen::LoadIcon(void) } #else -SDL_Surface* LoadImage(const char* filename); +SDL_Surface* LoadImageSurface(const char* filename); void Screen::LoadIcon(void) { - SDL_Surface* icon = LoadImage("VVVVVV.png"); + SDL_Surface* icon = LoadImageSurface("VVVVVV.png"); if (icon == NULL) { return; @@ -149,6 +133,7 @@ void Screen::ResizeScreen(int x, int y) if (!isWindowed || isForcedFullscreen()) { int result = SDL_SetWindowFullscreen(m_window, SDL_WINDOW_FULLSCREEN_DESKTOP); + recacheTextures(); if (result != 0) { vlog_error("Error: could not set the game to fullscreen mode: %s", SDL_GetError()); @@ -158,6 +143,7 @@ void Screen::ResizeScreen(int x, int y) else { int result = SDL_SetWindowFullscreen(m_window, 0); + recacheTextures(); if (result != 0) { vlog_error("Error: could not set the game to windowed mode: %s", SDL_GetError()); @@ -266,66 +252,10 @@ void Screen::GetWindowSize(int* x, int* y) } } -void Screen::UpdateScreen(SDL_Surface* buffer, SDL_Rect* rect ) +void Screen::RenderPresent() { - if((buffer == NULL) && (m_screen == NULL) ) - { - return; - } - - if(badSignalEffect) - { - buffer = ApplyFilter(buffer); - } - - - ClearSurface(m_screen); - BlitSurfaceStandard(buffer,NULL,m_screen,rect); - - if(badSignalEffect) - { - VVV_freefunc(SDL_FreeSurface, buffer); - } - -} - -const SDL_PixelFormat* Screen::GetFormat(void) -{ - return m_screen->format; -} - -void Screen::FlipScreen(const bool flipmode) -{ - static const SDL_Rect filterSubrect = {1, 1, 318, 238}; - - SDL_RendererFlip flip_flags; - if (flipmode) - { - flip_flags = SDL_FLIP_VERTICAL; - } - else - { - flip_flags = SDL_FLIP_NONE; - } - - SDL_UpdateTexture( - m_screenTexture, - NULL, - m_screen->pixels, - m_screen->pitch - ); - SDL_RenderCopyEx( - m_renderer, - m_screenTexture, - isFiltered ? &filterSubrect : NULL, - NULL, - 0.0, - NULL, - flip_flags - ); SDL_RenderPresent(m_renderer); - SDL_RenderClear(m_renderer); - ClearSurface(m_screen); + graphics.clear(); } void Screen::toggleFullScreen(void) @@ -354,20 +284,49 @@ void Screen::toggleLinearFilter(void) isFiltered ? "linear" : "nearest", SDL_HINT_OVERRIDE ); - SDL_DestroyTexture(m_screenTexture); - m_screenTexture = SDL_CreateTexture( + SDL_DestroyTexture(graphics.gameTexture); + graphics.gameTexture = SDL_CreateTexture( m_renderer, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, + SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS ); + + if (graphics.gameTexture == NULL) + { + vlog_error("Could not create game texture: %s", SDL_GetError()); + return; + } } void Screen::toggleVSync(void) { vsync = !vsync; SDL_RenderSetVSync(m_renderer, (int) vsync); + + recacheTextures(); +} + +void Screen::recacheTextures(void) +{ + // Fix for d3d9, which clears target textures sometimes (ex. toggling vsync, switching fullscreen, etc...) + + // Signal cached textures to be redrawn fully + graphics.backgrounddrawn = false; + graphics.foregrounddrawn = false; + graphics.towerbg.tdrawback = true; + graphics.titlebg.tdrawback = true; + + if (game.ingame_titlemode) + { + // Redraw the cached gameplay texture if we're in the in-game menu. + // Additionally, reset alpha so things don't jitter when re-entering gameplay. + float oldAlpha = graphics.alpha; + graphics.alpha = 0; + gamerender(); + graphics.alpha = oldAlpha; + } } /* FIXME: Launching in forced fullscreen then exiting and relaunching in normal diff --git a/desktop_version/src/Screen.h b/desktop_version/src/Screen.h index 66c86e7a..6a419d6d 100644 --- a/desktop_version/src/Screen.h +++ b/desktop_version/src/Screen.h @@ -19,16 +19,15 @@ public: void ResizeToNearestMultiple(void); void GetWindowSize(int* x, int* y); - void UpdateScreen(SDL_Surface* buffer, SDL_Rect* rect); - void FlipScreen(bool flipmode); - - const SDL_PixelFormat* GetFormat(void); + void RenderPresent(); void toggleFullScreen(void); void toggleScalingMode(void); void toggleLinearFilter(void); void toggleVSync(void); + void recacheTextures(void); + bool isForcedFullscreen(void); bool isWindowed; @@ -39,8 +38,6 @@ public: SDL_Window *m_window; SDL_Renderer *m_renderer; - SDL_Texture *m_screenTexture; - SDL_Surface* m_screen; }; #ifndef GAMESCREEN_DEFINITION diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 7831c924..f972f0fd 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -175,41 +175,54 @@ void scriptclass::run(void) #if !defined(NO_CUSTOM_LEVELS) if (words[0] == "warpdir") { - int temprx=ss_toi(words[1])-1; - int tempry=ss_toi(words[2])-1; + int temprx = ss_toi(words[1]) - 1; + int tempry = ss_toi(words[2]) - 1; const RoomProperty* room; cl.setroomwarpdir(temprx, tempry, ss_toi(words[3])); room = cl.getroomprop(temprx, tempry); //Do we update our own room? - if(game.roomx-100==temprx && game.roomy-100==tempry){ + if (game.roomx - 100 == temprx && game.roomy - 100 == tempry) + { //If screen warping, then override all that: graphics.backgrounddrawn = false; - map.warpx=false; map.warpy=false; - if(room->warpdir==0){ + map.warpx = false; + map.warpy = false; + if (room->warpdir == 0) + { map.background = 1; //Be careful, we could be in a Lab or Warp Zone room... - if(room->tileset==2){ + if (room->tileset == 2) + { //Lab map.background = 2; graphics.rcol = room->tilecol; - }else if(room->tileset==3){ + } + else if (room->tileset == 3) + { //Warp Zone map.background = 6; } - }else if(room->warpdir==1){ - map.warpx=true; - map.background=3; - graphics.rcol = cl.getwarpbackground(temprx,tempry); - }else if(room->warpdir==2){ - map.warpy=true; - map.background=4; - graphics.rcol = cl.getwarpbackground(temprx,tempry); - }else if(room->warpdir==3){ - map.warpx=true; map.warpy=true; + } + else if (room->warpdir == 1) + { + map.warpx = true; + map.background = 3; + graphics.rcol = cl.getwarpbackground(temprx, tempry); + } + else if (room->warpdir == 2) + { + map.warpy = true; + map.background = 4; + graphics.rcol = cl.getwarpbackground(temprx, tempry); + } + else if (room->warpdir == 3) + { + map.warpx = true; + map.warpy = true; map.background = 5; - graphics.rcol = cl.getwarpbackground(temprx,tempry); + graphics.rcol = cl.getwarpbackground(temprx, tempry); } } } diff --git a/desktop_version/src/TowerBG.h b/desktop_version/src/TowerBG.h index 0f5af644..2be0bc23 100644 --- a/desktop_version/src/TowerBG.h +++ b/desktop_version/src/TowerBG.h @@ -5,8 +5,7 @@ struct TowerBG { - SDL_Surface* buffer; - SDL_Surface* buffer_lerp; + SDL_Texture* texture; bool tdrawback; int bypos; int bscroll; diff --git a/desktop_version/src/UtilityClass.h b/desktop_version/src/UtilityClass.h index 6d11d1f6..4f6594bc 100644 --- a/desktop_version/src/UtilityClass.h +++ b/desktop_version/src/UtilityClass.h @@ -46,6 +46,15 @@ void VVV_fillstring( } \ do { } while (false) +#define WHINE_ONCE_ARGS(args) \ + static bool whine = true; \ + if (whine) \ + { \ + whine = false; \ + vlog_error args; \ + } \ + do { } while (false) + /* Don't call this directly; use the VVV_between macro. */ void _VVV_between( const char* original, diff --git a/desktop_version/src/main.cpp b/desktop_version/src/main.cpp index 37479e36..79a51723 100644 --- a/desktop_version/src/main.cpp +++ b/desktop_version/src/main.cpp @@ -584,34 +584,12 @@ int main(int argc, char *argv[]) vlog_info("\t\t"); vlog_info("\t\t"); - //Set up screen - - - - - // Load Ini - - + // Set up screen graphics.init(); game.init(); game.seed_use_sdl_getticks = seed_use_sdl_getticks; - // This loads music too... - if (!graphics.reloadresources()) - { - /* Something wrong with the default assets? We can't use them to - * display the error message, and we have to bail. */ - SDL_ShowSimpleMessageBox( - SDL_MESSAGEBOX_ERROR, - graphics.error_title, - graphics.error, - NULL - ); - - VVV_exit(1); - } - game.gamestate = PRELOADER; game.menustart = false; @@ -636,11 +614,26 @@ int main(int argc, char *argv[]) gameScreen.init(&screen_settings); } + // This loads music too... + if (!graphics.reloadresources()) + { + /* Something wrong with the default assets? We can't use them to + * display the error message, and we have to bail. */ + SDL_ShowSimpleMessageBox( + SDL_MESSAGEBOX_ERROR, + graphics.error_title, + graphics.error, + NULL + ); + + VVV_exit(1); + } + loc::loadtext(false); loc::loadlanguagelist(); game.createmenu(Menu::mainmenu); - graphics.create_buffers(gameScreen.GetFormat()); + graphics.create_buffers(); if (game.skipfakeload) game.gamestate = TITLEMODE; @@ -790,9 +783,10 @@ static void cleanup(void) { game.savestatsandsettings(); } - gameScreen.destroy(); + graphics.grphx.destroy(); graphics.destroy_buffers(); + gameScreen.destroy(); graphics.destroy(); music.destroy(); map.destroy(); @@ -849,9 +843,13 @@ static void inline deltaloop(void) if (implfunc->type == Func_delta && implfunc->func != NULL) { + graphics.clear(); + + graphics.set_render_target(graphics.gameTexture); + implfunc->func(); - gameScreen.FlipScreen(graphics.flipmode); + gameScreen.RenderPresent(); } } } @@ -873,7 +871,7 @@ static void unfocused_run(void) { if (!game.blackout) { - ClearSurface(graphics.backBuffer); + graphics.fill_rect(0, 0, 0); #define FLIP(YPOS) graphics.flipmode ? 232 - YPOS : YPOS graphics.bprint(5, FLIP(110), loc::gettext("Game paused"), 196 - help.glow, 255 - help.glow, 196 - help.glow, true); graphics.bprint(5, FLIP(120), loc::gettext("[click to resume]"), 196 - help.glow, 255 - help.glow, 196 - help.glow, true); diff --git a/desktop_version/src/preloader.cpp b/desktop_version/src/preloader.cpp index 469bd28b..6fd93750 100644 --- a/desktop_version/src/preloader.cpp +++ b/desktop_version/src/preloader.cpp @@ -95,15 +95,15 @@ void preloaderrender(void) pre_temprecty = (i * 16)- pre_offset; if (i % 2 == 0) { - FillRect(graphics.backBuffer, pre_temprectx, pre_temprecty, pre_temprectw,pre_temprecth, pre_lightcol); + graphics.fill_rect(pre_temprectx, pre_temprecty, pre_temprectw,pre_temprecth, pre_lightcol); } else { - FillRect(graphics.backBuffer, pre_temprectx, pre_temprecty, pre_temprectw,pre_temprecth, pre_darkcol); + graphics.fill_rect(pre_temprectx, pre_temprecty, pre_temprectw,pre_temprecth, pre_darkcol); } } - FillRect(graphics.backBuffer, pre_frontrectx, pre_frontrecty, pre_frontrectw,pre_frontrecth, graphics.getRGB(0x3E,0x31,0xA2)); + graphics.fill_rect(pre_frontrectx, pre_frontrecty, pre_frontrectw,pre_frontrecth, graphics.getRGB(0x3E,0x31,0xA2)); print_percentage = true; @@ -114,12 +114,12 @@ void preloaderrender(void) }else if (pre_transition <= -10) { //Switch to TITLEMODE (handled by preloaderrenderfixed) }else if (pre_transition < 5) { - ClearSurface(graphics.backBuffer); + graphics.fill_rect(0, 0, 0); }else if (pre_transition < 20) { pre_temprecty = 0; pre_temprecth = 240; - ClearSurface(graphics.backBuffer); - FillRect(graphics.backBuffer, pre_frontrectx, pre_frontrecty, pre_frontrectw,pre_frontrecth, graphics.getRGB(0x3E,0x31,0xA2)); + graphics.fill_rect(0, 0, 0); + graphics.fill_rect(pre_frontrectx, pre_frontrecty, pre_frontrectw,pre_frontrecth, graphics.getRGB(0x3E,0x31,0xA2)); print_percentage = true; }