Pages

Tuesday, September 4, 2012

Blast from the past: Galactic Mazes

Galactic Mazes

 
Here is a short video from my first ever game, Galactic Mazes.



It has been called 'worst game ever', which i find a huge compliment. ;-)

This game featured fully randomized, huge levels.
It had three different types of enemies.
The back story features a remote controlled probe (you) that investigates an ancient maze found somewhere on earth.
The probe finds a 'mysterious artifact' which turns out to be a type of Stargate, propelling the probe to a different star system.
As the game progresses, a story unfolds that explains the origins of the mazes, and unveils an ancient war that took place, almost wiping out the budding human race.

Monday, September 3, 2012

Unity3d shaders: z-depth controlling alpha

The Situation:


In my game Asteroid Ace, the player faces hordes of asteroids, minerals and other space debris. Sometimes there are so many of them storming towards you at the same time, that it becomes very difficult to navigate. For that reason, i gave the player a projection that shows where an incoming object is going to hit the player's plane.

Since this game is for mobile platforms (at least initially), i have a very limited draw call budget (25 to 30 max). Ideally, i want one single draw call to take care of all projections for each object/size combination. So, i used Unity's dynamic batching mechanism: make sure your projections have the same plane mesh, the same scale, and the same material. Works like a charm.

The Problem:


The projections do not provide any information about how long it takes for the object to reach the players plane. Without projections, a player can make a good judgement of distance and speed, but with projections, these actually occlude vision of incoming stuff.

For that reason, i wanted the projections to convey ETA of the objects. On an earlier prototype i simply manipulated the material's main color transparency as the object gets closer (its Z position changes). This approach has the desired effect, but totally kills unity's dynamic batching. Because, when you start manipulating an object's material in-game, the engine creates a material Instance for that object only. This means, the projections no longer share the same material, and dynamic batching no longer works.

The Solution:


Let the shader control the transparency, depending on the Z-depth.

Here's the shader without Z-depth factored in:

Shader "DapperDodo/Mobile Alpha" {

    Properties {
        _EmisColor ("Emissive Color", Color) = (.2,.2,.2,0)
        _MainTex ("Particle Texture", 2D) = "white" {}
    }

    Category {
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
       
        Lighting Off

        SubShader {
          CGPROGRAM
          #pragma surface surf None finalcolor:mycolor alpha noambient novertexlights nolightmap nodirlightmap noforwardadd

          half4 LightingNone (SurfaceOutput s, half3 lightDir, half atten) {
          half4 c;
          c.rgb = s.Albedo;
          c.a = s.Alpha;
          return c;
        }
          struct Input {
              float2 uv_MainTex;
          };
          fixed4 _EmisColor;
          void mycolor (Input IN, SurfaceOutput o, inout fixed4 color)
          {
              color *= _EmisColor;
          }
          sampler2D _MainTex;
          void surf (Input IN, inout SurfaceOutput o) {
              o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
              o.Alpha = tex2D (_MainTex, IN.uv_MainTex).a;
          }
          ENDCG
        }
    }
}

And here's the shader with Z-depth factored in. The code needed for this is Bold

Shader "DapperDodo/Mobile Z-depth Alpha" {

    Properties {
        _EmisColor ("Emissive Color", Color) = (.2,.2,.2,0)
        _MainTex ("Particle Texture", 2D) = "white" {}
    }

    Category {
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
       
        Lighting Off

        SubShader {
          CGPROGRAM
          #pragma surface surf None finalcolor:mycolor alpha noambient novertexlights nolightmap nodirlightmap noforwardadd

          half4 LightingNone (SurfaceOutput s, half3 lightDir, half atten) {
          half4 c;
          c.rgb = s.Albedo;
          c.a = s.Alpha;
          return c;
        }
          struct Input {
              float2 uv_MainTex;
              float3 worldPos;
          };
          fixed4 _EmisColor;
          void mycolor (Input IN, SurfaceOutput o, inout fixed4 color)
          {
              color *= _EmisColor;
          }
          sampler2D _MainTex;
          void surf (Input IN, inout SurfaceOutput o) {
              o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
              o.Alpha = tex2D (_MainTex, IN.uv_MainTex).a * (1 - saturate((IN.worldPos.z - 1000) / 100));
          }
          ENDCG
        }
    }
}

The key piece of code here is '* (1 - saturate((IN.worldPos.z - 1000) / 100))'

The values of 1000 and 100 depend on the camera setup. Change that according to you own situation. In this case, Z <= 1000 means alpha = 1, and as Z moves to 1100 and beyond, alpha becomes 0.

For Asteroid Ace i needed a double camera setup. The flying objects are rendered using a normal perspective camera. However, the projections are rendered using an Orthographic camera. This means that the projections keep the same size, independent of the Z depth.


Wednesday, August 22, 2012

Roguelike Dungeons : analysis of the classics

DapperDodo goes retro.


I am considering making an old school Roguelike, inspired by the old 1980's classics such as 'Rogue' and 'Sword of Fargoal'.

In this post i analyze how dungeons were done in those classic games and define my own rule set for this.

Classic Dungeons


A Dungeon generally consists of a balanced combination of Rooms, Corridors and Rock. 




The ratio's between those may vary between dungeons. For example, Sword of Fargoal featured the Sword Level, which consisted of only corridors, with only a single central Room (a classic Maze). The player could immediately recognize that they entered this sword level.




Players could move between Dungeons by means of Stairs, either up or down. In the classic games, every time you moved to another Dungeon, a brand new random dungeon was created. In my opinion it would be better to make Dungeons persistent within a Game.




The player could end up in an isolated part of a Dungeon (Compartment), with no corridors to the rest of the Dungeon. This required the player to return to the previous level and find another entrance.





Our Rule Set


When creating a new Dungeon, the following parameters must be provided:

- number, and location of 'returning' stairs from the previous Dungeon
- number of 'downward' stairs to the next Dungeon
- Room, Corridor and Rock (0..100)
- Rooms (0..n)
- Compartments (0..n)

Dungeons are persistent within a game. 

The return trip : on completion of the deepest level, the return stairs are to be destroyed, and a single new staircase becomes available. Dungeons on the return trip have less stairs (one or two).

Monday, August 6, 2012

Welcome to DapperDodo's Dev Dojo

On this blog i plan to post on topics like software design, (mobile) game development, programming languages, procedural content creation, worldbuilding and other stuff in the realm of game development.

DapperDodo, that's me, is an Indie Game Developer. Currently i am working on the mobile game Asteroid Ace, which is currently available for Android on the Play Store. The game state is Early Alpha, available for those interested in alpha funding cool Indie games.

Aside from developing my own games, i am available for freelance work. I'm an experienced software architect, more a generalist than a specialist. My daily toolkit includes Go for systems/backend programming and Unity3d for game client development. Historically i developed specialisms in the fields of Web Development (PHP), Relational Databases(SQL) and Music Production.

Hopefully i can contribute to the Indie and Developer communities through this Blog.

Other ways to follow DapperDodo: