Simple Lamp Animation

I modeled and animated a simple lamp to learn about rigging and kinematics. Below you can see the complete process.

First I modeled a simple lamp, using both box modeling and bezier curves:

wip lamp wirewip lamp renderwip lightbulb materialsThe light bulb was also modeled through bezier curves. It was given a blackbody material to more realistically represent the colour tone of a light source when interacting with another surface (see the slightly warmer colour on the inside of the lamp)

wip lightbulb wirewip lightbulb renderI then rigged the entire lamp and constricted its movement to rotation around a single axis depending on the type of joint.

After the basic rig worked, adding reverse auto kinematics made all the bones in the rig respond when only a single one was being manipulated. This gave the whole rig a more realistic feel to it.

Next up was animating the scene:

I found the scene to be more dynamic once I also animated the camera:

After adding some simple textures I rendered the entire thing:

A simple 6 second animation at 720p 60fps still took well over 12 hours to render. I sincerely hope I will not have to render Full HD or 4K projects any time soon.

I’m glad I finally learned the basics of animation. I had been putting that off, but it’s really not that difficult to get a working rig.

Chessboard: Modeling and Texturing

The latest assignment in my Blender course was to model and texture a chess set. This is a classic assignment because it allows for a wide variety of modeling techniques to be demonstrated. On the other hand, the scope of the project stays manageable.

This section was really cool. I feel like I learned a lot. Below you can find my chess pieces and final renders. The last 4 renders display a famous game between Garry Kasparov and Veselin Topalov.

Pawn:

pawn reference pawn wire pawn solidRook

Rook referenceRook wireRook solidKnight

knight referenceknight wireknight solidBishop

bishop referencebishop wirebishop solidQueen

King

King referenceKing wireKing solidFinal Scene

I changed the texture of the chessboard. I initially went with adding a texture per square and duplicating that to all squares of the same colour and keeping the rosewood texture around that, like we did in the lecture. However, I found the squares to be quite repetitive, so I made the whole playing field from one piece of wood (source:  wildtextures.com) and changed the squares’ colour in GIMP. This way uses more memory for rendering and in game, but on the upside: there’s no texture repetition between all squares from the same colour, as the grooves carry on from one square to the next.

The wooden pieces use a seamless texture (source: maxtextures.com) mapped with coordinates “generated” and projection “tube”.

If you want to use the textures, you can find them here:

Board:

Center Diffuse

Outer Diffuse

Bump map

Reflection Map

Pieces:

Light diffuse

Dark diffuse

Bump map

Reflection map

Simple bowling scene in Blender 3D

In order to create my own game assets, I’m taking a course in Blender 3D. Up to this point we’ve covered basic box modeling, Bézier curves and simple materials.

Below you can find my entire process of going from the initial reference material all the way to a finished bowling scene. As always, your feedback is greatly appreciated.

Creating the curve:

Larian Studios is Looking for Gamers to Play Divinity: Original Sin II

The studio behind the excellent Divinity: Original Sin are looking for players in the cities of Gent, Quebec City and St. Petersburg to play test sequel Divinity: Original Sin II in one of the weeks of August.  I have already applied, let’s hope I’m one of the lucky few.

You can find more information here: http://www.divinity.game/newsposts/2017/7/7/were-looking-for-gamers-to-play-divinity-original-sin-ii

Blockbustoid

The third assignment in my course on Unity game development was creating an Arkanoid clone. I feel like I learned a lot about a variety of topics, such as sprites, colliders, velocity, music, sound effects, gravity and simple physics. Click the screenshot below to play the game on Kongregate.

blockbustoid-screenshot

Bugs and features
Not long after publishing I noticed 2 bugs. The multiplier does not reset if you move from the game screen to the main menu and then start a new game. This can allow you to farm multiplier, quit to main menu and then start again to improve on the theoretical maximum high score. Game number 3 and there’s already cheats and exploits. Smh.
A bit more annoying is that the lives counter doesn’t grant you an extra life when you beat a level, making the game significantly harder to finish.

I would also like to add an options screen where you can change the volume for both music and sound effects. I’ll update this post once the game has been patched.

Sourcecode
I’m amazed at how fast the scope of even such a simple game expands. There are 116 scripts, sprites, images, sounds etc in this project. Therefore I will no longer be providing the code. If you’re interested in having a look at the project or its code, let me know in the comments and I’ll send you a copy.

