Maelstrom: Blit high res sprites at the correct display size

https://github.com/libsdl-org/Maelstrom/commit/1edca3f510f2bf327c7c117d1500908efc130759

From 1edca3f510f2bf327c7c117d1500908efc130759 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 2 Oct 2012 00:38:01 -0700
Subject: [PATCH] Blit high res sprites at the correct display size

---
 game/Maelstrom.h           |  3 +++
 game/game.cpp              |  6 ++++--
 game/game.h                |  2 +-
 game/object.cpp            |  2 +-
 game/player.cpp            |  6 +++---
 game/shinobi.h             |  2 +-
 screenlib/SDL_FrameBuf.cpp | 24 ++++++++++++++----------
 screenlib/SDL_FrameBuf.h   | 14 ++++++++++----
 screenlib/UIDrawEngine.cpp |  6 +++---
 9 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/game/Maelstrom.h b/game/Maelstrom.h
index b057cc79..ff5c34c8 100644
--- a/game/Maelstrom.h
+++ b/game/Maelstrom.h
@@ -59,6 +59,9 @@
 #define	SHOT_SIZE		4
 #define	SHOT_SCALE_FACTOR	4
 
+#define SHIELD_SIZE		32
+#define THRUST_SIZE		16
+
 #define	STATUS_HEIGHT		14
 #define	SHIELD_WIDTH		55
 #define	INITIAL_BONUS		2000
diff --git a/game/game.cpp b/game/game.cpp
index da9eb859..b3221231 100644
--- a/game/game.cpp
+++ b/game/game.cpp
@@ -1006,8 +1006,10 @@ void GetRenderCoordinates(int &x, int &y)
 /* ----------------------------------------------------------------- */
 /* -- Render a sprite on the screen */
 
-void RenderSprite(int x, int y, SDL_Texture *sprite)
+void RenderSprite(SDL_Texture *sprite, int x, int y, int w, int h)
 {
 	GetRenderCoordinates(x, y);
-	screen->QueueBlit(x, y, sprite);
+	w = (int)(((float)w * gScrnRect.w) / GAME_WIDTH);
+	h = (int)(((float)h * gScrnRect.h) / GAME_HEIGHT);
+	screen->QueueBlit(sprite, x, y, w, h, DOCLIP);
 }
diff --git a/game/game.h b/game/game.h
index 596128f6..22619384 100644
--- a/game/game.h
+++ b/game/game.h
@@ -73,6 +73,6 @@ class GamePanelDelegate : public UIPanelDelegate
 extern void NewGame(void);
 extern void ContinueGame(void);
 extern void GetRenderCoordinates(int &x, int &y);
-extern void RenderSprite(int x, int y, SDL_Texture *sprite);
+extern void RenderSprite(SDL_Texture *sprite, int x, int y, int w, int h);
 
 #endif // _game_h
diff --git a/game/object.cpp b/game/object.cpp
index 0a364fc1..f59de63d 100644
--- a/game/object.cpp
+++ b/game/object.cpp
@@ -101,7 +101,7 @@ Object::Move(int Frozen)		// This is called every timestep.
 void
 Object::BlitSprite(void)
 {
-	RenderSprite(x, y, myblit->sprite[phase]);
+	RenderSprite(myblit->sprite[phase], x, y, xsize, ysize);
 }
 
 /* Sound functions */
diff --git a/game/player.cpp b/game/player.cpp
index 09742939..c9ac9289 100644
--- a/game/player.cpp
+++ b/game/player.cpp
@@ -628,11 +628,11 @@ Player::BlitSprite(void)
 
 	/* Draw the new shots */
 	OBJ_LOOP(i, numshots) {
-		RenderSprite(shots[i]->x, shots[i]->y, gPlayerShot);
+		RenderSprite(gPlayerShot, shots[i]->x, shots[i]->y, SHOT_SIZE, SHOT_SIZE);
 	}
 	/* Draw the shield, if necessary */
 	if ( ! gPaused && (AutoShield || (ShieldOn && (ShieldLevel > 0))) ) {
-		RenderSprite(x, y, gShieldBlit->sprite[Sphase]);
+		RenderSprite(gShieldBlit->sprite[Sphase], x, y, SHIELD_SIZE, SHIELD_SIZE);
 		Sphase = !Sphase;
 	}
 	/* Draw the thrust, if necessary */
@@ -640,7 +640,7 @@ Player::BlitSprite(void)
 		int thrust_x, thrust_y;
 		thrust_x = x + gThrustOrigins[phase].h;
 		thrust_y = y + gThrustOrigins[phase].v;
-		RenderSprite(thrust_x, thrust_y, ThrustBlit->sprite[phase]);
+		RenderSprite(ThrustBlit->sprite[phase], thrust_x, thrust_y, THRUST_SIZE, THRUST_SIZE);
 		if ( ThrustBlit == gThrust1 )
 			ThrustBlit = gThrust2;
 		else
diff --git a/game/shinobi.h b/game/shinobi.h
index 3cf25d07..7da83a9e 100644
--- a/game/shinobi.h
+++ b/game/shinobi.h
@@ -202,7 +202,7 @@ class Shinobi : public Object {
 		/* Draw the new shots */
 		int i;
 		OBJ_LOOP(i, numshots) {
-			RenderSprite(shots[i]->x, shots[i]->y, gEnemyShot);
+			RenderSprite(gEnemyShot, shots[i]->x, shots[i]->y, SHOT_SIZE, SHOT_SIZE);
 		}
 		Object::BlitSprite();
 	}
