Browse Source

High DPI support for the invaders and luainvaders samples

Michael Ragazzon 4 years ago
parent
commit
9e7f04c20b
38 changed files with 154 additions and 134 deletions
  1. 14 14
      Samples/invaders/data/game.rml
  2. 5 5
      Samples/invaders/data/help.rml
  3. 10 10
      Samples/invaders/data/high_score.rml
  4. 2 2
      Samples/invaders/data/logo.rml
  5. 2 2
      Samples/invaders/data/main_menu.rml
  6. 3 3
      Samples/invaders/data/options.rml
  7. 2 2
      Samples/invaders/data/pause.rml
  8. 6 6
      Samples/invaders/data/start_game.rml
  9. 3 3
      Samples/invaders/src/Defender.cpp
  10. 1 1
      Samples/invaders/src/Defender.h
  11. 2 1
      Samples/invaders/src/ElementGame.cpp
  12. 4 4
      Samples/invaders/src/Game.cpp
  13. 1 1
      Samples/invaders/src/Game.h
  14. 3 3
      Samples/invaders/src/Invader.cpp
  15. 1 1
      Samples/invaders/src/Invader.h
  16. 6 3
      Samples/invaders/src/Shield.cpp
  17. 1 1
      Samples/invaders/src/Shield.h
  18. 10 4
      Samples/invaders/src/Sprite.cpp
  19. 1 1
      Samples/invaders/src/Sprite.h
  20. 14 14
      Samples/luainvaders/data/game.rml
  21. 5 5
      Samples/luainvaders/data/help.rml
  22. 10 10
      Samples/luainvaders/data/high_score.rml
  23. 2 2
      Samples/luainvaders/data/logo.rml
  24. 2 2
      Samples/luainvaders/data/main_menu.rml
  25. 3 3
      Samples/luainvaders/data/options.rml
  26. 2 2
      Samples/luainvaders/data/pause.rml
  27. 6 6
      Samples/luainvaders/data/start_game.rml
  28. 3 3
      Samples/luainvaders/src/Defender.cpp
  29. 1 1
      Samples/luainvaders/src/Defender.h
  30. 2 1
      Samples/luainvaders/src/ElementGame.cpp
  31. 4 4
      Samples/luainvaders/src/Game.cpp
  32. 1 1
      Samples/luainvaders/src/Game.h
  33. 3 3
      Samples/luainvaders/src/Invader.cpp
  34. 1 1
      Samples/luainvaders/src/Invader.h
  35. 6 3
      Samples/luainvaders/src/Shield.cpp
  36. 1 1
      Samples/luainvaders/src/Shield.h
  37. 10 4
      Samples/luainvaders/src/Sprite.cpp
  38. 1 1
      Samples/luainvaders/src/Sprite.h

+ 14 - 14
Samples/invaders/data/game.rml