Added a GUI to Number Wizard

As part of an ongoing course I’m taking in Unity game development, I added a menu and splash screen to the number guessing game I made earlier. You can play the game by clicking the picture below:

nw-screenshotYou can find the full code below:

Number Wizard UI (C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
 
public class NumberWizard : MonoBehaviour {
 
	// Use this for initialization
	int max;
	int min;
	int guess;
	int counter;
 
	int maxGuessesAllowed;
 
	public Text text;
 
	void Start () {	
		StartGame ();	
	}
 
	void StartGame () {
		max = 1000;
		min = 1;
		guess = 500;
		counter = 1;
		max = max+1;
		maxGuessesAllowed = 9;
	}
 
	public void GuessHigher(){
		min = guess;
		NextGuess ();
	}
 
	public void GuessLower(){
		max = guess;
		NextGuess ();
	}
 
	void NextGuess(){
		guess = (max+min)/2;
		counter = counter+1;
		text.text = "Is your number " +guess +"?\n\n I have guessed " +counter +" times.";
		maxGuessesAllowed = maxGuessesAllowed-1;
		if (maxGuessesAllowed <= 0){
			Application.LoadLevel("Win");
		} 
	}
 
}

[collapse]

As always, any tips or comments are greatly appreciated.

Jailbreak: a simple text adventure in Unity

As part of an ongoing course I’m taking in Unity game development, I created a short text adventure called Jailbreak. You can play the game by clicking the picture below:

Jailbreak preview You can find the full code below:

Jailbreak (C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
 
public class TextController : MonoBehaviour {
 
	public Text text;
	private enum States {intro, cell, mirror, sheets_0, lock_0, cell_mirror, sheets_1, mirror_broken, lock_1, hallway, femdoor, storage, smokealarm, guardroom,
						hallway_1, hallway_lighter, femdoor_lighter, storage_lighter, guardroom_lighter, smokealarm_lighter, hallway_sprinkler, femdoor_sprinkler,
						storage_sprinkler, smokealarm_sprinkler, guardroom_sprinkler, hallway_sprinkler_1, hallway_key, femdoor_key, storage_key, smokealarm_key,
						guardroom_key, femhallway, firstcell, secondcell, thirdcell, femhallway_lily};
	private States myState;
 
	// Use this for initialization
	void Start () {
		myState = States.intro;
	}
 
	// Update is called once per frame
	void Update () {
		print (myState);
		if (myState == States.intro) {
			state_intro ();
		} else if (myState == States.cell) {
			state_cell ();
		} else if (myState == States.sheets_0) {
			state_sheets_0 ();
		} else if (myState == States.mirror) {
			state_mirror ();
		} else if (myState == States.lock_0) {
			state_lock_0 ();
		} else if (myState == States.cell_mirror) {
			state_cell_mirror ();
		} else if (myState == States.sheets_1) {
			state_sheets_1 ();
		} else if (myState == States.mirror_broken) {
			state_mirror_broken ();
		} else if (myState == States.lock_1) {
			state_lock_1 ();
		} else if (myState == States.hallway) {
			state_hallway ();
		} else if (myState == States.femdoor) {
			state_femdoor ();
		} else if (myState == States.storage) {
			state_storage ();
		} else if (myState == States.smokealarm) {
			state_smokealarm ();
		} else if (myState == States.guardroom) {
			state_guardroom ();
		} else if (myState == States.hallway_1) {
			state_hallway_1 ();
		} else if (myState == States.hallway_lighter) {
				state_hallway_lighter ();
		} else if (myState == States.femdoor_lighter) {
			state_femdoor_lighter ();
		} else if (myState == States.storage_lighter) {
			state_storage_lighter ();
		} else if (myState == States.smokealarm_lighter) {
			state_smokealarm_lighter ();
		} else if (myState == States.guardroom_lighter) {
			state_guardroom_lighter ();
		} else if (myState == States.hallway_sprinkler) {
			state_hallway_sprinkler ();
		} else if (myState == States.hallway_sprinkler_1) {
			state_hallway_sprinkler_1 ();
		} 	else if (myState == States.femdoor_sprinkler) {
			state_femdoor_sprinkler ();
		} else if (myState == States.storage_sprinkler) {
			state_storage_sprinkler ();
		} else if (myState == States.smokealarm_sprinkler) {
			state_smokealarm_sprinkler ();
		} else if (myState == States.guardroom_sprinkler) {
			state_guardroom_sprinkler ();
		} else if (myState == States.hallway_key) {
			state_hallway_key ();
		} 	else if (myState == States.femdoor_key) {
			state_femdoor_key ();
		} else if (myState == States.storage_key) {
			state_storage_key ();
		} else if (myState == States.smokealarm_key) {
			state_smokealarm_key ();
		} else if (myState == States.guardroom_key) {
			state_guardroom_key ();
		} else if (myState == States.femhallway) {
			state_femhallway ();
		} else if (myState == States.firstcell) {
			state_firstcell ();
		} else if (myState == States.secondcell) {
			state_secondcell ();
		} else if (myState == States.thirdcell) {
			state_thirdcell ();
		} else if (myState == States.femhallway_lily) {
			state_femhallway_lily ();
		}
	}
 
	#region state handler methods
 
	void state_intro () {
		text.text = "\n\nYou wake up from the sound of something hitting metal. It might as well be hitting " +
					"you straight on the skull. You have a terrible headache and an even worse feeling in " +
					"your stomach. You look up to see the bulge in the top bunk, revealing where your " +
					"gorilla of a cell mate is currently sleeping off his hangover. Booze is not hard to " +
					"find in here, provided you have the right friends. Not exactly your specialty, the friend " +
					"department. Most certainly not in here. But then you remember the one friend you do have. " +
					"You need to get out of here and save her. She hasn't got much time left. You smash your " +
					"fist against the wall in anger. Your knuckles add to the symphony of pain, but at least " +
					"your head doesn't feel as bad as before. You grunt and get up, just as the guard finishes " +
					"his morning rounds.\n\n\nPress space to continue.";
		if (Input.GetKeyDown(KeyCode.Space)){
			myState = States.cell;
		}
	}
 
	void state_cell (){
		text.text = "\n\nYou pace through your cell.\n\n\nPress 'S' to view sheets." +
				"\nPress 'M' to view mirror." +
				"\nPress 'L' to view lock.";
		if (Input.GetKeyDown(KeyCode.S)){
			myState = States.sheets_0;
		} else if (Input.GetKeyDown(KeyCode.M)){
			myState = States.mirror;
		} else if (Input.GetKeyDown(KeyCode.L)){
			myState = States.lock_0;
		}
	}
 
	void state_sheets_0 (){
		text.text = "\n\nYou look at the sheets. You cannot believe you sleep in these things. They haven't been changed in ages. " +
					"Yet another example of the pleasures of prison life.\n\nPress 'R' to return to roaming your cell.";
		if (Input.GetKeyDown(KeyCode.R)){
			myState = States.cell;
		}
	}
 
	void state_mirror (){
		text.text = "\n\nYou look at your reflection in the mirror. It has seen better days. The friendly neighbourhood gorilla smashed " +
					"the lower right corner to pieces. \n\nPress 'P' to pry loose a shard of the mirror.\nPress 'R' to return to roaming your cell.";
		if (Input.GetKeyDown(KeyCode.R)){
			myState = States.cell;
		} else if (Input.GetKeyDown(KeyCode.P)){
			myState = States.cell_mirror;
		}
	}
 
	void state_lock_0 (){
		text.text = "\n\nYou try the cell door. Unsurprisingly, it's closed. The lock is operated through a keypad. " +
					"You have no idea what the combination is. You wish you could somehow see where the dirty " +
					"fingerprints on the outer keypad were, maybe that would help. \n\nPress 'R' to return to roaming your cell.";
		if (Input.GetKeyDown(KeyCode.R)){
			myState = States.cell;
		}
	}
 
	void state_cell_mirror (){
		text.text = "\n\nYou pace through your cell with the mirror shard in your hand.\n\n\nPress 'S' to view sheets." +
					"\nPress 'M' to view mirror." +
					"\nPress 'L' to view lock.";
		if (Input.GetKeyDown(KeyCode.S)){
			myState = States.sheets_1;
		} else if (Input.GetKeyDown(KeyCode.M)){
			myState = States.mirror_broken;
		} else if (Input.GetKeyDown(KeyCode.L)){
			myState = States.lock_1;
		}
	}
 
	void state_sheets_1 (){
		text.text = "\n\nYou look at the sheets. You cannot believe you sleep in these things. They haven't been changed in ages. " +
			"Yet another example of the pleasures of prison life.\n\nPress 'R' to return to roaming your cell.";
		if (Input.GetKeyDown(KeyCode.R)){
			myState = States.cell_mirror;
		}
	}
 
	void state_mirror_broken (){
		text.text = "\n\nYou look at your reflection in the mirror. It has seen better days. A shard in the lower right is missing. " +
					"\n\nPress 'R' to return to roaming your cell.";
		if (Input.GetKeyDown(KeyCode.R)){
			myState = States.cell_mirror;
		}
 
	}
 
	void state_lock_1 (){
		text.text = "\n\nYou slide the mirror shard under the door and after some adjustments, you can see the keypad. The two " +
					"bottom rows are clearly more worn-out than the others. Surely these guards couldn't be this sloppy? " +
					"\n\nPress 'R' to return to roaming your cell.\nPress 'C' to enter the combination '9876' on the keypad.";
		if (Input.GetKeyDown(KeyCode.R)){
			myState = States.cell_mirror;
		} else if (Input.GetKeyDown(KeyCode.C)){
			myState = States.hallway;
		}
	}
 
	void state_hallway (){
		text.text = "\n\nThe keypad gives a short buzz and the door unlocks. You slip out before your cellmate wakes up and find yourself in a dimly light corridor." +
					"At the end of the hallway you can see the door that leads to the female wing, where Lily is being held. There's a small storage room a few feet " +
					"to your right. Several sprinklers and two smoke alarms are attached to the corridor ceiling. You can hear the faint noise from a TV set coming from the guard booth." +
					"\n\nPress 'F' to try the door to the female wing of the prison." +
					"\nPress 'S' to go into the storage room. \nPress 'A' to inspect the smoke alarm. \n Press 'G' to sneak up to the guard room.";
		if (Input.GetKeyDown(KeyCode.F)){
			myState = States.femdoor;
		} else if (Input.GetKeyDown(KeyCode.S)){
			myState = States.storage;
		} else if (Input.GetKeyDown(KeyCode.A)){
			myState = States.smokealarm;
		} else if (Input.GetKeyDown(KeyCode.G)){
			myState = States.guardroom;
		}
	}
 
	void state_femdoor (){
		text.text = "\n\nThe door to the female prison wing is made from half a foot of solid steel. It doesn't have a keypad, but instead sports an enormous keyhole." +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_1;
		}
 
	}
 
	void state_storage (){
			text.text = "\n\nThere's a storage rack with cardboard boxes in the room. In the corner you can see a bucket and some mops, as well as several bottles of detergent " +
				"Next to one of the cardboard boxes you see half a pack of cigarettes and a lighter. \n\nPress 'H' to return to the hallway. \nPress 'L' to take the lighter.";
			if (Input.GetKeyDown(KeyCode.H)){
				myState = States.hallway_1;
			} else if (Input.GetKeyDown(KeyCode.L)){
				myState = States.hallway_lighter;
			}
		}
 
	void state_smokealarm (){
			text.text = "\n\nThe smoke alarm is seems pretty old, but the blinking red light tells you that it still works." +
				"\n\nPress 'H' to return to the hallway.";
			if (Input.GetKeyDown(KeyCode.H)){
				myState = States.hallway_1;
			}
 
		}
 
	void state_guardroom (){
			text.text = "\n\nThe guard room's door is slightly ajar. You peek through and see the guard watching 'Whose line is it anyway?' on a portable TV set. He's laughing loudly." +
						"There's a bunch of keys on a wall-mounted rack. The guard shifts in his chair and you quickly hide behind the door. \n\nPress 'H' to return to the hallway.";
			if (Input.GetKeyDown(KeyCode.H)){
				myState = States.hallway_1;
			}
 
		}	
 
	void state_hallway_1 (){
		text.text = "\n\nAt the end of the hallway you can see the door that leads to the female wing, where Lily is being held. There's a small storage room a few feet " +
					"to your right. Several sprinklers and two smoke alarms are attached to the corridor ceiling. You can hear the faint noise from a TV set coming from the guard booth." +
					"\n\nPress 'F' to try the door to the female wing of the prison." +
					"\nPress 'S' to go into the storage room. \nPress 'A' to inspect the smoke alarm. \n Press 'G' to sneak up to the guard room.";
		if (Input.GetKeyDown(KeyCode.F)){
			myState = States.femdoor;
		} else if (Input.GetKeyDown(KeyCode.S)){
			myState = States.storage;
		} else if (Input.GetKeyDown(KeyCode.A)){
			myState = States.smokealarm;
		} else if (Input.GetKeyDown(KeyCode.G)){
			myState = States.guardroom;
		}
	}
 
	void state_hallway_lighter (){
		text.text = "\n\nAt the end of the hallway you can see the door that leads to the female wing, where Lily is being held. There's a small storage room a few feet " +
				"to your right. Several sprinklers and two smoke alarms are attached to the corridor ceiling. You can hear the faint noise from a TV set coming from the guard booth." +
				"\n\nPress 'F' to try the door to the female wing of the prison." +
				"\nPress 'S' to go into the storage room. \nPress 'A' to inspect the smoke alarm. \n Press 'G' to sneak up to the guard room.";
		if (Input.GetKeyDown(KeyCode.F)){
			myState = States.femdoor_lighter;
		} else if (Input.GetKeyDown(KeyCode.S)){
			myState = States.storage_lighter;
		} else if (Input.GetKeyDown(KeyCode.A)){
			myState = States.smokealarm_lighter;
		} else if (Input.GetKeyDown(KeyCode.G)){
			myState = States.guardroom_lighter;
		}
	}
 
	void state_femdoor_lighter (){
		text.text = "\n\nThe door to the female prison wing is made from half a foot of solid steel. It doesn't look like it would melt even if you used up all the lighter fluid. " +
					"It doesn't have a keypad, but instead sports an enormous keyhole." +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_lighter;
		}
 
	}
 
	void state_guardroom_lighter (){
		text.text = "\n\nThe guard room's door is slightly ajar. You peek through and see the guard watching 'Whose line is it anyway?' on a portable TV set. He's laughing loudly." +
				"There's a bunch of keys on a wall-mounted rack. You briefly contemplate to set the nearby paper bin on fire, but when the guard shifts in his chair you quickly hide " +
				"behind the door. \n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_lighter;
		}
 
	}	
 
	void state_storage_lighter (){
		text.text = "\n\nThere's a storage rack with cardboard boxes in the room. In the corner you can see a bucket and some mops, as well as several bottles of detergent " +
			"Next to one of the cardboard boxes you see half a pack of cigarettes. You took the lighter earlier. \n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_lighter;
		}
	}
 
	void state_smokealarm_lighter (){
		text.text = "\n\nThe smoke alarm is seems pretty old, but the blinking red light tells you that it still works." +
			"\n\nPress 'L' to hold the lighter under the smoke alarm. \nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_1;
		} else if (Input.GetKeyDown(KeyCode.L)){
			myState = States.hallway_sprinkler;
		}
	}
 
	void state_hallway_sprinkler (){
		text.text = "\n\nSprinklers suddenly erupt and you hear the guard rushing out of his room while you quickly hide in the storage room. " +
					"The guard runs by while yelling something in his walkie-talkie." +
					"\n\nPress 'H' to return to the hallway after the guard has left.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_sprinkler_1;
		}
	}
 
	void state_hallway_sprinkler_1 (){
		text.text = "\n\nSprinklers are releasing large amounts of water throughout the hallway. You can just make out the door to the female prison wing at the end of the hallway. " +
					"The storage room is to your right. \n\nPress 'F' to try the door to the female wing of the prison." +
					"\nPress 'S' to go into the storage room. \nPress 'A' to inspect the smoke alarm. \n Press 'G' to sneak up to the guard room.";
		if (Input.GetKeyDown(KeyCode.F)){
			myState = States.femdoor_sprinkler;
		} else if (Input.GetKeyDown(KeyCode.S)){
			myState = States.storage_sprinkler;
		} else if (Input.GetKeyDown(KeyCode.A)){
			myState = States.smokealarm_sprinkler;
		} else if (Input.GetKeyDown(KeyCode.G)){
			myState = States.guardroom_sprinkler;
		}
	}
 
	void state_femdoor_sprinkler (){
		text.text = "\n\nThe door to the female prison wing is made from half a foot of solid steel. It's getting rather wet, but it doesn't look like it would disintegrate from rust " +
					" any time soon. It doesn't have a keypad, but instead sports an enormous keyhole." +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_sprinkler;
		}
 
	}
 
	void state_guardroom_sprinkler (){
		text.text = "\n\nThe guard room's door is wide open now. The TV is still on, but the guard is nowhere to be seen. He took several keys from the rack, but there's a couple of keys left. " +
					"\n\nPress 'T' to take the large key from the rack. \nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_sprinkler;
		} else if (Input.GetKeyDown(KeyCode.T)){
			myState = States.hallway_key;
		} 
 
	}	
 
	void state_storage_sprinkler (){
		text.text = "\n\nThe cardboard boxes on the storage rack are becoming soggy. The bucket is slowly filling with water. There's a faint hint of cleaning detergent in the air. " +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_sprinkler;
		}
	}
 
	void state_smokealarm_sprinkler (){
		text.text = "\n\nThe majority of the smoke alarm is charred from your lighter. The red light is still blinking. " +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_sprinkler;
		}
	}
 
	void state_hallway_key (){
		text.text = "\n\nSprinklers are releasing large amounts of water throughout the hallway. You can just make out the door to the female prison wing at the end of the hallway. " +
					"The storage room is to your right. \n\nPress 'F' to try the door to the female wing of the prison." +
					"\nPress 'S' to go into the storage room. \nPress 'A' to inspect the smoke alarm. \n Press 'G' to sneak up to the guard room.";
		if (Input.GetKeyDown(KeyCode.F)){
			myState = States.femdoor_key;
		} else if (Input.GetKeyDown(KeyCode.S)){
			myState = States.storage_key;
		} else if (Input.GetKeyDown(KeyCode.A)){
			myState = States.smokealarm_key;
		} else if (Input.GetKeyDown(KeyCode.G)){
			myState = States.guardroom_key;
		}
	}
 
	void state_femdoor_key (){
		text.text = "\n\nThe door to the female prison wing is made from half a foot of solid steel. It's getting rather wet, but it doesn't look like it would disintegrate from rust " +
					" any time soon. It doesn't have a keypad, but instead sports an enormous keyhole." +
					"\n\nPress 'U' to unlock the door. \nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_key;
		} else if (Input.GetKeyDown(KeyCode.U)){
			myState = States.femhallway;
		} 
 
	}
 
	void state_guardroom_key (){
		text.text = "\n\nThe guard room's door is wide open now. The TV is still on, but the guard is nowhere to be seen. He took several keys from the rack, but there's a couple of keys left. " +
					"You have already taken the large key from the rack. \n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_key;
		} 
 
	}	
 
	void state_storage_key (){
		text.text = "\n\nThe cardboard boxes on the storage rack are becoming soggy. The bucket is slowly filling with water. There's a faint hint of cleaning detergent in the air. " +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_key;
		}
	}
 
	void state_smokealarm_key (){
		text.text = "\n\nThe majority of the smoke alarm is charred from your lighter. The red light is still blinking. " +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.hallway_key;
		}
	}
 
	void state_femhallway (){
		text.text = "\n\nYou find yourself in the female prison wing. The sprinklers have been turned on here as well. There are several occupied cells. " +
					"\n\nPress 'F' to look through the first cell door." +
					"\nPress 'S' to look through the second cell door. \nPress 'T' to look through the first cell door.";
		if (Input.GetKeyDown(KeyCode.F)){
			myState = States.firstcell;
		} else if (Input.GetKeyDown(KeyCode.S)){
			myState = States.secondcell;
		} else if (Input.GetKeyDown(KeyCode.T)){
			myState = States.thirdcell;
		}
	}
 
	void state_firstcell (){
		text.text = "\n\nA woman is standing on the other side of the door. She's trying to see what is going on. As soon as she spots you, she starts " +
					"banging on the door and shouting at you to open her cell" +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.femhallway;
		}
	}
 
	void state_secondcell (){
		text.text = "\n\nThe cell is empty" +
					"\n\nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.femhallway;
		}
	}
 
	void state_thirdcell (){
		text.text = "\n\nAt long last, you find Lily. She breaks out into a devilish little grin as she sees you. 'About time!' she laughs." +
					"\n\nPress 'C' to try the same combination on the keypad. \nPress 'H' to return to the hallway.";
		if (Input.GetKeyDown(KeyCode.H)){
			myState = States.femhallway;
		} else if (Input.GetKeyDown(KeyCode.C)){
			myState = States.femhallway_lily;
		}
	}
 
	void state_femhallway_lily (){
		text.text = "\n\nLily takes you by the hand and pulls you through another corridor into a maintenance room. You spot a sewage duct and reluctantly make " +
					" your way out to the main sewers. After wandering through the sewer system for what feels like at least a day, you suddenly spot light in the distance." +
					"\n\nFreedom awaits. \n\n\n\n\nPress space to play again.";
		if (Input.GetKeyDown(KeyCode.Space)){
			myState = States.intro;
		}
	}
 
	#endregion
}

