Social

Chris Ashworth on LinkedInmid_gen on GitHub

MENU
  • Blog
  • Code
    • UnrealEngine
      • GOAPer
      • CashGen
      • CashUI
      • UnrealFastNoise
      • UESVON
      • UEBoids
  • Links
    • Rachel Higginbottom
    • Bob Morate
    • Linda Rendel
    • Ubisoft Blue Byte
  • About

A year in games - 2015

Category: Site
Published: 29 December 2015

As we're coming up to 2016 and I've got all the various changes done on the domain and site, I thought I'd finish off the year as I mean to go into the next with an article, and what better than my review of gaming in 2015.

The Games

Well, there's no way around it, for me 2015 was dominated by Destiny. Obviously it launched in 2014 but I have been playing it almost exclusively throughout the year until December. What's kept me interested? Well it is first and foremost a very polished FPS, the core gameplay is terrific, the variety of weapons, gear and enemies is superb. The music, artwork, voice acting just add to what is a beautiful game to behold, I've never been so taken in by a game world...but all this aside, what has really kept me engaged is the community. I've met a great bunch of people both through work and online and spent the majority of my game time in parties on voice comms. The predominantly co-operative nature of the game engenders a great sense of camaraderie, even when the game deals you a crap hand, it's all taken in good spirits and everyone has a good laugh about it.

But alas, I have sunk a huge amount of time into the game, and after beating the last of the King's Fall challenge modes in December, I feel like I'm finally done with the game. The Taken King DLC was excellent, and I thoroughly enjoyed my time playing through it, but now, I'm out. There are too many other games to play, and too many things I need to be spending my time on (like this website!). 

Other games I've dabbled in this year include Elite: Dangerous, which was a phenomenal experience on the Oculus Rift, but the emptiness of the universe and the huge amount of time required to get the most out of the game has meant I have barely touched it since launch. I backed the game well before launch and I have a lifetime pass, so I will be keeping an eye on future updates, particularly the atmospheric planetary landings which should turn a game with a lot of potential into something truly engrossing.

Star Wars Battlefront got some playtime in the run up to Christmas, after sinking so many hours chasing carrots in Destiny it felt great to have a game you can just drop into for 15 minutes and have a bit of quick simple fun. Glorious to look at and listen to, and in my view, mercifully shallow. I had a little dabble in Homeworld Remastered for old time's sake, and popped in to see how Star Citizen is going occasionally, but apart from that, that's about all my gaming this year.

Making The Games

A big year for engines, with Unity and UnrealEngine really duking it out for their slice of the market. Having spent time in both, it's hard to see past UnrealEngine for the hobbyist or indie, free access, a quality IDE, great Visual Studio integration, the language of pros (C++), and most of all, complete source code access. It's really a tremendous time to get into making games, compared to back in 2003 when I was at university and there were precious few engines around and you pretty much had to roll your own, to be able to get a AAA engine like Unreal for nothing and start making things on day 1 is invaluable. 

I'll admit I've given Unity very little time this year, back before I joined Blue Byte and I was dabbling in mobile games, even when I wasn't doing anything terribly complicated I was running into bugs, and with no source code to look at you're stuck with hacky workarounds. At least it plays nice with Visual Studio now, and for mobile games it probably trumps UnrealEngine which is a bit more heavyweight.

The Gaming Community

After all the noise late last year things settled down and we've really started see more equal representation of races and genders in games become the norm, rather than the subject of headlines and countless, foaming-at-the-mouth comment section outpourings of bile. Long may it continue.

This is already a bit late, so I'm going to end it here, and start the new year with an article on what I'm looking forward to in 2016.

Frohes Neues!

A new home: Cashworth.net!

Category: Site
Published: 27 December 2015

As you will know if you are seeing this, my site has moved! The original domain 'appzeit.com' was something I chose back when I quit the enterprise software industry and wanted a mobile app development related name. These days this website is really just my personal page for various game development stuff, so I've moved to a more generic domain that will be home to all my STUFF.

Of course, I will have to make a new logo and change some labels, but the move seems to have been pretty painless so far, no broken links as far as I can tell :)

More Boids - Predators preview

Category: Site
Published: 02 December 2015

Still working on refactoring the boids code a little and testing the extensibility by implementing some 'predator' boid types. Here's a little preview until I get the article written. You can of course check out the latest code on Github in the meantime.

{youtube}Gm72CF5ZWJY{/youtube}

{fcomment}

 

Unrealengine 4 'Boids' Implementation in C++ - PT4 - Refactoring!

Category: Unrealengine
Published: 25 November 2015

So we have a working boids implementation in UnrealEngine, this is fine and all, but when we come to look at expanding the behaviours of our boids...we're going to start hitting a wall.

In the original implementation, all boids use the same hard-coded algorithms, and will always behave identically. I embarked on a refactoring of the code with the following aims:

  • Allow boid behaviour algorithms to be added and removed dynamically at runtime.
  • Allow boids to maintain their own state and therefore behave independent of other boids.