@@ -6,8 +6,8 @@
 		<style>
 			body
 			{
-				padding: 0px;
-				margin: 0px;
+				padding: 0dp;
+				margin: 0dp;
 				width: 100%;
 				height: 100%;
 
@@ -23,11 +23,11 @@
 			
 			div
 			{
-				height: 47px;
-				padding: 8px 0px 0px 65px;
-				margin: 0px 20px;
+				height: 47dp;
+				padding: 8dp 0 0 65dp;
+				margin: 0 20dp;
 
-				font-size: 20px;
+				font-size: 20dp;
 
 				decorator: tiled-horizontal( huditem-l, huditem-c, huditem-r );
 			}
@@ -35,36 +35,36 @@
 			div#score_div
 			{
 				float: left;
-				width: 155px;
+				width: 155dp;
 			}
 
 			div#hiscore_div
 			{
 				float: left;
-				width: 205px;
+				width: 205dp;
 			}
 
 			div#waves_div
 			{
 				float: right;
-				width: 95px;
+				width: 95dp;
 			}
 
 			div#lives_div
 			{
 				float: right;
-				width: 80px;
+				width: 80dp;
 			}
 			
 			icon
 			{
 				display: block;
 				position: absolute;
-				left: 14px;
-				top: 3px;
+				left: 14dp;
+				top: 3dp;
 
-				width: 51px;
-				height: 39px;
+				width: 51dp;
+				height: 39dp;
 			}
 
 			div#score_div icon

+ 5 - 5
Samples/invaders/data/help.rml

@@ -31,20 +31,20 @@
 		</p>
 		<h1>The X-42</h1>
 		<p>
-			The culmination of <img src="help_defender.tga" style="float: left; margin: -6px -24px;" />decades of research and the pinnacle of Earth's technology, the X-42 'Defender' is the finest weapon mankind has to fight the alien menace. Equipped with the dual-layer ablative tridranium armour, low-velocity depleted-narconium chain-fed belt gun and state-of-the-art liquid-hydrangea turbo-thrusters, it is still going to be nearly impossible for its pilot to secure the safety of mankind.
+			The culmination of <img src="help_defender.tga" style="float: left; margin: -6dp -24dp;" />decades of research and the pinnacle of Earth's technology, the X-42 'Defender' is the finest weapon mankind has to fight the alien menace. Equipped with the dual-layer ablative tridranium armour, low-velocity depleted-narconium chain-fed belt gun and state-of-the-art liquid-hydrangea turbo-thrusters, it is still going to be nearly impossible for its pilot to secure the safety of mankind.
 		</p>
 		<h1>The Invaders</h1>
 		<p>
-			The most numerous <img src="help_invader_rank1.tga" style="float: left; margin: -4px 0px;" />invader you'll face is a primitive drone that is primarily employed by its Martian overlords in the mines of Cydonia. It is large, ungainly and poorly-armed, so ill-suited to its new role as the backbone of the invasion fleet. However, whatever it lacks in pugilistic prowess it makes up for with numbers. Each drone is worth 10 points.
+			The most numerous <img src="help_invader_rank1.tga" style="float: left; margin: -4dp 0dp;" />invader you'll face is a primitive drone that is primarily employed by its Martian overlords in the mines of Cydonia. It is large, ungainly and poorly-armed, so ill-suited to its new role as the backbone of the invasion fleet. However, whatever it lacks in pugilistic prowess it makes up for with numbers. Each drone is worth 10 points.
 		</p>
 		<p>
-			Behind the drones <img src="help_invader_rank2.tga" style="float: right; margin: -4px 0px;" />stand the formidable berserker units, encased in their zyterium battle-suits and wielding the dreaded Nimbus death-rods. A lone unit is no match for a skilled X-42 pilot, but in large groups they adopt complex flight patterns that can confuse even the best targetting computer. Pick them off and separate them when you can. Each berserker is worth 20 points.
+			Behind the drones <img src="help_invader_rank2.tga" style="float: right; margin: -4dp 0dp;" />stand the formidable berserker units, encased in their zyterium battle-suits and wielding the dreaded Nimbus death-rods. A lone unit is no match for a skilled X-42 pilot, but in large groups they adopt complex flight patterns that can confuse even the best targetting computer. Pick them off and separate them when you can. Each berserker is worth 20 points.
 		</p>
 		<p>
-			The dreaded commander <img src="help_invader_rank3.tga" style="float: left; margin: -4px 0px;" />death-droids lie at the back of every Martian wave. Small, nimble and deadly, these ships are the true test of an X-42 pilot's abilities. Consider yourself warned, and watch out especially for their mind control attack! Each droid is worth 40 points.
+			The dreaded commander <img src="help_invader_rank3.tga" style="float: left; margin: -4dp 0dp;" />death-droids lie at the back of every Martian wave. Small, nimble and deadly, these ships are the true test of an X-42 pilot's abilities. Consider yourself warned, and watch out especially for their mind control attack! Each droid is worth 40 points.
 		</p>
 		<p>
-			Occasionally one of the <img src="help_invader_mothership.tga" style="float: right; margin: -6px -12px;" /> invasion motherships will drop into low-orbit to provide the Martian Overbrain with a close look at the progress of the battle; this is when they are most vulnerable, destroy them if you can! The loss of even a single mothership will be keenly felt by the fleet. The points value of each mothership is variable, depending on the seniority of its command synapse.
+			Occasionally one of the <img src="help_invader_mothership.tga" style="float: right; margin: -6dp -12dp;" /> invasion motherships will drop into low-orbit to provide the Martian Overbrain with a close look at the progress of the battle; this is when they are most vulnerable, destroy them if you can! The loss of even a single mothership will be keenly felt by the fleet. The points value of each mothership is variable, depending on the seniority of its command synapse.
 		</p>
 		<p>
 			Destroy all the invaders in each wave before any get past your ship to invade Earth, unleash their deadly toxin and wipe out all of humanity!

+ 10 - 10
Samples/invaders/data/high_score.rml

@@ -5,8 +5,8 @@
 	<style>
 		body
 		{
-			width: 440px;
-			height: 440px;
+			width: 440dp;
+			height: 440dp;
 			
 			margin: auto;
 		}
@@ -18,18 +18,18 @@
 		defender
 		{
 			display: inline-block;
-			width: 64px;
-			height: 16px;
+			width: 64dp;
+			height: 16dp;
 			
 			decorator: defender( high_scores_defender.tga );
 		}
 		tbody tr {
-			height: 30px;
+			height: 30dp;
 		}
 		tbody td
 		{
-			padding-top: 5px;
-			height: 30px;
+			padding-top: 5dp;
+			height: 30dp;
 			white-space: nowrap;
 			overflow: hidden;
 		}
@@ -39,10 +39,10 @@
 	<table data-model="high_scores">
 		<thead>
 			<tr>
-				<td style="width: 200%; margin-left: 10px;">Pilot</td>
-				<td style="min-width: 64px;">Ship</td>
+				<td style="width: 200%; margin-left: 10dp;">Pilot</td>
+				<td style="min-width: 64dp;">Ship</td>
 				<td>Wave</td>
-				<td style="min-width: 64px;">Score</td>
+				<td style="min-width: 64dp;">Score</td>
 			</tr>
 		</thead>
 		<tbody>

+ 2 - 2
Samples/invaders/data/logo.rml

@@ -12,8 +12,8 @@
 			#rifm_logo
 			{
 				position: absolute;
-				left: 25px;
-				top: 25px;
+				left: 25dp;
+				top: 25dp;
 			}
 		</style>
 	</head>

+ 2 - 2
Samples/invaders/data/main_menu.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 300px;
-				height: 225px;
+				width: 300dp;
+				height: 225dp;
 
 				margin: auto;
 			}

