Project Dino – Code samples

Project Dino is a small game project I did to try out different stuff. It started with me wanting to learn more about vertex shading. While testing things around I listened to this track on side could and decides to make a small game that fitted the tone of the music. I also wanted to use as simple controls as possible and decided to only use one button as input for the game.

Portfolio page

Vertex shading

To make things as simple as possible I decided to create the whole game as a simple side scroller where everting was scrolling from the right to the left. Every object in the game is only traveling in in X axis from the right to the left without rotating.

To get the rotation I created a vertex shader that bends the vertices around a point in the world space. This creates the globe-trotting effect in the game.

Doing it this way of bending the sprites in shader instead of rotating them in game had several benefits. For example, it made the “fake” game physics and collision detection very easy since nothing ever rotates. I would also adjust the exact bendiness of the game with adjusting simple parameters in the materials instead of having to change any game code.

Vertex shading bends the game world dynamically in run-time.

Shader "Custom/BenderShader"
{
	Properties
	{
		_MainTex("Sprite Texture", 2D) = "white" {}
		_Color("Tint", Color) = (1,1,1,1)
		_Curvature("Curvature", Float) = 0
		_Origin("Origin", Vector) = (0,0,0)
	}

	SubShader
	{
		Tags
		{
			"Queue" = "Transparent"
			"IgnoreProjector" = "True"
			"RenderType" = "Transparent"
			"PreviewType" = "Plane"
			"CanUseSpriteAtlas" = "True"
		}

	Cull Off
	Lighting Off
	ZWrite Off
	Blend One OneMinusSrcAlpha

	Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			sampler2D _MainTex;
			uniform fixed4 _Color;

			uniform float _Curvature;
			uniform float3 _Origin;

			struct appdata_t
			{
				float4 vertex   : POSITION;
				float4 color    : COLOR;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f
			{
				float4 vertex   : SV_POSITION;
				fixed4 color : COLOR;
				float2 texcoord  : TEXCOORD0;
			};

			float4 Bend(float4 v)
			{
				float4 wPos = mul(unity_ObjectToWorld, v);
				wPos.xyz -= _Origin;

				float2 xyDir = (wPos.xy);

				float s = sin(_Curvature * -xyDir.x);
				float c = cos(_Curvature * -xyDir.x);

				float4 nPos = float4((c * wPos.x - s * wPos.y),(s * wPos.x + c * wPos.y), wPos.z, wPos.w);

				return  mul(unity_WorldToObject, nPos);
			}

			v2f vert(appdata_t IN)
			{
				v2f OUT;
				OUT.vertex = UnityObjectToClipPos(Bend(IN.vertex));
				OUT.texcoord = IN.texcoord;
				OUT.color = IN.color * _Color;

				return OUT;
			}

			fixed4 SampleSpriteTexture(float2 uv)
			{
				fixed4 color = tex2D(_MainTex, uv);
				return color;
			}

			fixed4 frag(v2f IN) : SV_Target
			{
				fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
				c.rgb *= c.a;
				return c;
			}

			ENDCG
		}
	}
}

Portfolio page