April 1, 2012 0

Wheeler Dealer

By in Games, Unity3D

Last month I finally got around to making an entry for the Experimental Gameplay Project! I’ve been meaning to enter for a while but never summoned up the effort or courage to attempt it. This month was different. I actually started work on two different ideas and managed to finish the good one to quite a high degree of polish.

I even got a great little review from the guys at EGP.

Extremely addictive truck delivery game about making a selling various goods.  Traveling and time burn fuel.  Looking forward to updates on this one!

You can try it out here - Wheeler Dealer

Read the rest of this entry »

Tags: , , ,

December 9, 2011 0

A Vector3 Cross Product optimisation

By in Code theory, Free Code, Unity3D

I’m about to implement a custom LineRenderer for Unity3D as I’ve noticed that the built-in one does not batch draw calls properly. I’m gonna be rendering a lot of lines, so an extra draw call for each LineRenderer isn’t really acceptable.

One of the calculations you have to perform to find the vertex positions for the line is to get the cross product of the direction of the line with the direction the camera is facing. So for every line segment that’s a cross product – 6 multiplications and 3 subtractions. In my case I need quite a few segments, and they’re going to be updating in real time. This is going to be running on mobile, so I’m trying to eek out every last bit of performance I can.

In my case the camera is always facing in the same direction as it’s a 2D game so the cross product will always be of the form Vector3.Cross(lineDirection,-Vector3.forward). Surely there is some mathematical optimisation that can be done there! Yep, and it’s really simple!

public static Vector3 ForwardCross( Vector3 v ) {
	return new Vector3( v.y, -v.x, 0 );
}

That’s a saving on 6 multiplications and 2 subtractions (does negation count as subtraction?!). So I was expecting some pretty amazing performance increase from this…

For 100,000,000 random vectors and cross products, computed on my laptop:

Normal Cross Time: 13.187
Quick Cross Time: 11.354
Performance increase: 13.9%

What, is that it?! So what about manually inlining the function:

Normal Cross Time: 12.723
Quick Cross Time: 9.381
Performance increase: 26.2%

That’s more like it. But weird… I was under the impression that C# dynamically inlined functions. Maybe it’s different on the mobile, needs testing!

So another lesson learned – if you need a cross product with a constant vector, premultiply; and (maybe) manually inline functions if they’re called a lot!

December 2, 2011 0

Unity3D Perlin Benchmark

By in Code theory, Unity3D

I was wondering if the Perlin noise class from this package was quicker than the built in Mathf.PerlinNoise(x,y). So I did some quick benchmarks! For 1,000,000 Perlin look-ups the time taken was:

  • Built-in 2D Perlin took: 0.09539998s
  • C# 1D Perlin took: 0.04631203s
  • C# 2D Perlin took: 0.167416s

So if you just need 1 dimensional Perlin noise use the C# class rather than Mathf.PerlinNoise(x,0f). For 2 dimensional Perlin noise use the built-in function (although it’s not documented so is it even officially supported?!). For 3D Perlin noise you’re stuck with the C# class.

November 29, 2011 0

Reaching Terminal Velocity

By in Code theory, Free Code, Unity3D

Limiting a rigidbody’s velocity is a problem I’ve tried to solve in Unity over and over again with this trick:

rigidbody.velocity = Vector3.ClampMagnitude( rigidbody.velocity, terminalVelocity );

The problem with this method is that by setting the velocity in every frame, adding forces to the rigidbody can’t have any effect. In general, using this trick has always led to strange things happening. There must be a better solution.

Recently I remembered my high school physics lessons about how objects have a terminal velocity – a velocity they cannot move quicker than. This occurs when drag (a force proportionate to the object’s velocity) cancels out the constant force on the body (such as gravity). I realised this could be used with Unity’s built in drag to get a very simple solution for limiting velocity on bodies with a constant force applied.

So first I had to make an assumption about Unity’s drag equation. I guessed at this:

Vector3 dragForce = -rigidbody.velocity * rigidbody.drag

Terminal velocity occurs when the constant force and the drag force are equal, so this can be rearranged to find the drag required for a particular terminal velocity.

rigidbody.drag = boostForceMagnitude / terminalVelocity;

Simple right? Actually, it turns out that the drag equations can’t be what I thought. I did some tests with this method and it turned out that the limiting velocity was always exactly 0.2 less than what I wanted, no matter what the boostForceMagnitude or terminalVelocity was… So a bit of fiddling and it turned out that drag must have some sort of dependency on the length of the time step. I also tried to emulate the ConstantForce component in FixedUpdate and interestingly it turns out that it doesn’t scale the force by Time.fixedDeltaTime … So that means if you use this component (or indeed drag), changing your time step will have side-effects on your physics.