+ 3 - 3
Samples/invaders/data/options.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 350px;
-				height: 330px;
+				width: 350dp;
+				height: 330dp;
 				
 				margin: auto;
 			}
@@ -19,7 +19,7 @@
 
 			form div
 			{
-				width: 200px;
+				width: 200dp;
 				margin: auto;
 			}
 		</style>

+ 2 - 2
Samples/invaders/data/pause.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 350px;
-				height: 135px;
+				width: 350dp;
+				height: 135dp;
 				
 				margin: auto;
 			}

+ 6 - 6
Samples/invaders/data/start_game.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 300px;
-				height: 225px;
+				width: 300dp;
+				height: 225dp;
 				
 				margin: auto;
 			}
@@ -18,15 +18,15 @@
 			
 			form div
 			{
-				width: 200px;
+				width: 200dp;
 				margin: auto;
 			}
 			color
 			{
 				display: inline-block;
-				width: 9px;
-				height: 9px;
-				border: 1px #666;
+				width: 9dp;
+				height: 9dp;
+				border: 1dp #666;
 				margin-right: 0.5em;
 			}
 		</style>

+ 3 - 3
Samples/invaders/src/Defender.cpp

@@ -103,18 +103,18 @@ void Defender::Update()
 	}
 }
 
-void Defender::Render()
+void Defender::Render(float dp_ratio)
 {
 	glColor4ubv(GameDetails::GetDefenderColour());
 
 	// Render our sprite if rendering is enabled
 	if (render)
-		defender_sprite.Render(Rml::Vector2f(position.x, position.y));
+		defender_sprite.Render(position, dp_ratio);
 
 	// Update the bullet, doing collision detection
 	if (bullet_in_flight)
 	{
-		bullet_sprite.Render(Rml::Vector2f(bullet_position.x, bullet_position.y));
+		bullet_sprite.Render(bullet_position, dp_ratio);
 
 		// Check if we hit the shields
 		for (int i = 0; i < game->GetNumShields(); i++)

+ 1 - 1
Samples/invaders/src/Defender.h

@@ -48,7 +48,7 @@ public:
 	/// Update the defender state.
 	void Update();
 	/// Render the defender.
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Move the defender left.
 	void StartMove(float direction);	

+ 2 - 1
Samples/invaders/src/ElementGame.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "ElementGame.h"
+#include <RmlUi/Core/Context.h>
 #include <RmlUi/Core/ElementDocument.h>
 #include <RmlUi/Core/Input.h>
 #include "Defender.h"
@@ -92,7 +93,7 @@ void ElementGame::OnUpdate()
 // Renders the game.
 void ElementGame::OnRender()
 {
-	game->Render();
+	game->Render(GetContext()->GetDensityIndependentPixelRatio());
 }
 
 void ElementGame::OnChildAdd(Rml::Element* element)

+ 4 - 4
Samples/invaders/src/Game.cpp

@@ -142,7 +142,7 @@ void Game::Update()
 	}
 }
 
-void Game::Render()
+void Game::Render(float dp_ratio)
 {	
 	if (defender_lives <= 0)
 		return;
@@ -150,7 +150,7 @@ void Game::Render()
 	// Render all available shields
 	for (int i = 0; i < NUM_SHIELDS; i++)
 	{
-		shields[i]->Render();
+		shields[i]->Render(dp_ratio);
 	}
 
 	glEnable(GL_TEXTURE_2D);
@@ -161,10 +161,10 @@ void Game::Render()
 	// Render all available invaders
 	for (int i = 0; i < NUM_INVADERS + 1; i++)
 	{
-		invaders[i]->Render();
+		invaders[i]->Render(dp_ratio);
 	}
 	
-	defender->Render();
+	defender->Render(dp_ratio);
 
 	glEnd();
 }

+ 1 - 1
Samples/invaders/src/Game.h

@@ -58,7 +58,7 @@ public:
 	void Update();
 
 	/// Render the game
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Access the defender
 	Defender* GetDefender();

+ 3 - 3
Samples/invaders/src/Invader.cpp

@@ -182,7 +182,7 @@ void Invader::UpdateAnimation()
 	}
 }
 
-void Invader::Render()
+void Invader::Render(float dp_ratio)
 {
 	if (type == MOTHERSHIP)
 	{
@@ -192,11 +192,11 @@ void Invader::Render()
 	int sprite_offset = Rml::Math::RealToInteger((invader_sprites[sprite_index].dimensions.x - 48) / 2);
 
 	if (state != DEAD)
-		invader_sprites[sprite_index].Render(Rml::Vector2f(position.x - sprite_offset, position.y));
+		invader_sprites[sprite_index].Render(Rml::Vector2f(position.x - sprite_offset, position.y), dp_ratio);
 	
 	if (bomb != NONE)
 	{
-		bomb_sprites[bomb_animation_frame].Render(bomb_position);
+		bomb_sprites[bomb_animation_frame].Render(bomb_position, dp_ratio);
 	}
 
 	if (type == MOTHERSHIP)

+ 1 - 1
Samples/invaders/src/Invader.h

@@ -60,7 +60,7 @@ public:
 	virtual void Update();
 
 	/// Render the invader
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Update the invaders animation
 	void UpdateAnimation();

+ 6 - 3
Samples/invaders/src/Shield.cpp

@@ -119,11 +119,14 @@ const Rml::Vector2f& Shield::GetPosition() const
 	return position;
 }
 
-void Shield::Render()
+void Shield::Render(float dp_ratio)
 {
 	if (health > 0)
 	{
-		glPointSize((GLfloat) PIXEL_SIZE);
+		const Rml::Vector2f scaled_position = (dp_ratio * position).Round();
+		const int scaled_pixel = Rml::Math::RoundUpToInteger(PIXEL_SIZE * dp_ratio);
+
+		glPointSize((GLfloat)scaled_pixel);
 		glDisable(GL_TEXTURE_2D);
 		glColor4ubv(GameDetails::GetDefenderColour());
 
@@ -135,7 +138,7 @@ void Shield::Render()
 			{
 				if (shield_cells[i][j] == ON)
 				{
-					Rml::Vector2f cell_position = position + Rml::Vector2f((float) (PIXEL_SIZE * i), (float) (PIXEL_SIZE * j));
+					Rml::Vector2f cell_position = scaled_position + Rml::Vector2f(float(scaled_pixel * i), float(scaled_pixel * j));
 					glVertex2f(cell_position.x, cell_position.y);
 				}
 			}

+ 1 - 1
Samples/invaders/src/Shield.h

@@ -62,7 +62,7 @@ public:
 	const Rml::Vector2f& GetPosition() const;
 
 	/// Render the shield.
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Returns true if the position hits the shield
 	/// If a hit is detected, will degrade the shield.

+ 10 - 4
Samples/invaders/src/Sprite.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "Sprite.h"
+#include <RmlUi/Core/Math.h>
 #include <ShellOpenGL.h>
 
 Sprite::Sprite(const Rml::Vector2f& dimensions, const Rml::Vector2f& top_left_texcoord, const Rml::Vector2f& bottom_right_texcoord) : dimensions(dimensions), top_left_texcoord(top_left_texcoord), bottom_right_texcoord(bottom_right_texcoord)
@@ -37,17 +38,22 @@ Sprite::~Sprite()
 {
 }
 
-void Sprite::Render(const Rml::Vector2f& position)
+void Sprite::Render(Rml::Vector2f position, const float dp_ratio)
 {
+	position = (dp_ratio * position);
+	Rml::Vector2f dimensions_px = dp_ratio * dimensions;
+
+	Rml::Math::SnapToPixelGrid(position, dimensions_px);
+
 	glTexCoord2f(top_left_texcoord.x, top_left_texcoord.y);
 	glVertex2f(position.x, position.y);
 
 	glTexCoord2f(top_left_texcoord.x, bottom_right_texcoord.y);
-	glVertex2f(position.x, position.y + dimensions.y);
+	glVertex2f(position.x, position.y + dimensions_px.y);
 
 	glTexCoord2f(bottom_right_texcoord.x, bottom_right_texcoord.y);
-	glVertex2f(position.x + dimensions.x, position.y + dimensions.y);
+	glVertex2f(position.x + dimensions_px.x, position.y + dimensions_px.y);
 
 	glTexCoord2f(bottom_right_texcoord.x, top_left_texcoord.y);
-	glVertex2f(position.x + dimensions.x, position.y);
+	glVertex2f(position.x + dimensions_px.x, position.y);
 }

+ 1 - 1
Samples/invaders/src/Sprite.h

@@ -41,7 +41,7 @@ public:
 	Sprite(const Rml::Vector2f& dimensions, const Rml::Vector2f& top_left_texcoord, const Rml::Vector2f& bottom_right_texcoord);
 	~Sprite();
 
-	void Render(const Rml::Vector2f& position);
+	void Render(Rml::Vector2f position, float dp_ratio);
 
 	Rml::Vector2f dimensions;
 	Rml::Vector2f top_left_texcoord;

+ 14 - 14
Samples/luainvaders/data/game.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				padding: 0px;
-				margin: 0px;
+				padding: 0dp;
+				margin: 0dp;
 				width: 100%;
 				height: 100%;
 
@@ -22,11 +22,11 @@
 
 			div
 			{
-				height: 47px;
-				padding: 8px 0px 0px 65px;
-				margin: 0px 20px;
+				height: 47dp;
+				padding: 8dp 0dp 0dp 65dp;
+				margin: 0dp 20dp;
 
-				font-size: 20px;
+				font-size: 20dp;
 
 				decorator: tiled-horizontal( huditem-l, huditem-c, huditem-r );
 			}
@@ -34,36 +34,36 @@
 			div#score_div
 			{
 				float: left;
-				width: 155px;
+				width: 155dp;
 			}
 
 			div#hiscore_div
 			{
 				float: left;
-				width: 205px;
+				width: 205dp;
 			}
 
 			div#waves_div
 			{
 				float: right;
-				width: 95px;
+				width: 95dp;
 			}
 
 			div#lives_div
 			{
 				float: right;
-				width: 80px;
+				width: 80dp;
 			}
 
 			icon
 			{
 				display: block;
 				position: absolute;
-				left: 14px;
-				top: 3px;
+				left: 14dp;
+				top: 3dp;
 
-				width: 51px;
-				height: 39px;
+				width: 51dp;
+				height: 39dp;
 			}
 
 			div#score_div icon

+ 5 - 5
Samples/luainvaders/data/help.rml

@@ -31,20 +31,20 @@
 		</p>
 		<h1>The X-42</h1>
 		<p>
-			The culmination of <img src="help_defender.tga" style="float: left; margin: -6px -24px;" />decades of research and the pinnacle of Earth's technology, the X-42 'Defender' is the finest weapon mankind has to fight the alien menace. Equipped with the dual-layer ablative tridranium armour, low-velocity depleted-narconium chain-fed belt gun and state-of-the-art liquid-hydrangea turbo-thrusters, it is still going to be nearly impossible for its pilot to secure the safety of mankind.
+			The culmination of <img src="help_defender.tga" style="float: left; margin: -6dp -24dp;" />decades of research and the pinnacle of Earth's technology, the X-42 'Defender' is the finest weapon mankind has to fight the alien menace. Equipped with the dual-layer ablative tridranium armour, low-velocity depleted-narconium chain-fed belt gun and state-of-the-art liquid-hydrangea turbo-thrusters, it is still going to be nearly impossible for its pilot to secure the safety of mankind.
 		</p>
 		<h1>The Invaders</h1>
 		<p>
-			The most numerous <img src="help_invader_rank1.tga" style="float: left; margin: -4px 0px;" />invader you'll face is a primitive drone that is primarily employed by its Martian overlords in the mines of Cydonia. It is large, ungainly and poorly-armed, so ill-suited to its new role as the backbone of the invasion fleet. However, whatever it lacks in pugilistic prowess it makes up for with numbers. Each drone is worth 10 points.
+			The most numerous <img src="help_invader_rank1.tga" style="float: left; margin: -4dp 0dp;" />invader you'll face is a primitive drone that is primarily employed by its Martian overlords in the mines of Cydonia. It is large, ungainly and poorly-armed, so ill-suited to its new role as the backbone of the invasion fleet. However, whatever it lacks in pugilistic prowess it makes up for with numbers. Each drone is worth 10 points.
 		</p>
 		<p>
-			Behind the drones <img src="help_invader_rank2.tga" style="float: right; margin: -4px 0px;" />stand the formidable berserker units, encased in their zyterium battle-suits and wielding the dreaded Nimbus death-rods. A lone unit is no match for a skilled X-42 pilot, but in large groups they adopt complex flight patterns that can confuse even the best targetting computer. Pick them off and separate them when you can. Each berserker is worth 20 points.
+			Behind the drones <img src="help_invader_rank2.tga" style="float: right; margin: -4dp 0dp;" />stand the formidable berserker units, encased in their zyterium battle-suits and wielding the dreaded Nimbus death-rods. A lone unit is no match for a skilled X-42 pilot, but in large groups they adopt complex flight patterns that can confuse even the best targetting computer. Pick them off and separate them when you can. Each berserker is worth 20 points.
 		</p>
 		<p>
-			The dreaded commander <img src="help_invader_rank3.tga" style="float: left; margin: -4px 0px;" />death-droids lie at the back of every Martian wave. Small, nimble and deadly, these ships are the true test of an X-42 pilot's abilities. Consider yourself warned, and watch out especially for their mind control attack! Each droid is worth 40 points.
+			The dreaded commander <img src="help_invader_rank3.tga" style="float: left; margin: -4dp 0dp;" />death-droids lie at the back of every Martian wave. Small, nimble and deadly, these ships are the true test of an X-42 pilot's abilities. Consider yourself warned, and watch out especially for their mind control attack! Each droid is worth 40 points.
 		</p>
 		<p>
-			Occasionally one of the <img src="help_invader_mothership.tga" style="float: right; margin: -6px -12px;" /> invasion motherships will drop into low-orbit to provide the Martian Overbrain with a close look at the progress of the battle; this is when they are most vulnerable, destroy them if you can! The loss of even a single mothership will be keenly felt by the fleet. The points value of each mothership is variable, depending on the seniority of its command synapse.
+			Occasionally one of the <img src="help_invader_mothership.tga" style="float: right; margin: -6dp -12dp;" /> invasion motherships will drop into low-orbit to provide the Martian Overbrain with a close look at the progress of the battle; this is when they are most vulnerable, destroy them if you can! The loss of even a single mothership will be keenly felt by the fleet. The points value of each mothership is variable, depending on the seniority of its command synapse.
 		</p>
 		<p>
 			Destroy all the invaders in each wave before any get past your ship to invade Earth, unleash their deadly toxin and wipe out all of humanity!

+ 10 - 10
Samples/luainvaders/data/high_score.rml

@@ -5,8 +5,8 @@
 	<style>
 		body
 		{
-			width: 440px;
-			height: 440px;
+			width: 440dp;
+			height: 440dp;
 			
 			margin: auto;
 		}
@@ -18,18 +18,18 @@
 		defender
 		{
 			display: inline-block;
-			width: 64px;
-			height: 16px;
+			width: 64dp;
+			height: 16dp;
 			
 			decorator: defender( high_scores_defender.tga );
 		}
 		tbody tr {
-			height: 30px;
+			height: 30dp;
 		}
 		tbody td
 		{
-			padding-top: 5px;
-			height: 30px;
+			padding-top: 5dp;
+			height: 30dp;
 			white-space: nowrap;
 			overflow: hidden;
 		}
@@ -48,10 +48,10 @@ end
 	<table data-model="high_scores">
 		<thead>
 			<tr>
-				<td style="width: 200%; margin-left: 10px;">Pilot</td>
-				<td style="min-width: 64px;">Ship</td>
+				<td style="width: 200%; margin-left: 10dp;">Pilot</td>
+				<td style="min-width: 64dp;">Ship</td>
 				<td>Wave</td>
-				<td style="min-width: 64px;">Score</td>
+				<td style="min-width: 64dp;">Score</td>
 			</tr>
 		</thead>
 		<tbody>

+ 2 - 2
Samples/luainvaders/data/logo.rml

@@ -12,8 +12,8 @@
 			#rifm_logo
 			{
 				position: absolute;
-				left: 25px;
-				top: 25px;
+				left: 25dp;
+				top: 25dp;
 			}
 		</style>
 	</head>

+ 2 - 2
Samples/luainvaders/data/main_menu.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 300px;
-				height: 225px;
+				width: 300dp;
+				height: 225dp;
 
 				margin: auto;
 			}

+ 3 - 3
Samples/luainvaders/data/options.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 350px;
-				height: 350px;
+				width: 350dp;
+				height: 350dp;
 				
 				margin: auto;
 			}
@@ -19,7 +19,7 @@
 
 			form div
 			{
-				width: 200px;
+				width: 200dp;
 				margin: auto;
 			}
 		</style>

+ 2 - 2
Samples/luainvaders/data/pause.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 350px;
-				height: 135px;
+				width: 350dp;
+				height: 135dp;
 				
 				margin: auto;
 			}