[collapse]

As always, any tips or comments are greatly appreciated.

Firewatch

Firewatch is a first-person point-and-click adventure released in 2016.

Story
It tells a story of grief and loss that will appeal mostly to people aged 30 or more. The main story is told through a series of radio conversations between Henry, a man in his early 40s, and his supervisor, Delilah. The game does an admirable job in having both Henry and the player quickly form a bond with what is essentially just a voice on the radio. This is in no small part due to the excellent voice acting. Suspense keeps the story moving and makes sure it doesn’t become stale. There are several interesting story lines throughout the game, but unfortunately the ending doesn’t manage to conclude these properly.

Graphics
The game’s cartoony style works surprisingly well for nature, and the lighting is excellent. The environments you encounter are also quite varied: you’ll spend time in the forests or by the lake, hike through a canyon, go spelunking in caves, there’s something here for everybody. The engine can be a bit choppy at times, but it’s not so severe that it breaks the magic.

Controls and UI
The controls and interface are quite barebones, which allows the player to focus more on the story. You’re eased into the controls, but the game sneakily withholds telling you that you can run until later on, once you’re already used to the more laid-back pace of walking around. You can even hide what little user interface you do have. One thing I’d recommend is turning off your location on the map, this makes the game much more immersive and realistic.

Sound
The sound design is excellent in its minimalism. There’s the occasional subdued guitar at key points in the story, but really it’s mostly wind, birds and silence.