rigidbody.drag = boostForceMagnitude/ ( terminalVelocity + 10f*Time.fixedDeltaTime );

The full ‘Boost’ class:

using UnityEngine;
using System.Collections;

public class Boost : MonoBehaviour {

	public float acceleration, terminalVelocity;

	// Use this for initialization
	void Start () {
		float boostForceMagnitude = rigidbody.mass*acceleration;
		rigidbody.drag = boostForceMagnitude/(terminalVelocity+10f*Time.fixedDeltaTime);
		ConstantForce f = gameObject.AddComponent();
		f.relativeForce = Vector3.forward*boostForceMagnitude;
	}

	void OnGUI() {
		GUI.Label( new Rect(0,0,200,20), "Speed: " + rigidbody.velocity.magnitude.ToString("N4") );
	}

}

This implementation will only limit velocity when you have a constant force on your body. Soon I’ll try to work out a generic solution to clamping velocity within a certain range just with drag. I wonder if there is an analytical solution using momentum or something…

October 26, 2011 0

Spinors

By in Free Code, Unity3D

I was prototyping for a *top secret 2D project* yesterday when I realised that Slerping (Spherical Linear Interpolation) a 3D vector just doesn’t work when you need to stay constrained to 2D. That’s when I found this article about Spinors, which are essentially 2D Quaternions, along with an implementation (in Visual Basic?!).

So I went ahead and ported the code for Unity3D and it seems to work really well! So thanks to Parade of Rain for the base code.

using UnityEngine;

public class Spinor
{

	float real;
	float complex;

	public Spinor (float angle)
	{
		angle *= 0.5f;
		real = Mathf.Cos (angle);
		complex = Mathf.Sin (angle);
	}

	public Spinor (float realPart, float complexpart)
	{
		complex = complexpart;
		real = realPart;
	}

	public Spinor GetScale (float t)
	{
		return new Spinor (real * t, complex * t);
	}

	public Spinor GetInvert ()
	{
		Spinor s = new Spinor (real, -complex);
		return s.GetScale (s.GetLengthSquared ());
	}

	public static Spinor operator + (Spinor a, Spinor b)
	{
		return new Spinor (a.real + b.real, a.complex + b.complex);
	}

	public float GetLength ()
	{
		return Mathf.Sqrt (real * real + complex * complex);
	}

	public float GetLengthSquared ()
	{
		return (real * real + complex * complex);
	}

	public static Spinor operator * (Spinor a, Spinor b)
	{
		return new Spinor (a.real * b.real - a.complex * b.complex, a.real * b.complex + a.complex * b.real);
	}

	public Spinor GetNormalized ()
	{
		float length = GetLength ();
		return new Spinor (real / length, complex / length);
	}

	public float GetAngle ()
	{
		return Mathf.Atan2 (complex, real) * 2f;
	}

	public static Spinor Lerp (Spinor startVal, Spinor endVal, float t)
	{
		return (startVal.GetScale (1f - t) + endVal.GetScale (t)).GetNormalized ();
	}

	public static Spinor Slerp (Spinor start, Spinor end, float t)
	{
		float tr;
		float tc;
		float omega, cosom, sinom, scale0, scale1;

		//calc cosine
		cosom = start.real * end.real + start.complex * end.complex;

		//adjust signs
		if (cosom < 0) {
			cosom = -cosom;
			tc = -end.complex;
			tr = -end.real;
		} else {
			tc = end.complex;
			tr = end.real;
		}

		// coefficients
		if ((1f - cosom) > 0.001f) {
			//threshold, use linear interp if too close
			omega = Mathf.Acos (cosom);
			sinom = Mathf.Sin (omega);
			scale0 = Mathf.Sin ((1f - t) * omega) / sinom;
			scale1 = Mathf.Sin (t * omega) / sinom;
		} else {
			scale0 = 1f - t;
			scale1 = t;
		}

		//calc final
		Spinor res = new Spinor (0f, 0f);
		res.complex = scale0 * start.complex + scale1 * tc;
		res.real = scale0 * start.real + scale1 * tr;
		return res;
	}

	public static float Slerp2D (float fromAngle, float toAngle, float t)
	{
		Spinor a = new Spinor (fromAngle);
		Spinor b = new Spinor (toAngle);
		return Spinor.Slerp (a, b, t).GetAngle ();
	}

}
October 10, 2011 0

One day game – ‘Survival’

By in Games, One day games

Another week another one day game! This time the theme was ‘survival’. It turned out really, really simple and but I think it’s a good a base for a more elaborate game. The idea is that you are stranded on a chain of desert islands and must try to find enough food to survive. The problem is that much of the available food is below the sea and is only exposed at low tide.