+ 6 - 6
Samples/luainvaders/data/start_game.rml

@@ -5,8 +5,8 @@
 		<style>
 			body
 			{
-				width: 300px;
-				height: 225px;
+				width: 300dp;
+				height: 225dp;
 				
 				margin: auto;
 			}
@@ -18,15 +18,15 @@
 			
 			form div
 			{
-				width: 200px;
+				width: 200dp;
 				margin: auto;
 			}
 			color
 			{
 				display: inline-block;
-				width: 9px;
-				height: 9px;
-				border: 1px #666;
+				width: 9dp;
+				height: 9dp;
+				border: 1dp #666;
 				margin-right: 0.5em;
 			}
 		</style>

+ 3 - 3
Samples/luainvaders/src/Defender.cpp

@@ -103,18 +103,18 @@ void Defender::Update()
 	}
 }
 
-void Defender::Render()
+void Defender::Render(float dp_ratio)
 {
 	glColor4ubv(GameDetails::GetDefenderColour());
 
 	// Render our sprite if rendering is enabled
 	if (render)
-		defender_sprite.Render(Rml::Vector2f(position.x, position.y));
+		defender_sprite.Render(position, dp_ratio);
 
 	// Update the bullet, doing collision detection
 	if (bullet_in_flight)
 	{
-		bullet_sprite.Render(Rml::Vector2f(bullet_position.x, bullet_position.y));
+		bullet_sprite.Render(bullet_position, dp_ratio);
 
 		// Check if we hit the shields
 		for (int i = 0; i < game->GetNumShields(); i++)

+ 1 - 1
Samples/luainvaders/src/Defender.h

@@ -48,7 +48,7 @@ public:
 	/// Update the defender state.
 	void Update();
 	/// Render the defender.
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Move the defender left.
 	void StartMove(float direction);	

+ 2 - 1
Samples/luainvaders/src/ElementGame.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "ElementGame.h"
+#include <RmlUi/Core/Context.h>
 #include <RmlUi/Core/ElementDocument.h>
 #include <RmlUi/Core/Input.h>
 #include <RmlUi/Core/Factory.h>
@@ -89,7 +90,7 @@ void ElementGame::OnUpdate()
 // Renders the game.
 void ElementGame::OnRender()
 {
-	game->Render();
+	game->Render(GetContext()->GetDensityIndependentPixelRatio());
 }
 
 void ElementGame::OnChildAdd(Rml::Element* element)

+ 4 - 4
Samples/luainvaders/src/Game.cpp

@@ -140,7 +140,7 @@ void Game::Update()
 	}
 }
 