diff --git a/screenlib/SDL_FrameBuf.cpp b/screenlib/SDL_FrameBuf.cpp
index 9e6b61a5..5d6cae97 100644
--- a/screenlib/SDL_FrameBuf.cpp
+++ b/screenlib/SDL_FrameBuf.cpp
@@ -166,30 +166,34 @@ FrameBuf:: GetDisplaySize(int &w, int &h)
 }
 
 void
-FrameBuf:: QueueBlit(int dstx, int dsty, SDL_Texture *src,
-			int srcx, int srcy, int w, int h, clipval do_clip)
+FrameBuf:: QueueBlit(SDL_Texture *src,
+			int srcx, int srcy, int srcw, int srch,
+			int dstx, int dsty, int dstw, int dsth, clipval do_clip)
 {
 	SDL_Rect srcrect;
 	SDL_Rect dstrect;
 
 	srcrect.x = srcx;
 	srcrect.y = srcy;
-	srcrect.w = w;
-	srcrect.h = h;
+	srcrect.w = srcw;
+	srcrect.h = srch;
 	dstrect.x = dstx;
 	dstrect.y = dsty;
-	dstrect.w = w;
-	dstrect.h = h;
+	dstrect.w = dstw;
+	dstrect.h = dsth;
 	if (do_clip == DOCLIP) {
+		float scaleX = (float)srcrect.w / dstrect.w;
+		float scaleY = (float)srcrect.h / dstrect.h;
+
 		if (!SDL_IntersectRect(&clip, &dstrect, &dstrect)) {
 			return;
 		}
 
 		/* Adjust the source rectangle to match */
-		srcrect.x += (dstrect.x - dstx);
-		srcrect.y += (dstrect.y - dsty);
-		srcrect.w = dstrect.w;
-		srcrect.h = dstrect.h;
+		srcrect.x += (int)((dstrect.x - dstx) * scaleX);
+		srcrect.y += (int)((dstrect.y - dsty) * scaleY);
+		srcrect.w = (int)(dstrect.w * scaleX);
+		srcrect.h = (int)(dstrect.h * scaleY);
 	}
 	SDL_RenderCopy(renderer, src, &srcrect, &dstrect);
 }
diff --git a/screenlib/SDL_FrameBuf.h b/screenlib/SDL_FrameBuf.h
index e8617fb0..eb0197ca 100644
--- a/screenlib/SDL_FrameBuf.h
+++ b/screenlib/SDL_FrameBuf.h
@@ -110,12 +110,18 @@ class FrameBuf : public ErrorBase {
 	void GetDisplaySize(int &w, int &h);
 
 	/* Blit and update routines */
-	void QueueBlit(int dstx, int dsty, SDL_Texture *src,
-			int srcx, int srcy, int w, int h, clipval do_clip);
-	void QueueBlit(int x, int y, SDL_Texture *src, clipval do_clip = DOCLIP) {
+	void QueueBlit(SDL_Texture *src,
+			int srcx, int srcy, int srcw, int srch,
+			int dstx, int dsty, int dstw, int dsth, clipval do_clip);
+	void QueueBlit(SDL_Texture *src, int x, int y, int w, int h, clipval do_clip) {
+		int srcw, srch;
+		SDL_QueryTexture(src, NULL, NULL, &srcw, &srch);
+		QueueBlit(src, 0, 0, srcw, srch, x, y, w, h, do_clip);
+	}
+	void QueueBlit(SDL_Texture *src, int x, int y, clipval do_clip) {
 		int w, h;
 		SDL_QueryTexture(src, NULL, NULL, &w, &h);
-		QueueBlit(x, y, src, 0, 0, w, h, do_clip);
+		QueueBlit(src, 0, 0, w, h, x, y, w, h, do_clip);
 	}
 	void StretchBlit(const SDL_Rect *dstrect, SDL_Texture *src, const SDL_Rect *srcrect);
 
diff --git a/screenlib/UIDrawEngine.cpp b/screenlib/UIDrawEngine.cpp
index 991c158c..fb801c67 100644
--- a/screenlib/UIDrawEngine.cpp
+++ b/screenlib/UIDrawEngine.cpp
@@ -127,7 +127,7 @@ UIDrawEngine::OnDraw()
 	SDL_Texture *image = m_element->GetImage();
 	if (image) {
 		UIArea *area = m_element->GetImageArea();
-		m_screen->QueueBlit(area->X(), area->Y(), image, NOCLIP);
+		m_screen->QueueBlit(image, area->X(), area->Y(), NOCLIP);
 	}
 
 	if (m_textImage) {
@@ -139,12 +139,12 @@ UIDrawEngine::OnDraw()
 			m_screen->GetRGB(m_element->GetTextShadowColor(), &r, &g, &b);
 			SDL_SetTextureColorMod(m_textImage, r, g, b);
 
-			m_screen->QueueBlit(area->X()+x, area->Y()+y, m_textImage, NOCLIP);
+			m_screen->QueueBlit(m_textImage, area->X()+x, area->Y()+y, NOCLIP);
 
 			m_screen->GetRGB(m_element->GetCurrentColor(), &r, &g, &b);
 			SDL_SetTextureColorMod(m_textImage, r, g, b);
 		}
-		m_screen->QueueBlit(area->X(), area->Y(), m_textImage, NOCLIP);
+		m_screen->QueueBlit(m_textImage, area->X(), area->Y(), NOCLIP);
 	}
 }