Monday, October 31, 2011

Alpha Version Progress Report

Progress Report
Up to now, we have finished all of the requirements in Alpha Version:
Procedural generation of tunnel
Distribution and generation of obstacles and accelerators
Collision between character and obstacles
Scoring system
Sound effects

We have also implemented some of those in Beta Version:
Webcam based movement control
Dizzy and motion blur effects
Menu GUI

In the next few weeks, we will be working on:
Other Beta Version requirements, including dual game mode, diverse bonus/ obstacles and custom shaders, etc.
We will also optimize the existing mechanism and graphic effects according to the feedback.

Game Demo:

Motion Controller Detail

Idea:
Threat the frame of player(s) as a texture and analyze the average direction of the contour edges of the player(s).

Assumptions:
1. Players can be distinguished from background because they are moving. (Even if they looks still, people have subtle movement other than the background.)
2. People can be seen as sticks. (They are tall, long, and most of the edges are vertical if they stand still.)

Extract Moving Things:
That is a simple trick, because the background image never moves (Assumption 1), we can simply use the difference between a frame and its previous frame.


Smooth and Get Gradient Map:
We can use a gradient convolution kernel {-1, 1} to get the result. We can see that the horizontal lines are obvious after convoluted with a Y direction gradient, and the vertical lines are obvious after X direction gradient.


Get the Interesting Points:
We can see from the gradient kernel, even if the background is subtracted, there is still a lot of noise comes from the background, that is due to contrast change from frame-to-frame brightness change.  So we need to set a threshold that means, if the edge is more obvious than something, I should pay attention to it. A simple way to measure how the edge is obvious is add the magnitude of the x-and-y-direction gradient up. (If Gx*Gx + Gy*Gy > threshold, the point in counted as a interesting point.)


Calculate the Point Directions:
Here is an example of how to calculate the local direction of edges:
The upper left matrix is for a simple edge, the upper right one is the smoothed edge with a Gaussian kernel of size 3, while the lower left is the convolution result with a x-direction gradient kernel and the lower right is the the convolution result with a y-direction gradient kernel.
As we known that if the edge is vertical, the x direction convolution response will be high and vice versa, we can get the direction of the edge by calculate the tangent value of x and y direction convolution results.
Say, we want to know direction of the point (3, 3), we can simply use atan2(-16, -16) = 45 degree.

Calculate the Average Direction of the Whole Frame
Knowing the method above, we can simply accumulate all the direction values and calculate the average of them to get the direction of the whole frame.


HUD in Game

Idea:
We want to Create Really Simple but cool HUD in game to show the current score and speed level of the player. Because our game is pretty like the racing game, the idea of build a speedometer like HUD comes to our mind first.

Rotate the Pointer:
We started to add our HUD from a Unity GUI Texture, but the problem is, it is not allowed to rotate any non-3D GUI Textures in Unity, while we definitely don't want to use mesh textures because that is not cool...
So one way to rotate the GUI Texture is like that:

        posPointer = new Vector2(transform.localPosition.x - sizePointer.x * 0.5f, transform.localPosition.y);
        rectPointer = new Rect(posPointer.x - sizePointer.x * 0.5f, posPointer.y - sizePointer.y * 0.5f, sizePointer.x, sizePointer.y);
        pivotPointer = new Vector2(rectPointer.xMin + rectPointer.width * 0.5f, rectPointer.yMin + rectPointer.height * 0.5f);
        GUIUtility.RotateAroundPivot(angle, pivotPointer);
        GUI.DrawTexture(rectPointer, pointer);
        GUI.matrix = matrixBackup;
        GUI.DrawTexture(rectSpeedometer, speedometer);

It Rotates a Texture2D like the OpenGL way, and the result is pleasing.

Result:
Here is a screenshot of our HUD:





Start Menu GUI Detail

We have implemented most parts of start menu GUI and connected it to the game scene.

As mentioned before, we use doors in the tunnel to act as the menu GUI for the game. Now we have three doors, which are:

Main Menu with four buttons as "Game Mode""Options""High Scores""Quit Game"
Game Mode Menu with three buttons as "Classic Mode""Time Mode""Go Back"
High Scores Menu with "Go Back" Button




We have also added some more detailed animations to the menu, for example, the button will "stand up" when a user puts the mouse on it. Light will also be turned on and gear will spin before the door opens.




We will apply the animations to all of the parts of the doors and implement all of the functions including Options and High Scores. We will also modify the scene transfer to make it smoother instead of  convert the camera from the menu to the game directly.

Thursday, October 27, 2011

Procedural Tunnel Generation Detail

//FIXME
OMG! alpha version presentation is coming!!!
Let's focus on games rather than words!
Details will come soon :-)

Tuesday, October 18, 2011

Challenges Encountered in Procedural Tunnel Generation

In Sliding in the Deep, the core development task is to procedurally generate the tunnel. In our design, the tunnel has two varying parameters, the longitudinal direction and latitudinal curvature. We want to make our tunnel turn left/right/up/down randomly. And its shape can also vary between a complete circle and a plane. Player will move inside the tunnel if its curvature is positive and outside the tunnel if its curvature goes negative. We want the tunnel direction and curvature change smoothly.

The basic idea is to derive a section of tunnel from a procedurally generated cubic Bezier curve, namely, the guide curve. This guide curve will determine the general shape of this section of tunnel. Its start point coincides with the end point of last guide curve. Its end point is randomly picked. We want our tunnel to always develop along the +z axis, so we keep our tangent of two endpoints be (0, 0, 1) * constant.

The basic idea is easy and straightforward. But we did meet challenging problems when implementing this idea:

1. How to describe the tunnel’s curvature?

Most of the time, the tunnel is an arc of a circle (or a complete circle). But things goes messier if current curvature is 0, which means the tunnel degenerated to a plane. We can no longer treat it as arc since its radius will be infinity.

2. How to ensure uniform speed?

The speed of player moving along the curve is an essential element in our game. It will only be affected by the interaction between player and obstacles or accelerators. We actually want our player move a contestant length of curve in each step (If it doesn’t get accelerated or hit an obstacle). If using Bezier curve, the naive method to deal with player movement is to use the Bezier parameter t. But for Bezier curve, uniform change in t doesn’t mean uniform speed.

3. The workload of tunnel generator is not uniform. Next section only needs to be generated if player get near to the end of current section. But the generating process needs heavy computation. Simply call the generating function when player move towards the end will make the game get stuck for a very short time. This is annoying and will make our user experience quite bad.

The method we used to solve those problems and more implementation details will be given in the following blog.

Automatic Tunnel Generation Script Done

Result Demo:


There are aliasing problems for the recorded video because the frame rate of Windows Encoder Express is only 10 fps... The game experience is continues and fluent.