-void Game::Render()
+void Game::Render(float dp_ratio)
 {	
 	if (defender_lives <= 0)
 		return;
@@ -148,7 +148,7 @@ void Game::Render()
 	// Render all available shields
 	for (int i = 0; i < NUM_SHIELDS; i++)
 	{
-		shields[i]->Render();
+		shields[i]->Render(dp_ratio);
 	}
 
 	glEnable(GL_TEXTURE_2D);
@@ -159,10 +159,10 @@ void Game::Render()
 	// Render all available invaders
 	for (int i = 0; i < NUM_INVADERS + 1; i++)
 	{
-		invaders[i]->Render();
+		invaders[i]->Render(dp_ratio);
 	}
 	
-	defender->Render();
+	defender->Render(dp_ratio);
 
 	glEnd();
 }

+ 1 - 1
Samples/luainvaders/src/Game.h

@@ -58,7 +58,7 @@ public:
 	void Update();
 
 	/// Render the game
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Access the defender
 	Defender* GetDefender();

+ 3 - 3
Samples/luainvaders/src/Invader.cpp

@@ -182,7 +182,7 @@ void Invader::UpdateAnimation()
 	}
 }
 
-void Invader::Render()
+void Invader::Render(float dp_ratio)
 {
 	if (type == MOTHERSHIP)
 	{
@@ -192,11 +192,11 @@ void Invader::Render()
 	int sprite_offset = Rml::Math::RealToInteger((invader_sprites[sprite_index].dimensions.x - 48) / 2);
 
 	if (state != DEAD)
-		invader_sprites[sprite_index].Render(Rml::Vector2f(position.x - sprite_offset, position.y));
+		invader_sprites[sprite_index].Render(Rml::Vector2f(position.x - sprite_offset, position.y), dp_ratio);
 	
 	if (bomb != NONE)
 	{
-		bomb_sprites[bomb_animation_frame].Render(bomb_position);
+		bomb_sprites[bomb_animation_frame].Render(bomb_position, dp_ratio);
 	}
 
 	if (type == MOTHERSHIP)

+ 1 - 1
Samples/luainvaders/src/Invader.h

@@ -60,7 +60,7 @@ public:
 	virtual void Update();	
 
 	/// Render the invader
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Update the invaders animation
 	void UpdateAnimation();

+ 6 - 3
Samples/luainvaders/src/Shield.cpp

@@ -119,11 +119,14 @@ const Rml::Vector2f& Shield::GetPosition() const
 	return position;
 }
 
-void Shield::Render()
+void Shield::Render(float dp_ratio)
 {
 	if (health > 0)
 	{
-		glPointSize((GLfloat) PIXEL_SIZE);
+		const Rml::Vector2f scaled_position = (dp_ratio * position).Round();
+		const int scaled_pixel = Rml::Math::RoundUpToInteger(PIXEL_SIZE * dp_ratio);
+
+		glPointSize((GLfloat)scaled_pixel);
 		glDisable(GL_TEXTURE_2D);
 		glColor4ubv(GameDetails::GetDefenderColour());
 
@@ -135,7 +138,7 @@ void Shield::Render()
 			{
 				if (shield_cells[i][j] == ON)
 				{
-					Rml::Vector2f cell_position = position + Rml::Vector2f((float) (PIXEL_SIZE * i), (float) (PIXEL_SIZE * j));
+					Rml::Vector2f cell_position = scaled_position + Rml::Vector2f(float(scaled_pixel * i), float(scaled_pixel * j));
 					glVertex2f(cell_position.x, cell_position.y);
 				}
 			}

+ 1 - 1
Samples/luainvaders/src/Shield.h

@@ -62,7 +62,7 @@ public:
 	const Rml::Vector2f& GetPosition() const;
 
 	/// Render the shield.
-	void Render();
+	void Render(float dp_ratio);
 
 	/// Returns true if the position hits the shield
 	/// If a hit is detected, will degrade the shield.

+ 10 - 4
Samples/luainvaders/src/Sprite.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "Sprite.h"
+#include <RmlUi/Core/Math.h>
 #include <ShellOpenGL.h>
 
 Sprite::Sprite(const Rml::Vector2f& dimensions, const Rml::Vector2f& top_left_texcoord, const Rml::Vector2f& bottom_right_texcoord) : dimensions(dimensions), top_left_texcoord(top_left_texcoord), bottom_right_texcoord(bottom_right_texcoord)
@@ -37,17 +38,22 @@ Sprite::~Sprite()
 {
 }
 
-void Sprite::Render(const Rml::Vector2f& position)
+void Sprite::Render(Rml::Vector2f position, const float dp_ratio)
 {
+	position = (dp_ratio * position);
+	Rml::Vector2f dimensions_px = dp_ratio * dimensions;
+
+	Rml::Math::SnapToPixelGrid(position, dimensions_px);
+
 	glTexCoord2f(top_left_texcoord.x, top_left_texcoord.y);
 	glVertex2f(position.x, position.y);
 
 	glTexCoord2f(top_left_texcoord.x, bottom_right_texcoord.y);
-	glVertex2f(position.x, position.y + dimensions.y);
+	glVertex2f(position.x, position.y + dimensions_px.y);
 
 	glTexCoord2f(bottom_right_texcoord.x, bottom_right_texcoord.y);
-	glVertex2f(position.x + dimensions.x, position.y + dimensions.y);
+	glVertex2f(position.x + dimensions_px.x, position.y + dimensions_px.y);
 
 	glTexCoord2f(bottom_right_texcoord.x, top_left_texcoord.y);
-	glVertex2f(position.x + dimensions.x, position.y);
+	glVertex2f(position.x + dimensions_px.x, position.y);
 }

+ 1 - 1
Samples/luainvaders/src/Sprite.h

@@ -41,7 +41,7 @@ public:
 	Sprite(const Rml::Vector2f& dimensions, const Rml::Vector2f& top_left_texcoord, const Rml::Vector2f& bottom_right_texcoord);
 	~Sprite();
 
-	void Render(const Rml::Vector2f& position);
+	void Render(Rml::Vector2f position, float dp_ratio);
 
 	Rml::Vector2f dimensions;
 	Rml::Vector2f top_left_texcoord;