Gameplay
The vast majority of the game is spent walking from one place to another, and that’s exactly the point. Walking through the woods and enjoying the way the light plays through the leaves is what it’s all about. Firewatch embodies the journey being the destination. You just walk, occasionally consulting your map and compass. You might stumble upon supplies, or if you’re of the lawful good alignment, the game even lets you clean up other people’s trash.

Unfortunately, exploration both in the physical world as well as through dialogue options is rather linear. While you can sidetrack, wander around a bit or change how Delilah responds depending on what dialogue option you chose, ultimately the game always shepherds you in a single, preset direction. Many people expect to make meaningful decisions and that is something you just cannot do in this game.

Verdict
Both the games industry and its audience have matured to the point where a story about grief and loss in a package that is mostly devoid of any action can still turn heads. While the game has its flaws, the graphical style, excellent voice acting and general atmosphere of the game will make sure you’ll revisit the forests of Wyoming more often than you’d think.

Made a basic number guessing game in Unity

I made a basic number guessing game in Unity as part of an ongoing course in Unity game development. You pick a number between 1 and 1000 and the computer will always guess it in 10 tries or less. This is because every time it guesses it discards half of the available options. After ten times it has gone over 2 to the 10th power options or 1024 options. This type of search algorithm is called a binary search algorithm (or binary chop).