The core of this meant refactoring the boid behaviours out into their own class, BoidAlgo. Here's the header :

class BoidAlgo
{
public:
	BoidAlgo(int _algo_type, float _weight);
	virtual ~BoidAlgo();

	// Some consts for readability
	static const int COHERENCE = 0;
	static const int ALIGNMENT = 1;
	static const int AVOIDANCE = 2;
	static const int BOUNDS = 3;

	// The boid algorithm declarations
	static FVector func_coherence(const ABoid& _currentBoid, const boid_config& _config, const float& _weight);
	static FVector func_alignment(const ABoid& _currentBoid, const boid_config& _config, const float& _weight);
	static FVector func_avoidance(const ABoid& _currentBoid, const boid_config& _config, const float& _weight);
	static FVector func_bounds(const ABoid& _currentBoid, const boid_config& _config, const float& _weight);

	bool setAlgo(int _algoEnum);

	// Function pointer used to define which algorithm is to be used in this instance
	FVector(*calc_func) (const ABoid& _currentBoid, const boid_config& _config, const float& _weight);

	// weighting to apply to this algorithm
	float weight;

};

 Each boid behaviour is now defined as a static function within BoidAlgo. Each instance of BoidAlgo only contain the weight to apply to the algorithm, and a function pointer *calc_func to the appropriate static function. When we create a BoidAlgo we pass the algo type and weight to the constructor and hey presto, one very lightweight algorithm class. I did initially go the usual inheritance route of having an abstract BoidAlgo class and concrete implementations of each algorithm, but decided that this approach is cleaner, less files, and just as easy to maintain.

The setup and configuration of the boids by the BoidManager now looks like this :

// Called when the game starts or when spawned
void ABoidManager::BeginPlay()
{
	Super::BeginPlay();
	World = GetWorld();
	FVector thisSpawnPos;

	// Populate the configuration struct with values from the editor
	//   ready to pass to the boids

	config.allBoids = &boids;
	config.avoidBoidRange = AvoidBoidRange;
	config.avoidBoundsStrength = AvoidBoundsStrength;
	config.velocityMax = VelocityMax;
	config.cohesionWeight = CohesionWeight;
	config.avoidWeight = AvoidWeight;
	config.alignWeight = AlignWeight;
	config.spawnBoundsStart = SpawnBoundsStart;
	config.spawnBoundsEnd = SpawnBoundsEnd;
	config.interactionRange = InteractionRange;

	for (int32 i = 0; i < NumberOfBoids; i++)
	{
		//  Pick a random point in the defined bounds to spawn
		thisSpawnPos.X = FMath::RandRange(SpawnBoundsStart.X, SpawnBoundsEnd.X);
		thisSpawnPos.Y = FMath::RandRange(SpawnBoundsStart.Y, SpawnBoundsEnd.Y);
		thisSpawnPos.Z = FMath::RandRange(SpawnBoundsStart.Z, SpawnBoundsEnd.Z);

		// Spawn the boid into the world, keep the reference
		ABoid* spawnedBoid = World->SpawnActor<ABoid>(ABoid::StaticClass(), thisSpawnPos, FRotator(0.0f));

		// Stash the reference, key to this implementation!
		boids.Add(spawnedBoid);

		// Setup the vector of algorithms to give to this boid
		// Note we're giving each boid it's own instance so they can change independently
		TArray<BoidAlgo> _algos;
		BoidAlgo algo_coherence(BoidAlgo::COHERENCE, config.cohesionWeight);
		BoidAlgo algo_alignment(BoidAlgo::ALIGNMENT, config.alignWeight);
		BoidAlgo algo_avoidance(BoidAlgo::AVOIDANCE, config.avoidWeight);
		BoidAlgo algo_bounds(BoidAlgo::BOUNDS, 1.0f);

		_algos.Add(algo_coherence);
		_algos.Add(algo_alignment);
		_algos.Add(algo_avoidance);
		_algos.Add(algo_bounds);

		// Pass the configuration and starting algorithms to the boid
		spawnedBoid->setup(&config, _algos);
	}
}

 Pretty similar to before, but now we are creating a vector of BoidAlgo instances for each Boid. This might seem wasteful, but remember, each instance only contains a float and a function pointer.

Inside the Boid class, we now handle all the behaviours with just a few lines of code :

		for (auto& _algo : algos)
		{
			newVelocity += _algo.calc_func((*this), (*config), _algo.weight);
		}

 Just loop through the algos we have and apply the result to our new velocity. 

Although the boids behave exactly as they did previously, we now have a much more robust codebase to start adding advanced behaviours. We can change the algo weightings on each boid individually, and even add and remove algorithms on the fly....perhaps we will be adding an algorithm for terrain avoidance or predator evasion? Now it's as easy as writing the static function in BoidAlgo and adding it to the Boid's list of algos. Sorted :)

As before, all the code is available here on github (note I've moved to a new repo with this refactoring).

{fcomment}

Page 14 of 20

  • Start
  • Prev
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • Next
  • End