You can try it out here!

October 2, 2011 0

One day game – Advance To Contact H-Hour

By in Games, One day games

The idea for this one came about while chatting with @inslayn about old games we’d made. One of his was ‘Advance to contact H-hour’ – a military term for something to do with artillery and death and suchlike. But the game didn’t match the title so we both decided to jam on it and see what happened. Here is the result of my weekends coding. If you don’t like cute sphere men being brutally shot to pieces in bloody explosions then don’t press play…

PLAY IT HERE!!!

OK so this one was a little more than a day, but it was totally worth it. Most of the SFX were done with bfxr and the music was written by me with Logic Pro.

September 26, 2011 0

5 hour game!

By in Games

Wow, what a prolific weekend I’ve had. Internet has been up and down all day so what else could I do but program?! This time Sandra gave me the verb ‘Run’ as inspiration. First thought was Canabalt (ugh) so I took the other meaning of ‘Run’ I know, which is to run a program.

The game that has emerged is definitely not a casual one. In fact I think to really play well you probably need to be like a chess grand master and plan many moves in advance. I thought the rules were actually quite simple, but when I wrote them down I realised there are a lot of them, and they are rather complex. Even with zero randomness (except for the starting position), a lot of different situations can emerge.

A lot of the rules were added so that infinite loops are impossible. I believe it is also impossible for the player to help create an infinite loop (and thus an infinite score) by clever tile swapping, but I’m pretty sure there must be a way. Even if there is, it’s part of the fun of the game trying to work out how to break it! I certainly had a lot of fun causing infinite loops and then finding ways to change the rules to prevent them.

My top score so far is a pathetic 6. If you can best that I’d love to hear how!

http://davidrzepa.com/games/runprogram/

September 24, 2011 0

One day game – ‘Cry’

By in Games, One day games

Last night I had the idea that it would be nice to try and make a game in a day. Once again I asked my girlfriend for a verb to inspire a game and she came up with ‘cry’. Oh dear! Anyway rules are rules so I gave it a go. It kind of turned out as more of a toy than a game, but I don’t think that’s a bad thing. You can play it HERE and here’s a video:

I’d love to say that there is a deep meaning to all this, but really ‘cry’ just led to ‘tears’ which led to water drops falling in a desert with cactuses. Ah well was fun making it, and the hope is I’ll try to make a new ‘One day game’ every week or so.

 

August 29, 2011 0

Endless games

By in Game theory, Games

As an iOS game developer, one of the design problems that seems to come up repeatedly is ‘How should endless games ramp up in difficulty?’. By ‘endless games’ I mean those in which the aim is to survive for as long as possible e.g. Flight Control, Fruit Ninja, or W.A.R.P (shameless plug!).

Endless games have a number of advantages on mobile devices:

  • Don’t need as much content so can be small downloads.
  • Easy to pick-up-and-play, important for devices that are so often used while waiting for the bus!
  • Lend themselves well to leader boards which seem to be popular on mobiles these days (but this is probably just because endless games are popular)

Endless games are typically constructed by finding a simple gameplay action and forcing the player to repeat it over and over until they fail somehow and the game ends. Of course once the player has grokked the main mechanic the game becomes boring, so how can you delay this for as long as possible?

Increase the difficulty!

More planes, more bombs, more asteroids, faster enemies. All the ways in which games have traditionally ramped up the difficulty should apply here. But can you just ramp up the difficulty forever? No! Because then it’s not an endless game anymore.

With all games there is a point in the difficulty curve where it becomes logically impossible to not fail. It becomes humanly impossible a long time before that. But this doesn’t just apply to endless games. If you allow any game to become humanly impossible to complete, then the game can no longer be perceived as fair and you will quickly lose your players.

At some point your game will have to stop getting harder. But even if a player is good enough to reach the difficulty cap, eventually they will get tired and and fail. The important thing is that they know it was their failure and not the games so they will play again and again to beat their previous record.

But what curve should the difficulty increase take? The best curve will be the one that keeps the most players in flow. But do you balance this for first time players or veterans? Is dynamic difficulty an option if you have leader boards? Perhaps the player can choose to speed up the game (like Flight Control) taking them out of the boredom channel and back into the flow channel as quickly as possible.

Vary the mechanics!

Not everybody is an achiever so just increasing the difficulty isn’t enough. By introducing variations to the main mechanic you can delay grokking for a little bit longer. Of course you can’t add new variations infinitely so the key is to add variations that interact well with each other to produce even more variations! For the explorers, maybe you could even signal exactly when a new variation will become available to encourage them to play again and unlock the next one.

 

So that’s my theory on endless games :)

Tags: , ,