You can see the game in action here:

You can find the code below:

Console Version:
This was the basic assignment. It does what it’s supposed to do, runs without UI in Unity’s console.

Number Wizard - Console Version (C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using UnityEngine;
using System.Collections;
 
public class NumberWizards : MonoBehaviour {
 
	// Use this for initialization
	int max;
	int min;
	int guess;
	int counter;
 
	void Start () {	
		StartGame ();	
	}
 
	void StartGame () {
		max = 1000;
		min = 1;
		guess = 500;
		counter = 1;
		max = max+1;
		print("========================");
		print("Welcome to Number Wizard");
		print("Pick a number in your head, but don't tell me.");
 
 
		print("The highest number you can pick is " +(max-1));
		print("The lowest number you can pick is " +min);
 
		print("Instructions:");
		print("I will try to guess your number.");
		print(" > Press up if it is higher than my guess.");
		print(" > Press down if it is lower than my guess.");
		print(" > Press enter if it is equal to my guess.");	
		print("Is the number " +guess +"?" +" I have guessed " +counter +" times so far.");
	}
 
	void NextGuess (){
		guess = (max+min)/2;
		counter = counter+1;
		print("Is the number " +guess +"?" +" I have guessed " +counter +" times so far.");
		}
 
 
	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown(KeyCode.UpArrow)) {
			print("The number is higher than " +guess +".");
			min = guess;
			NextGuess ();
		} else if (Input.GetKeyDown(KeyCode.DownArrow)) {
			print("The number is lower than " +guess +".");
			max = guess;
			NextGuess ();
		} else if (Input.GetKeyDown(KeyCode.Return)) {
			print("Your number is "  +guess +"!");
			print ("I found your number in " +counter +" guesses.");
		} else if (Input.GetKeyDown(KeyCode.KeypadEnter)) {
			print("Your number is "  +guess +"!");
			print ("I found your number in " +counter +" guesses.");
			}
		}
	}

[collapse]

UI Version:
This is the Number Wizard featured in the video above. I’m trying some things which haven’t been covered in the course yet, so if you spot some inelegant code (there’s bound to be plenty), feel free to let me know :)

Number Wizard - UI Version 1 (C#)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
 
public class TextController : MonoBehaviour {
 
public Text text;
 
	// Use this for initialization
	int max;
	int min;
	int guess;
	int counter;
 
	void Start () {
			StartCoroutine(Intro());
 
		}
 
	IEnumerator Intro()
		{
			max = 1000;
			min = 1;
			guess = 500;
			counter = 1;
			max = max+1;
			text.text = "Welcome.";
			yield return new WaitForSeconds(3);
			text.text = "Welcome. \n Pick a number in your head, \n but don't tell me what it is.";
			yield return new WaitForSeconds(3);
			text.text = "Welcome. \n Pick a number in your head, \n but don't tell me what it is. \n The highest number you can pick is " +(max-1) +".";
			yield return new WaitForSeconds(3);
			text.text = "Welcome. \n Pick a number in your head, \n but don't tell me what it is. \n The highest number you can pick is " +(max-1) +"." +"\n The lowest number you can pick is " +min +".";
			yield return new WaitForSeconds(3);
			text.text = "Welcome. \n Pick a number in your head, \n but don't tell me what it is. \n The highest number you can pick is " +(max-1) +"." +"\n The lowest number you can pick is " +min +"." +"\n You will now get 10 seconds \n to think of a number.";
			yield return new WaitForSeconds(3);
			text.text = "\n \n \n 10";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 9";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 8";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 7";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 6";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 5";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 4";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 3";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 2";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n 1";
			yield return new WaitForSeconds(1);
			text.text = "\n \n \n Ready?";
			yield return new WaitForSeconds(2);
			text.text = "\n \n \n I will now try to guess your number.";	
			yield return new WaitForSeconds(3);
			text.text = "Is the number " +guess +"?" +"\n(I have guessed " +counter +" time so far.)\n\n > Press the up arrow if \n it is higher than my guess. \n > Press the down arrow if \n it is lower than my guess. \n > Press enter if I guessed correctly.";
 
		}
 
	void NextGuess (){
		guess = (max+min)/2;
		counter = counter+1;
		text.text = "\n \n \n Is the number " +guess +"?" +"\n(I have guessed " +counter +" times so far.)";
	}
 
	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown(KeyCode.UpArrow)) {
			text.text = "The number is higher than " +guess +".";
			min = guess;
			NextGuess ();
		} else if (Input.GetKeyDown(KeyCode.DownArrow)) {
			text.text = "The number is lower than " +guess +".";
			max = guess;
			NextGuess ();
		} else if (Input.GetKeyDown(KeyCode.Return)) {
			text.text = "\n \n \n Your number is "  +guess +"! \n (I found your number in " +counter +" guesses.)";
		} else if (Input.GetKeyDown(KeyCode.KeypadEnter)) {
			text.text = "\n \n \n Your number is "  +guess +"! \n (I found your number in " +counter +" guesses.)";
		}
	}
	}

[collapse]