Jump to content
  • Advertisement
  • entries
  • comments
  • views

About this blog

Development of the game Mr Boom's Firework Factory in Unreal Engine 4.

This game is due for release on July 4th 2019 on PC via steam, itch.io, and GameJolt, or direct purchase from the game website via PayPal.

Closed beta is now in effect until release, if anyone is interested in taking part please drop me a PM. You must be willing to actually playtest each new feature or level which is added.

Entries in this blog


Creating the release trailer for Mr Boom's Firework Factory

Hi Everyone! In preperation for the release of Mr Boom's Firework Factory, i have created a release trailer which has been uploaded to various storefronts and to YouTube: The release trailer is an incremental improvement on the previous three trailers, one created in 2016, another created in January 2019 and the other in April 2019. This trailer was created in Lightworks Pro, using a whole load of video footage of existing gameplay, some stock footage, and static images made in GIMP with green-screen effects to overlay them onto moving images. If anyone's interested in the technical production of this trailer (as i've seen nothing technical relating to creation of trailers on this site) please let me know in the comments below, however please note that I'm generally quite new to video editing myself, certainly no expert, and this may be "a case of the blind leading the blind". This new trailer adds the following: I've used some of the voice acting I'm using in game, most notably at the end when the name of the game pops up, Mr Boom tells you to hurry up. I thought this would be a good addition as the main character of the game addresses the viewer directly, accusing them of sitting on their ass, basically goading them to go to the steam page. I've added some extra level sequences, mainly level 22, the server room. I'm keeping pretty tight-lipped on new levels now, so that if you want to find out all about later levels, you'll just have to play the game and experience them! At the very end of the trailer, the sequence goes to a VHS style 'noise', and then to some footage of the streamer NorkDorf playing the game. He got extremely wound up by the difficulty at first, and shouting angrily at the game, scared his pet cat out of the room. Every person i've shown this footage to laughed, so i decided to insert it at the end of the trailer, with his permission of course. Within the trailer, i've added YouTube cards which encourage clickthroughs to the store page, basically calls to action. As always feedback is welcome in the comments below



Returning from Casual Connect - The final sprint to finish line and release

Hi Everyone, Now that I've returned from Casual Connect London 2019, I can finally progress with pushing Mr Boom's Firework Factory to release. Casual Connect was extremely productive, and an extremely useful resource for getting the game polished and put in front of many eyes. There is a gallery for the photos of Casual Connect below: The main things that happened were: Over 70 people played the game, with overwhelmingly positive feedback. The game is as hard as we'd intended, but I need to review the tutorial and usability to ensure people are getting stuck in a good way with the game's difficulty curve, and not with the controls and learning what they actually need to do I managed to grow my professional network, meeting many other indie developers One of the people I met has encouraged me to get proper voice acting done for Mr Boom, so the main 'antagonist' of the game will have a voice! What worked? Actively encouraging people to come and play the game worked very well. Where most people patiently sat and waited for people to come and play their game, I was not content with this, and would stride with purpose into the walkway and try to convince people that they needed to play my game. A casual introduction of "hi, how are you?" would start a conversation which usually ended with 15 minutes of play. Having a rolling video of the game helped massively, if one person was playing, or we were busy networking, a second person could simply watch the video. Similarly, if someone did not want to play the game, but wanted to know how it worked they could simply watch the rolling gameplay video. Recording various players on my phone as they played help two ways; firstly, it allowed us to analyse their body language and expressions afterwards to determine where they were pleased, happy, frustrated, or confused. Secondly, these may be useful later in footage to promote the game, at key moments where people cheer to themselves or curse the game as they lose or win a level. Having Trello on our mobile phones allowed us to quickly make a list of observations in the background as people played. The appeal of the game was very strong, many people played until they had other places to be (e.g. they had a set of games they wanted to try out, or had to go to a talk or meeting) with the average game session lasting 15-20 minutes. I purposefully chose to take equipment to casual connect which could not edit the code and perform fixes. This forced me to ensure that the game was stable enough on the equipment to not need hotfixes at the event. We didn't want to be the ones sat trying to edit our code at the event for all to see. Reaching out to previous winners gave a whole wealth of useful advice, which we used. Thanks very much to Robert Kujawa at Neurodio for his in-depth email responses which helped tailor my approach to the conference. They produced a guide, which is now available to everyone, based on the emails they sent me. What didn't work? The tutorial was not strong enough to stand alone at the conference, Craig and I ended up becoming an interactive tutorial, with each player, explaining the controls and goals repeatedly. This soon became tiresome, but at the same time afforded the opportunity for the player to ask questions as they played. The hardware we had planned to use was not up to the task - the netbook I had ready to stream 1080P video was not up to the challenge on the day, luckily we had backup hardware. Recording people on our phones did not yield the excitement we had hoped to capture. While people got very excited to complete a level that had challenged them for ten minutes or more, they would react naturally and excitedly when we weren't recording, but if they were aware of the mobile phone recording their reactions would change, perhaps due to being uncomfortable with being recorded. What did I learn? This may be directly related to the types of professionals at the event, but we were repeatedly asked when this would be available on mobile. Due to this, I intend to look into a mobile port soon after the steam release, either porting it myself or finding a third party able to port it, such as a publisher. Once you put a game in front of real people, outside your testing team, they will uncover bugs you never dreamed possible. Amongst the positive feedback were at least two crashes to desktop, two different forms of lockups, and some weird non-game-breaking visual bugs. For the non-game-breaking bugs, usually the player did not notice as they were too deep into the gameplay and concentrating on finishing the level. The game needs more visual cues. For example ghosted crates on the exit, and above the machines, to give hints to what is going to happen next and what is expected of you:
          I am now starting on the list of feedback obtained from Casual Connect, so there should be another blog entry of these fixes soon. Stay tuned! If anyone has any comments or feedback as always please do leave comments below!



Mr Boom's Firework Factory has won a place at Casual Connect London!

I'm really happy to announce that my indie game Mr Boom's Firework Factory has been selected as an Indie Prize finalist and I will be attending
Casual Connect London 2019 on 28th-30th May where I will be exhibiting my game in the QEII Centre on the third floor. Come along and say hi, or have a go at my game in person! There will be a live stream during the event. I look forwards to seeing you there!



The Hydraulic Press - Not safe for use around explosives.

Hi everyone! It's been a good couple of weeks since I last posted a blog entry. With the help of @Rutin and his 3D model making expertise, i've now implemented the hydraulic press mechanics within the game, and also finished the appearance of the laser tripwires. These were required to implement level 12 of Mr Boom's Firework Factory, the first level to use electricity mechanics. The Completed Laser Tripwire Starting with the laser tripwires, i selected some free to use models, and some cheap paid models and kitbashed them to end up with something visually appealing, with some help from @Rutin converting 3D studio files into FBX. Using a CCTV camera model, an SLR camera tripod, and some weird electrical gadget, this was the end result, connecting the set using a UE4 Cable Component: There are two arrow components in this model, the one in the lens of the camera dictates where the laser beam originates from, and in which direction, and the one on the control box is a connection point for the cable actor which connects it to the object it powers. With this complete, i could move on to the hydraulic press itself. Hydraulic Press Development For the actual hydraulic press that connects to this laser tripwire, I'd started out with a basic primitive prototype, made of some textured boxes which i sent to @Rutin for a sense of scale so he could get started on something better: I then left @Rutin to do his thing, and after lots of to-ing and fro-ing, talking about how it needed to look, he finally came back with the finished product, which i turned into an actor within the game proper... The Hydraulic Press - The final model Animated Parts I also decided to add some extra parts to the model to allow for connection to a cable (the pylon at the top of the model) and to allow for animation of the display screen. The display screen uses a simple texture atlas to animate its text when it is powered up: The end result looks like this, and has some emissive applied to make it look more like an oldschool green phospor screen. It only appears when the machine is powered on: Hydraulic Press Blueprint Events This needed to be connected to the existing power system by deriving the class from my "Powered Object" class, which implements the base interface, and a set of related events added, one for powering it up and one for powering it down, plus a timer to animate the model. Power on event The power on event is called when the device receives power, it changes the materials of the screen and power button to 'lit' ones with texture atlases and emissives. Power off event The power off event reverses the behaviour of the power on event, reverting the glowing textures and texture atlases back to plain boring non-animated and non-emissive ones. Animation event The animation event is powered by two timelines, one to quickly descend the crusher to the ground, detecting any collisions with crates as it sweeps and registers collisions. Any crates it collides with are set to explode as soon as possible. The second timeline runs eight times slower, and ascends the crusher back to maximum height. Each of these timelines has a sound attached after it has finished executing, one for a loud slamming sound, and one for a hissing of hydraulics and steam engines. Both of these events only operate while the object is powered, and if power is removed, the animation always completes, leaving the crusher part at its highest position allowing crates to pass through. Once these are all rigged up, the whole thing can be tied together, which produces some wonderful and destructive machines: Videos! The videos below show the hydraulic press in all its glory. Note that the first video does not show the camera shake effect, as I had de-posessed the player pawn to reposition the camera in a better position. It appears that in UE4, a de-posessed free floating camera does not receive camera shakes. The view from the other side of the machine better demonstrates the camera shake effects used to add polish to the machine:   As always, feedback is more than welcome! Please feel free to comment below, and let me know if i missed anything! 🙂



Powered actors, laser tripwires, and simulating simple electrical connections

Hi all! As I progress through adding yet more levels to my game, I have decided that next on my to-do list is the ability to turn on and off devices around the levels based upon the crates passing along the conveyor belts. The system should give visual feedback as to what is connected to what, without me needing to manually connect cable actors to things when creating level mechanics. I took inspiration from the way sensors work on conveyor belts when building settlements and manufacturing systems in Fallout 4; So how would I go about making a similar system? Without further ado, let us begin! Part 1: The Sensor I first needed to create a laser sensor object that could detect crates passing through it. A quick google found a tutorial on making a 'laser trip mine', as seen in many FPS games, so I decided to use this as a starting point. The difference between this and a mine though is that once triggered a mine will instantly explode, so there is no need to visually display the beam being stopped by an object. In this case, this is essential as well as the ability to detect the type of object which has intersected it. I started out by creating a simple red beam particle. This is extra bright, with lots of bloom for gameplay reasons. Although a dimmer, shimmering beam much like a red laser pen or barcode reader would be much more realistic, it is also much harder to see from 'gods eye view'; We can then use this beam in an actor. I created an actor which could serve as a beam emitter, which for now is just a placeholder cube with an unrelated brightly coloured texture on it. The beam particle emits from its right hand edge in a straight horizontal line. To determine how far this beam should go, we calculate its maximum length in the Begin Play blueprint event, and also every time the Tick event fires to compensate for anything in the path of the beam which stops it. The first of these images is the BeginPlay event, which does three things: 1) Find the actor that the switch powers on/off, identified by a tag
2) Call the function to line trace the beam to its endpoint
3) Create and set up a cable actor connecting this sensor to its powered object for visual polish The function Create Beam is simple, as it simply gets the start and end locations, spawns an emitter at the start location and sets the end point of the particle effect: The Calculate Beam Length is a little more complex, and is called every tick (as we need to adjust the length based on what we find intersecting it using a line trace): You'll note that this function does not just return an end position vector. As well as the ending position, it will return a reference to a Crate if one intersects the beam, or an invalid (null) reference if the beam does not intersect a crate. We use this later on to determine whether or not to toggle power to connected actors: The three options at the end of this event are implemented by the NativePowered class, which I will discuss in the next section... Part 2: Powered Actors To make this work, we need a way to represent which actors are powered by electrical connections. I decided to do this as a simple linked list of powered objects which share one common power source. In my game the actual source of the power is not visible, or relavent to the game mechanics, so i don't show a wall socket or similar, to avoid confusing the player. After all, they aren't building these power networks themselves! All electricity originates from a switch, so in this case the sensor we implemented above. In the tick event, when a crate intersects the laser, this fires the Set Power State method of the class, which sets the power state of that object, calls the Power On or Power Off event for that object, and then propagates the power change to the next object in the linked list. All objects which can receive power derive from one type of Actor, written as a C++ class: NativePowered.h /* Represents an actor which may receive power from a switch, and be daisy chained to other powered actors. * If a powered actor is daisy chained to another actor, power state is shared between all connected objects. */ UCLASS() class FWF_API ANativePowered : public AActor { GENERATED_BODY() /* Current power state of this actor, on or off */ bool PowerState; /* Next actor in the chain, or NULL if this is the end of the chain */ class ANativePowered* Next; /* Cable component encapsulated within actor, connecting this actor * to the next actor, if there is a chain. */ class APowerCable* Cable; public: // Sets default values for this actor's properties ANativePowered(const FObjectInitializer& ObjectInitializer); // Set power state to on or off, also changes the power state // of any 'Next' actors connected to this one UFUNCTION(BlueprintCallable, Category = "Power|Power State") void SetPowerState(bool Power); // Get current power state of the actor UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Power|Power State") bool GetPowerState(); // Called when the game starts or when spawned virtual void BeginPlay() override; // Called when the actor is destroyed virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; // Called every frame virtual void Tick( float DeltaSeconds ) override; // Can be overridden to get notification events when the object receives power. // Use this to turn on animations, enable lights, etc. UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Power|Power Event") void PowerOn(); // Can be overriden to get notification events when the object loses power. // You can use this for example to stop animations and disable lights. UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Power|Power Event") void PowerOff(); // Called after components are initialised void PostInitializeComponents(); // The main mesh of the powered actor. As objects that receive power are visible // in the level and have power cables going into and out of them, they must have a // visual presence so a mesh is the default base object. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Power|Mesh") UStaticMeshComponent* Mesh; // A tag value to find in the next connected actor in a chain. This is then used // in BeginPlay() to locate and link to the next connection. We use tags here because // there is no other way to represent this loose relation in the editor, which // only allows selection of actors that are immediate descendents of the level, // not actors embedded in child actor components, etc. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Power|Power Connection") FString NextActorInGrid; }; NativePowered.cpp /* Powered actors default to powered off */ ANativePowered::ANativePowered(const FObjectInitializer& ObjectInitializer) : PowerState(false), Next(nullptr), Cable(nullptr) { PrimaryActorTick.bCanEverTick = true; /* Create static mesh component */ Mesh = ObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("Mesh")); Mesh->AttachToComponent(GetRootComponent(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, false)); } void ANativePowered::PostInitializeComponents() { Super::PostInitializeComponents(); } void ANativePowered::EndPlay(const EEndPlayReason::Type EndPlayReason) { /* Don't leave spawned cables hanging around (literally hanging... lol) */ if (Cable != nullptr) { Cable->Destroy(); } } // Called when the game starts or when spawned void ANativePowered::BeginPlay() { Super::BeginPlay(); /* Is this powered actor daisy chained to another powered actor? */ if (NextActorInGrid != TEXT("")) { /* Find the actor with this tag. Note that if there are copies of the level actor hanging around, * there may be multiple, so always pick the last. */ TArray<AActor*> TaggedActors; UGameplayStatics::GetAllActorsWithTag(GetWorld(), FName(*this->NextActorInGrid), TaggedActors); /* We also can't have the actual NextActorInGrid property be FName directly, because FName values * in properties of a child actor are wiped to 'None' on object initialisation. Bummer. */ /* Did we find any? */ if (TaggedActors.Max()) { /* Set linked list ptr */ Next = Cast<ANativePowered>(TaggedActors.Last()); /* Get the world position of the 'Plug' socket/bone in the source actor. * Enforce a scale and rotation, regardless of the scale and rotation of the actor itself and its components. * If we don't the cable actor flies off in some random direction based on the rotation and scale. */ FTransform nextlocation = Mesh->GetSocketTransform(FName("Plug")); nextlocation.SetScale3D(FVector(1, 1, 1)); nextlocation.SetRotation(FQuat(FRotator(0, 0, 0))); FActorSpawnParameters params; params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; /* NOTE: APowerCable is basically just like ACableActor. It contains nothing but a UCableComponent, and a couple of * lines in the constructor to set its colour and thickness. * I would just be using UCableActor, but due to a BUG, i cant include it because it won't let me spawn it across * module boundaries due to a link error. Clearing intermediate files did not fix this bug, as the answerhub said it should. * UGH!!! */ Cable = GetWorld()->SpawnActor<APowerCable>(APowerCable::StaticClass(), nextlocation, params); /* HACK HACK - To attach to an actor, we must first specify the actor reference in OtherActor, and then we MUST * (NOTE: MUST!!!!) specify a local offset in the EndLocation, from that actor position in actor transform space. * This is the last line here, that sets the relative offset to that of the 'Plug' socket/bone within the static mesh. * Note that this behaviour is quite poorly documented. */ FComponentReference ref; ref.OtherActor = Next; Cable->CableComponent->AttachEndTo = ref; Cable->CableComponent->EndLocation = Mesh->GetSocketTransform(FName("Plug"), RTS_Actor).GetLocation(); /*FVector(0, 0, 30);*/ } } } // Called every frame void ANativePowered::Tick( float DeltaTime ) { Super::Tick( DeltaTime ); } void ANativePowered::SetPowerState(bool Power) { this->PowerState = Power; /* Trigger overridable events for this actor */ if (this->PowerState) { PowerOn(); } else { PowerOff(); } if (Next) { /* Cascade the change to other attached actors */ Next->SetPowerState(Power); } } /* Simple getter for power state */ bool ANativePowered::GetPowerState() { return PowerState; } /* Base class, empty implementation */ void ANativePowered::PowerOn_Implementation() { } /* Base class, empty implementation */ void ANativePowered::PowerOff_Implementation() { } As you can see here, we determine the next 'link' in our chain of powered objects by using the tags of the actor. We must use tags, rather than just an object reference or pointer, because which objects we can pick using the editor in this way is highly restricted, we can only choose pointers to objects that are direct instantiated objects at the root of the level itself, not for example a spawned actor that is spawned at runtime, or a child actor within a child actor component. To get around this restriction we set up our actors in the editor to work with the tags and the code written above: Source Object Destination Object We can repeat this process as many times as we like, within the editor or even at runtime, to create complex chains of powered objects triggered by one switch. Adding Sockets All that's needed now is to add a socket to a mesh. In this instance i've picked a random large mesh from my collection of props. We add a socket to it called 'Plug', this is where the cables that link each item visually connect them: Part 3: The complete system Now we can test and view the complete system as a whole. As you can see, the system visually connects the related objects, as well as having the logical association behind the scenes. Passing a crate through the laser will toggle the connected objects. This will be used in level 12 to power some quite awesome hardware, namely a large hydraulic press that will destroy crates unless you toggle some switches in the right order to turn it off! The system below is a simple test system, featuring two powered objects and a sensor: ## As always, comments and feedback are more than welcome! Please vent your spleens below! 🙂



Rewarding the player's efforts: The stock room

Hi everyone! Another week, another update to the development blog for Mr Boom's Firework Factory! The Easy Stuff: Creating the Stock Room This week, I have been creating a way to reward players for successfully completing levels. Every time a level is completed with a three star rating (the best possible rating) the game will route the player to the stock room on the completion of the level. The stock room is an enclosed area, containing some junk and six boxes. Selecting from the boxes will reward the player with one of the following: A random power-up Nothing (along with a condescending message) A booby prize, for example a burned cereal box. This new feature can be seen working in the video below: The booby prizes, if won, will just stack to an inventory, e.g. multiples are represented by "x2", "x3" etc. These can't be gotten rid of an have absolutely no use except cosmetic, so I can imagine that the player may find a way to meta-game this, and i may add an achievement relating to this if there is time before release. It is obvious on the video above that selecting boxes in the stock room is simple enough if the player is using a mouse and keyboard, simply clicking on a box will select it, and this is done effectively using the onclick events within blueprint on those particular components for the crates. The More Interesting Stuff: Making This Work With A Gamepad This becomes slightly more complex when dealing with a gamepad. Unreal Engine 4 has facilities when dealing with UMG for UI so that each control which can receive focus has a 'next' control for each direction, so if for example "Up" is pressed when focused on control A, it can be told that control B is "Up" in relation to it, and that control "B" should then receive focus. When dealing with an actor built with components, which is not UI, we're out of luck and have to implement this ourselves. Time to roll up our sleeves and see how I did this! Firstly, we must map out visually how each of the crates relate to each other. Consider that each crate has an index number between zero and five, and that for each crate index, we have a table of relations based on the direction of travel for which is "nearest" to it in that direction: So, for example, if the current crate was crate index 1 and we wanted to move up, then the crate index would become 0. Similarly if the crate index was 0 and we wanted to move right, the crate index would become 2. We can represent the currently selected crate then as a simple integer value. All clear on this? OK, let's continue! Based on this layout, we can click on each of the components in the actor, and set up these representations using the tags within the component, always sticking to a uniform layout, tag index 0 representing down, index 1 representing up, index 2 representing left, and index 3 representing right: Once all these have been defined, we have a way, completely within data, and without having to adjust code, of being able to indicate the relationship between the components so we can navigate between them. All we need to do now is write some code to do it. Firstly, we need a function which if given a a direction (as an integer) will update the current crate to a new crate, still going with the same constant directions as above, 0 = down, 1 = up, 2 = left, 3 = right. We'll call this function "Move Selection Cursor", because... well why not?: We will also need to define in the constructor, or in the Begin Play Event, the indices of each of the crates in a simple array (as a member variable of the actor class) which this function can use. Remember the order of the items in this array is important as we determined our layout in the first picture when we mapped out the relationships between the objects. If there were more objects or in different positions in relation to each other, this would need to be adjusted: Once we have done this, it is a simple matter to attach five events to action mappings, which will allow us to detect input events from the gamepad, and route them to the functions we have created. For readability's sake, we can also define four constants (see the top left in the green square) representing our index values for up, down, left, and right respectively, which means that the code becomes more understandable, rather than just a mass of magic numbers between 0 and 3: Once this is in place, as many before me have said, sometimes in jest and sometimes in seriousness, "it just works". I hope you found this journey into the depths of my mind enlightening, please do comment and leave feedback if you have any questions or comments! Stay tuned for more blog entries!  



Steam, Tutorials and more!

Hi everyone, It's been two weeks since my last blog post, and many things have happened in the development of Mr Boom's Firework Factory. The R&D Department The game now has a fifth level (not including the tutorial level mentioned below) which is set in the factory's R&D department. The R&D department is a rather dodgy area, very much below board, dealing with radioactive waste (for use in fireworks??? You be the judge!) and toxic gases. As you can tell from the products in use, this place has taken a turn for the worst and isn't what it seemd to be when the player started out on their journey: The poison gas crates emit a huge cloud of green gas when they explode, which causes the player to lose vision of the game temporarily. If done at the wrong moment, this can be catastrophic: The radioactive goop crates were previously covered in a past blog post and leave goop stains all over the level, which are destructive to anything that passes over them. Getting the game on Steam Next, and most importantly, I have finally set up the store front on Steam, and configured my build process to push builds to steam via Steampipe. This took a little time to get working, and during this time I established a closed beta. Under the offer of free keys for the game, and credit in the game's credits page, many people contacted me asking to take part, and based on the feedback they gave I now have a reasonable sized bug list and feature list on the project's Trello. The most commonly requested of these was a tutorial, to explain the controls and the basic aim of the game. Each user had to have the basic controls explained by myself (there was no readme, or online help) and the basic aim of the game, as it seems that the game is sufficiently different from most of the puzzle games available on steam as to confuse many new players. Without further ado, this leads on to the next item on this blog post... Creating a tutorial level for fun and profit! To be effective and useful, the tutorial level in my game had to have the following qualities: Be very easy to complete Allow for multiple different choices of input method (e.g. keyboard, gamepad) Have obvious points where gameplay could pause and pop-up hints can occur Still be possible to fail, to try out failure and see what happens Not be easy to break the tutorial flow Be possible to complete the tutorial in under a couple of minutes I decided to settle on a simple level, with the fewest possible number of usable junctions that can be placed whilst still allowing a crate to bounce  between them in a loop (two), and the fewest number of machines (one). The level would work by popping up a dialog box indicating how machines worked, and how to move the camera, then emitting one crate from the machine, and after it had emitted the crate, popping up another dialog box indicating how to rotate crates. Once this dialog box had popped up the ability to rotate junctions became available, until this point the player can't rotate the junctions to help prevent breakage of the 'scripted' events. As soon as the player has rotated the correct junction to the correct angle, the next scripted event will trigger, popping up a dialog box to confirm that this was the correct action. There is a short delay of a couple of seconds before the final dialog pops up to explain how crates wait for the grab claw, and then the level ends. There were two verisons of this tutorial, which only varied based on the text content of the speech bubbles; one for keyboard/mouse usage and one for the gamepad, with different summaries of the buttons to use. If played efficiently, this takes about one and a half minutes. As far as tutorials go, this is pretty much short and sweet. First attempt (AKA: How to scare off new players) The first iteration of the tutorial level had dialog boxes which just contained raw text: This did work, somewhat, but it had two flaws which required a second iteration be done, these flaws were: Each dialog box was a wall of text, off-putting to the new player and hard to digest Aligning the dialog text with the rounded speech bubble and having it work on any resolution of screen was proving to be near impossible Tutorial Trek - The Next Iteration The next version of the tutorial involved me spending a good couple of hours in GIMP polishing images. Instead of using raw walls of text that are hard to align with a speech bubble and still look good, i decided to draw the speech bubbles as PNG images: I ended up drawing six of these, two of each of the first two speech bubbles that were controller specific, and two of the last two generic bubbles. I drew each one with some particular features in mind to make them better than the wall-of-text equivalents: Each speech bubble was to make more effective use of the rounded bubble area Where a bubble mentioned controller or keyboard controls it would use the expected iconography to indicate what to press Names of controls, or important gameplay elements would be highlighted in red, e.g. crate, machine, left stick. Actual images of gameplay elements would appear in the bubbles to help the player relate (this way the player knows what a machine looks like as they saw one in a tutorial bubble, most real life factory machines are not square boxes with an exhaust sticking out of them!). These images would sometimes overlap the edge of the bubble by design, to draw attention to them. Most importantly: All wordage was to be shortened as much as possible! I then rolled them out into the game: And that, as the say, is all he wrote. Feedback and comments are as always very welcome!



Photo finish - automating previews of levels

Hi all, The main project for this weekend was to get powerups tied to an actual level in the game, which i have now got working as in the video below: With this out of the way I have decided to progress onto the next feature of the game which requires development. This is the level select page, which you are presented with if you have previously unlocked any levels in the game, letting you revisit and replay them to get better scores and collect extra powerups. Within the menu, each level should have a preview image, or thumbnail, showing its appearance to allow for visual memory of which level is which. This was previously implemented on the .NET version of Firework Factory, as can be seen below: In the newer unreal engine version this must be re-implemented. In the previous version, screenshots were taken by spawning the entire level, taking a screen capture of the level and storing that in a texture. I decided to do something similar in UE4, only to find that doing so would be overkill, as instantiating a level is quite expensive, and would have to be done dozens of times on startup just to capture screenshots to render targets, which could then be turned into materials, and displayed in the menu. Instead, i chose to make a 'photo studio', and get the levels 'photographed'. Yes, you heard right, a photo studio. The solution for the problem is to first create a separate map. Within this separate map create a couple of strong directional lights to ensure that there isn't too much shadow in the images. Secondly, create a floor made of a non-emissive completely black material with no reflectiveness. Essentially, this floor is impossibly black, much like it has been painted with vantablack. Next, I set up a blueprint to incrementally load each level in a loop, wait 1 second for the postprocessing effects to settle, and issue the console command: HighResSnapshot 3.0 The code for this can be seen in the blueprint below: This causes the game to save a screenshot of the current level to the folder Saved\Screenshots\Windows, where it can be loaded into GIMP and autocropped, giving me an image like the one below, which is the one for level 4: These can then be associated with the levels as a Texture2D by importing them into the content folder, so that a thumbnail can be displayed. As i add new levels, i just re-run the process to generate the snapshots, pick the new levels images, autocrop them and drop them into content, which takes all of 30 seconds. This means i can ensure that all the images are taken from the same angle, with the same lighting, the same postprocessing effects, and have an image of exactly the same dimensions. Next on the list: Use these thumbnails for an actual level select menu! Feedback as always is more than welcome, stay tuned for further updates!



Happy new year, and continued development!

It's been a very long time since any new blog posts have been posted about my current game project. I have decided that my new year's resolution for 2019 will be to get my game finished and out there within this year; After all, it's almost at the point now where an MVP or Vertical Slice exists. The claw has finally been fixed, and redone with a bit of kitbashing to make it nicer looking: Over the past year where there have been few blog posts, life has taken over and taken away a lot of the free time i had for gamedev. However over Christmas i have managed to get a bit more done again, and have moved onto where i left off, which was power-ups. The game will have several power-ups, which are gained by successfully completing levels with some finesse, and can then be used to make finishing some levels easier, or in some cases possible at all - the first level which introduces power-ups cannot be completed without them. Power-ups derive from a simple C++ class: UCLASS() class FWF_API ANativePowerup : public AActor { GENERATED_BODY() public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Powerup") bool AllowDropOnMachines; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Powerup") bool AllowDropOnCrates; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Powerup") bool AllowDropOnJunctions; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Powerup") bool AllowDropOnConveyors; // Sets default values for this actor's properties ANativePowerup(); // Called when the game starts or when spawned virtual void BeginPlay() override; // Called every frame virtual void Tick( float DeltaSeconds ) override; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Powerup") UStaticMeshComponent* Mesh; UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Powerup") UMaterial* GetSprite(); UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Powerup") UAudioComponent* OnUseAudio; UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Powerup") void Pickup(const FVector &PickupLocation); UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Powerup") void Use(const FVector &DropLocation); UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Powerup") void UseOnMachine(class ANativeMachine *machine); UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Powerup") void UseOnJunction(class ANativeJunction *junction); UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Powerup") void UseOnCrate(class ANativeCrate *crate); UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Powerup") void UseOnConveyor(class ANativeGridActor *conveyor); UFUNCTION(BlueprintCallable, BlueprintNativeEvent, BlueprintPure, Category = "Powerup") FString GetName(); }; Each of the boolean values at the top of the class indicate what a power-up may be dropped onto, each of which will have a different effect - some positive, and some negative. These booleans will allow the game to present a different (affirmative) cursor for elements that the power-up may be used on at all, to give the player some guidance and feedback. The first such power-up is the wrench: This power-up can be dropped on either a machine, or a crate. If it is dropped on a machine, it disables that machine for ten seconds, during which time it will not produce crates. Any crates it would have produced will be moved to the back of the production queue and produced later. This may cause other machines to produce crates in different orders. If you accidentally (or even on purpose) drop a wrench onto a crate, the crate will immediately explode. If you continually use wrenches on a machine, each successive use damages the machine slightly much like sending a crate back through the same machine, eventually causing it to explode. When the power-ups are dropped onto a supported object, the "UseOn*" methods, e.g. UseOnMachine() are called, where the object the power-up was dropped on is passed. There is much more to come, after a few power-ups have been implemented (next on my list is glue, which causes crates to stick to the conveyor, and oil, which makes crates go faster, but is highly flammable!) I will be moving on to saving of the game state to a file, and selection of levels from a list of levels that have already been completed, via the main menu. Once this is completed, I will be much closer to actually completing the vertical slice of the game which has been in progress for over a year now. Feedback is as always more than welcome!




Radioactive Goop, Flashing Lights, And Lots More!

Hi all, It's been quite some time since i last posted a journal entry. This hasn't been for lack of development of the game, more lack of free time where i'm not being a Dad, working my day job, or finding a few minutes to add to the game. Unfortunately for everyone who reads my journals, writing about my progress kind of came last, and for that i'm sorry. There have been many advancements to the game in the past three months, these are: Porting of most of the gameplay code to C++ Certain parts of the game were quite slow. I had narrowed this down through a small profiling session to loops within Blueprints. It seems that while Blueprint is good for some things, for loops especially it has some issues, as well as casts, which cannot be resolved at compile-time like many C++ casts can, and will quickly bog down performance.
To resolve this i rewrote large amounts of the code in C++. During this time, I encountered some annoying bugs, such as this one, which I reported to the Unreal Engine developers, and they are fixing as we speak: To rewrite my code in C++ i had to basically create a C++ base class for each blueprint and move variables first, then code a function at a time, manually rewriting it. In the process of doing this I learned a lot about Unreal Engine that i didn't know before, and this was a great learning exercise for me as well as helping improve the game's performance. Adding new crate types I have finally had time to add a new crate type to the game. The new crate type contains radioactive waste, and i have dubbed it the "goop crate". This crate appears later on in the game, after a major plot twist. The crate explodes with radioactive blobs of glowing green muck upon impact, which linger around and cause damage to any crates that pass across them: I created this particle effect using CPU particles with collisions, which when they collide with a horizontal surface (by checking the surface normal) they leave a decal on the surface, which is embedded within an Actor with a timer set to fade it out by adjusting values in its material instance. I am quite happy with the effect, and hope to find some time to add some more types of crate very soon! Adjusting the apperance of the machines I have decided that as i cannot get the previous artist for the game on board, and the look and feel of the game has changed anyway, i would like to go with a darker, grittier and less comedic, less cartoony feel for the game. The first part of this is to replace the comedy machines that produce the crates with something slightly more realistic. To aid this i have placed grilles on the sides of the machines and created a more realistic lamp which sits atop the machine. When the machine is due to produce a crate, a siren sounds and the lamp flashes. The flashing is realistic, working with a spotlight pointed at a mirrored surface, and a rotating lamp body which has a great effect. The model for the lamp cost me a cool $15 on turbosquid (let's be honest here, i am a programmer and i cant model something like this to save my life). Below is an example of the new machines in the game, and a development test in the editor:
As always comments are more than welcome! (it's encouraging to know that people read and sometimes enjoy what i write here). Let me know your thoughts, minor flames, or whatever comes to mind. Bye for now and stay tuned for future developments!




The claw is gonna get ya! (if the explosions don't!)

Hi all, Another day, another feature! The last couple of days have kept me busy creating a "physics powered" grab arm for picking up the crates. When the player gets the crates to the exit, the claw comes to get it. This is as creepy looking as it sounds. I decided to build the claw from primitive static mesh types, and bind the meshes together with physics constraints so that they acted in a hinged way, using forces and impulses to manipulate the arms. The reasoning behind this is so that when an object is within the claws, the physics library (in UE4's case, PhysX) can automatically clamp the four arms onto the box, or whatever else is there, and lift it. Once the item is lifted it can let go at any point and let it drop (which it will do if you give it the wrong crate). The other approach to this would involve a skeletal mesh, rigging, and inverse kinematics. That set of options is a non-starter for me because I am extremely lousy at Blender, not even able to create something with simple shapes, never mind rig or animate a model, and secondly, in my opinion, inverse kinematics in unreal engine 4 is a bit awkward to implement and last i tried it, a bit unstable causing random crashes. It took me a couple of hours to create a model i was happy with, using static meshes and some material work, and then another hour or so to fine tune the physics of the hinges on the arms, giving me a rather disturbing looking grab claw:

The claw can be controlled by two simple physics radial forces, one to draw the arms together into the centre, restricted by a maximum angle, and one to push the arms wide apart ready to pick something up (this is required so that they don't clip through the thing theyre trying to grab, and cause them to go completely nuts). These actions are shown in the video below:

Finally, the proof is in the seeing, here is the claw in action, with some really cool new explosion effects!

Comments and feedback as always are more than welcome!




"It's like the difference between night and day!" - Polishing the lighting

Hi everyone! It has been a long time (nearly a year) since i last worked on this game. My usual development routine involves having multiple games in progress at any one time. Once i start feeling burn-out coming on, or boredom setting in with one project i flip to the other, until one or the other is complete, always having more than one ready to be developed. This is the way it has been for me for over a decade, and it works very well for me. To this end when restarting working on this project i took a long hard look at what I could and couldn't quickly improve in the codebase. The graphics of the game were severely lacking, with no real lighting, no shadow mapping, no physically-based rendering, none of the textures had normal maps, etc. To add these features myself and get them looking good would take quite some time. Once they were added, i would need to implement a toolset to manipulate them correctly, and then test it all. This would also take a long time. My other project, which some of you may have been following, was written in UE4, and this gave me the features mentioned above out of the box. I decided therefore to take my existing C++ code, and adapt it to Unreal Engine 4, using UE4 to do the rendering and sound (this also gets rid of the licensing requirements of using fmod for sound and music, as these features plus 3D audio are built into UE4). It took surprisingly little time to get something looking pretty good out of UE4 using my existing assets, scaled up using GIMP's Sinc (Lanczos 3) scaling which prevents blockiness you usually get when scaling up an image. In the end, i plan to re-create these assets myself using edge detection to turn them into line art, then scaling the line art to suit. Currently, my old 64x64 textures have been scaled successfully to 512x512. By being very creative, and spending the better part of 6 hours tweaking light levels, placing spot and point lights, emissive materials etc, i came up with something that pleases my eyes and looks very impressive, especially compared to the old game: [table]
[tr][td]New Graphics[/td][td]Old Graphics[/td][/tr]
[/table] The graphics in the new version are a bit of a hack. To keep performance good when lots of particle effects will be going off, i have intended to keep FPS high at this point, and consider carefully everything i do. Therefore, the lighting must be carefully planned out. A lot of the lighting must be dynamic (movable lights) rather than static, baked lighting, as most of the items inside the room can move, including the 'play table' itself. To this end i decided that even though the game's room looks like it is indoors on a sunny day, there is actually no real sky light and no real outside environment. Outside the room is a quad, which has an image of an outdoor scene textured onto it. The material used to texture this quad has a high emissive value (texel colour * 8.0) which makes it shine with brightness like a bright sunny day when viewed from inside a dark room. This in itself is not enough to cause light shafts to stream in through the open windows however and shadows to be cast on inside items, as the emissive materials in UE4 are a bit of a hack, which to cut a long story short, technically don't really emit light (unless you're using light propogation volumes, which are a performance hit, and still experimental even in 4.10) - it is just a post-processing effect or two. So, to emit light, i have added a single spotlight slightly above, in front of, and to the left of the textured quad, still outside the window. The intensity of this light has been ramped up to 100,000 units, which causes a really bright light to be shone in through the window with much the same intensity as the sun on a bright summer day. For all intents and purposes, the effect is the same as being inside a room with a bright day outside. To complete the effect, as all factories and offices seem to have them, a point light has been placed just below the ceiling of the room, casting a less powerful set of shadows almost straight down. This is why when you look at the image the machines etc seem to have two shadows, one darker than the other. The complete layout of my room (as i can't just screenshot the editor, there is no "light outside" to be cast on it to show you) is sketched below: [sharedmedia=gallery:images:7292] I am still undecided wether or not the high bloom effect actually contributes to the scene or detracts from it, comments on this as always or anything else are welcome :)




What came first, the chicken or the egg: Implementing the loading screen

Another week, another feature!

This week heralds the addition of a loading screen. Partly due to a thread here on gamedev.net i decided that perhaps now was the time to add one, as shown below.

This actually turned out to be quite a challenge, due to the way i had designed my game.

At the point where the assets are loaded, the game loop is not yet running, and nearly none of the subsystems are initialised. This makes it harder than it otherwise would be to display and represent a loading screen, and leaves me grappling with a slightly alien environment without all my event driven conveniences.

I decided to approach this as follows:

Firstly, I had to adjust my sprite cache, to allow pre-caching specific named items at startup without enumerating the entire directory (which contains hundreds of files) and support for streaming objects on request:
/** * The SpriteCache class is a container object which loads and stores the Sprite2D * objects, which can be referenced by a string key. SpriteCache is accessed via the * read only [] operator, e.g. sprites["name"]. */class SpriteCache{private: FireworkFactory* creator; std::unordered_map, std::hash> sprites; Sprite2D* Get(ResId id);public: SpriteCache(); SpriteCache(const SpriteCache &copy); SpriteCache(FireworkFactory* creator, const std::wstring &directory); SpriteCache(FireworkFactory* creator, const std::wstring &directory, std::vector preload); void CacheDirectory(const std::wstring &directory); void Stream(const std::wstring &directory, const std::wstring &file); ~SpriteCache(); Sprite2D* operator[] (ResId id); void ReleaseAll();};

This can then be called when starting up the game to load a select small number of 2D sprites for the loading screen only. The loading screen is made up of several pieces, a bottom part of the bomb, the top part of the bomb (there are various versions of this showing different amounts of fuse remaining), the text saying "Loading..." and the spark, which is alpha blended into the scene. When we initialise the sprite cache, we load only the first "top portion" of the bomb with a complete fuse, and as further sprites are needed they are streamed on request:
sprites = SpriteCache( this, L"Sprites", { L"bomb-bottom.png", L"bomb-spark.png", L"bomb-top-1.png", L"bomb-top-overlay.png", L"loading.png" } );

I then created a class called LoadingScreen (more on this later), and i wrapped creation and destruction of the LoadingScreen object around my resource loading calls:
loader = new LoadingScreen(this, Util::ReadDirectory(L"Textures/*.dds", true).size() // Number of textures to load + Util::ReadDirectory(L"Sprites/*.png", true).size() // Number of sprites to load + Util::ReadDirectory(L"sfx/*.wav", true).size() // Number of sound effects to load ); /* Load assets here... */ delete loader; loader = nullptr;

The second parameter to LoadingScreen is simply a figure used to calculate how many steps should build the progress meter. For this, we do a total count of all sound effects, sprites, and textures in the game by enumerating the directories, and using only the size of the returned vector in-place.

The LoadingScreen class looks like this:
/* Represets the loading screen of the game. * Note that when this is instantiated, the game loop is not yet active. * To draw and update the loading screen, you must call the Draw() or * Increment() method which renders the current frame to the render target. * The loading screen requires only DirectX and Direct2D to be initialised. * Deleting the object triggers the explosion effect. This is will block until * complete. */class LoadingScreen{private: /* Creator object */ FireworkFactory* creator; /* Sprites (pre-loaded by SpriteCache) */ Sprite2D* bomb_bottom; Sprite2D* bomb_spark; Sprite2D* top_overlay; Sprite2D* loadingtext; /* Streamed sprites (loaded on request by SpriteCache) */ std::vector bomb_top; /* Sprite positions */ D2D1_RECT_F bomb_position; D2D1_RECT_F text_position; D2D1_POINT_2F spark_position; /* Number of completed steps */ int done; /* Total number of steps */ int steps; /* Last "top of bomb" sprite. When this changes, * we request a new sprite be streamed from disk. */ int last_top; /* Waypoint coordinates for positions of the spark along the fuse. * There are actually 235 of these, each contains an X and Y * coordinate making 470 values. */ static const double waypoints[470];public: /* Create a loading screen which expects 'steps' increments */ LoadingScreen(FireworkFactory* creator, int steps); /* dtor automatically plays the explosion animation */ ~LoadingScreen(); /* Draw current frame of loading screen at done/steps*100 percent */ void Draw(); /* Add completed steps to the animation */ void Increment(int step);};

As you can see, there is a Draw() method, and an Increment() method. The Draw() method is called directly by the constructor once everything is set up, and by the Increment() method. Different subsystems call the Increment() method as they load assets, increasing the number of steps completed, and redrawing the screen with the new progress:
sprites[crc32] = std::make_shared(new Sprite2D(creator->GetDX()->D2D->GetRenderTarget(), *f)); if (creator->GetLoader()) creator->GetLoader()->Increment(+1);

An important feature of the loading screen is that when its destructor is called, it will play the 'explosion' animation, which blocks for 100 frames while it updates. This then leaves the game in a state ready for the backbuffer to be cleared and the game proper to be launched.

You might also be asking yourselves "so if no subsystems are properly initialised when the loading screen is being displayed, where do the sounds come from?" - The answer to this is simple. Because we cannot guarantee that the sound system is initialised, or that any sound effect assets are loaded, the simple sound effect for the fuse is embedded into the executable as a win32 custom resource type. We use the WinMM PlaySound() API call to play the embedded wav file:

Of course, by the time the explosion is ready to be displayed, we can be sure the sound system and all the sound effects are ready for use, so we stop the PlaySound call, and use FMOD to play the explosion sound:
/* Stop the fuse sound */ PlaySound(NULL, NULL, SND_FILENAME); creator->GetSFX()->PlayEffect(SFX_LOADING_BOMB);

That about sums up the trickery and deception that is my loading screen. As always, comments are welcome below :)




Three, two, one, you're out! Adding the countdown timer, and other bits

Over the past month I have busied myself adding lots of tiny bits to the game, some of which are obvious to players and others not.

I have added a new menu design, with sound effects and animations;


I have also added a new logo for the game on the menu screen.


I have also sped up and increased the pitch of the boss's speech so now he sounds more like an unintelligable voice on the other end of a cartoon telephone conversation - i think this sounds much nicer, and i have made the text in the speech bubble incrementally appear as the boss speaks. Every syllable of gibberish causes appearance of one new word until all are displayed, or the mouse is clicked to cancel it.

More importantly, I have also added a clock to the game. The original 2D version had this clock, but it never was finished, when it reached zero, it would do nothing.

As you can see the clock starts with its 'minute' hand at the 3PM position, and the 'second' hand makes one complete revolution per real-time second. Each revolution of the second hand advances the 'minute' hand to the position of "360 / time limit * elapsed seconds" degrees around the clock face. The clock face is drawn rather simply: clocksprite->Draw(position); float radians = minuteshand * (M_PI / 180.0f); rt->DrawLine(centre, D2D1::Point2F(centre.x + (cos(radians) * handlength), centre.y + (sin(radians) * handlength)), minutes_brush, 8.0f * scale.x); if (running) { radians = (secondshand - 90.0f) * (M_PI / 180.0f); rt->DrawLine(centre, D2D1::Point2F(centre.x + (cos(radians) * handlength), centre.y + (sin(radians) * handlength)), seconds_brush, 3.0f * scale.x); } clockglass->Draw(position); if (HurryUp && running && !creator->IsPaused()) title->Draw("HURRY UP!", titlepos, messageopacity);
When writing this code i did consider using matricies to translate the positions of the lines used for the hands, but i decided that in this case, good old-school sine and cosine seemed more readable to me, and they work well.

When at least 70% of the time allowed for the level is taken up, the clock starts to shake (as if under pressure) and a message appears on the screen stating to 'HURRY UP!'. If the player still hasn't finished the level when over 90% of the time is taken up, the clock shakes more violently still, and once all time is taken up, all crates active in the level explode, which can and usually leads to level failure. Level* lev = creator->GetLevel(); D2D1_RECT_F rumble = position; float used = Ticks / lev->TimeLimitSeconds; if (running && !creator->IsPaused() && lev && used > 0.7f) { float offset_x, offset_y; if (used > 0.9f) { offset_x = Util::Rand(-4.99f, 4.99f) * scale.x; offset_y = Util::Rand(-4.99f, 4.99f) * scale.y; } else { offset_x = Util::Rand(-2.99f, 2.99f) * scale.x; offset_y = Util::Rand(-2.99f, 2.99f) * scale.y; } rumble.top += offset_y; rumble.bottom += offset_y; rumble.left += offset_x; rumble.right += offset_x; clocksprite->Draw(rumble); } else clocksprite->Draw(position);
At each of the incremental changes at 70% of the allowed time limit and 90% of the allowed time limit, the pitch and speed of the game music increases, in a rather comical way. I got the inspiration from this from sonic the hedgehog, on the underwater levels when running out of oxygen. No matter how much i try, i will never forget the frustration of those levels and that tune always sticks in my head. float used = Ticks / lev->TimeLimitSeconds; if (used > 0.9f) { creator->GetSFX()->SetMusicPitch(1.8f); } else if (used > 0.7f) { creator->GetSFX()->SetMusicPitch(1.5f); HurryUp = true; }
In many levels the addition of this clock will add extra challenge to the game, and was a missing game mechanic i have been waiting until now to implement.

Next on my to-do list is power ups. I have several of these in mind each of which can be purchased with points acrued from successfully completing levels:
A glue gun, which makes a piece of conveyor sticky, pasting a box to it which won't move for a while
A grease gun, which has the opposite effect, accellerating any box to pass over it
A grab claw, like those seen in amusement arcades, which takes any selected box and deposits it somewhere else of your choosing
A spanner, which when thrown at a machine disables it for a while and stops it producing crates, changing the order of production

There is room for more (and i'm open to suggestions in the comments!) but these were the four that i planned to have level designs to exploit.

Comments as always are welcome!




Texture Caching, Concept art and more!

It's been a month or so since i last wrote a journal entry here, but this has not been due to lack of work on the game.

Rather the opposite in fact, i find myself spending so much time creating the game that i have very little time left in my life to write journal entries! Oh, what a first world problem it is.

Of many things i have busied myself with over the past month, one of them has been rewriting and optimising how resources are managed within the game.

I have settled on doing this in a particular way which i thought it worth sharing with the rest of the community.

Firstly, each resource has an ID key which is called a ResId, and is 32 bits long. This is a strongly typed value:BOOST_STRONG_TYPEDEF(UINT32, ResId);
This actually creates a class containing just the native type (UINT32) with various operators for assignment, copying and comparison. It ensures that I am forced to use "ResId" as my variable type all through my code and not get lazy and start using UINT32, which means that if i choose to change the size of ResId (for example to 64 bits) at a later date, this can be done relatively painlessly in one place.

ResId types are calculated at compile time by a pre-build step. The pre-build step is a perl script (attached at the bottom of this journal entry, if you are curious!), which enumerates a set of directories and builds a header file, which is full of definitions like this:/* Compile time hashes for files within the Textures directory. * Automatically generated by Util/makehashes.pl. DO NOT MODIFY * by hand! */#pragma once#define TEX_CONVEYOR (static_cast(0x4eec1561)) /* Textures/conveyor.png */#define TEX_CRATE_BREAKABLE (static_cast(0x64d3a7f5)) /* Textures/crate-breakable.png */#define TEX_CRATE_DYNAMITE (static_cast(0x57f6ebd3)) /* Textures/crate-dynamite.png */#define TEX_CRATE_MORTAR (static_cast(0xb1ddcc8a)) /* Textures/crate-mortar.png */
As you may have noticed, each of these is a simple CRC32 value of the constant name, e.g. 0x4eeC1561 is a CRC32 of "TEX_CONVEYOR". The script which generates these header files only updates them on disk in the event they need to change, to avoid needless rebuilds of the project dependencies.

Armed with this metadata which we built at compile time, we are now able to define a texture cache class:/** The TextureCache preloads all textures into SRVs and allows access to them via operator[]. * It may throw a std::runtime_exception when constructed with a directory name and DX11 object, * if it cannot load a texture. All textures are loaded from a virtual directory within the zip * file on PhysicsFS. */class TextureCache{private: /** All resources are stored in an unordered_map which uses a nerfed hash function. * Performing std::hash on ResId always just returns the same ResId, as ResId's are hashed * already at compile time. */ std::unordered_map, std::hash> textures; /** Used internally by operator[] */ ID3D11ShaderResourceView* Get(ResId id); /** Builds a descriptive string with an error text and error number from a windows stringtable * resource, and throws it as a string within a std::runtime_error exception object. */ void ReportError(HRESULT hr, UINT caption_id);public: /** Create empty but initialised object, used when assigning inplace */ TextureCache(); /** Copy constructor, usage of CComPtr above ensures that we don't lose our SRVs * when we copy, so this is mainly just to copy the unordered_map itself. */ TextureCache(const TextureCache &copy); /** Initialise texture cache by reading all textures from a given directory using WIC. * The directory is virtualised via PhysicsFS. The DX11 object contains the context and * device upon which the SRVs are to be associated. */ TextureCache(DX11* dx11, const std::wstring &directory); /** Release all CComPtrs by nulling them */ void ReleaseAll(); ~TextureCache(); /** Look up any given texture resource by ID, e.g: * ID3D11ShaderResourceView* srv = cache[TEX_CRATE_DYNAMITE]; */ ID3D11ShaderResourceView* operator[] (ResId id);};
You might have noticed something strange about the hash function i am using. I have written my own hash function for "hashing" ResIds, which effectively does nothing. This is because ResIds are hashed at compile time, so any further implicit hashing would be a time wasting exercise:namespace std{ /** This is a nerfed hashing function for resource caches where unordered_map is used. * To prevent the unordered_map doing anything with the Resource Id, we just return it * verbatim here. Otherwise, we can't gaurantee that the hasher for unsigned int won't do * anything to the resource id, wasting time. There's no use hashing a value at runtime * that's already been created as a hashed value at compile time. */ template struct hash { inline size_t operator()(const ResId &v) const { return v; } };};
We can then construct a texture cache simply and effectively on startup, without any needless heap allocation as follows:textures = TextureCache(dx11, L"Textures/*.png");
When called, this constructor enumerates the content of the Textures directory, finding all PNG files, and loading them with WIC. Each one it loads, it builds a CRC32 value of the constant name (which it determines from the filename) and stores it in the unordered_map keyed by its ResId:TextureCache::TextureCache(DX11* dx11, const std::wstring &directory){ HRESULT hr; const FileList tex = Util::ReadDirectory(directory, true); for (FileListIter f = tex.begin(); f != tex.end(); f++) { CComPtr LoadedTexture; size_t texturelen = 0; const char* texturedata = Util::ReadWholeFile(*f, texturelen, true); if (texturedata) { hr = DirectX::CreateWICTextureFromMemory(dx11->Device, dx11->Context, (const uint8_t*)texturedata, texturelen, nullptr, &LoadedTexture); if(FAILED(hr)) { ReportError(hr, IDS_ERROR_LOADING_TEXTURE); } else { std::string processed = Util::ProcessFileName(Util::GetFileName(*f), "TEX_"); ResId crc32 = static_cast(Util::CRC32(processed)); DebugOut()
You might also have noticed that there is no operator[] method used for assignment. This is on purpose, so that if i accidentally ever type "cache[VALUE] = someSRV;" this will be caught as a compile-time error. Such an action is not expected and should be forbidden at this point.

There are a few gotcha's with this implementation, the most important being hash collisions. It is possible, but unlikely, that I can get hash collisions by using CRC32 to hash the resource IDs. If this does become a problem, I will look to moving to CRC64 or FNV-1a instead. Time will tell if this will prove to be a problem at all.

A future enhancement would be runtime loading of new textures, and releasing of unused textures to stay within a memory budget. Right now, i have enough memory and small enough number of textures that this isn't required.

So, enough code. I am sure your first question when looking at this journal entry was "well, who is that lady in the picture at the top of the page?"

The lady in question is the secret agent character for the game. Half way through the game she replaces the boss at intervals, giving you advice and subtle warnings about your manager's antics. Having enough free time to do so, and wanting to try my hand at drawing once more, i decided to create the concept for this character and start shading it myself.[table][td='33'][/td][td='33'][/td][td='33'][/td][td='33'][/td][td='33'][/td][/table]

As you can see from the image, i am now about half way through this and all i can say is that creating art takes a lot longer than creating code especially if it doesn't come naturally like it doesn't to me. For me to create reasonable art, i have to spend many tedious hours within GIMP, gently massaging pixels to be where i want them. Time will tell if i am able to create some art passable enough for the game, and of course feedback from anyone more artistically inclinded about my creation is always more than welcome!

On with the show, and back to the grindstone. Please comment and leave feedback if you have any questions!

Keep an eye out for my new article, coming to this site soon: How to automate deployment of your game!




Level completion animation

Hi everyone!

Another week has passed, and more features have been added into my game. Today, I have found some time to create the end of level animation.

I have drawn my inspiration heavily from casual mobile games such as angry birds, cut the rope and Bag-It, which all have a sequence of stars at the end of the level which fill depending upon the amount completed.

I also managed to find some very nice sound effects on opengameart.org which have several different variations, each one becoming more excited and louder the more they progress through the sequence. I have used these to ensure that the better you do the more congratulatory the music seems.

Of course, if you don't get the required percentage at all, you get the classic 'game over' music, as in the previous 2D version of the game.

The general concept is to remove the need for the user to interpret percentages - in a short glance of a nice looking animation they have determined if they passed or failed the level and if their next step should be to try again (or perhaps throw their controller at the monitor in frustration maybe?) or advance straight to the next level with a big smile on their face, punching the air in a "YES!" pose.

I have also completed various small bits of polish such as the "picking list" on the bottom right of the screen, which indicates which crates are coming next and what order is correct. As the crates move along this list, the sprite shakes as if under stress and rumbling sounds are played.

Dropping crates off the edges of the playing field are now accompanied by a cartoonish "whee-kersplat" sound effect.

Oddly enough, just these small pieces of polish is making the game seem more like a game as time goes along, and showing non-technical strangers videos of the game in progress now results in "oooh's" and "aah's" as opposed to "what is that? looks like minecraft...".

On a related note i have decided to call the main character "Eric Boom", or "Mr Boom" for short as a result of this thread...

Stay tuned for further updates from the firework factory!




"Gamedev Lego": Putting all the parts together into a playable game using an event system

Hi everyone!

So, again, it's been a couple of weeks since my last entry. Moving on from where we were, to where we are now, I am now in a position to start putting together various subsystems and linking them together to form a flowing gameplay experience.

In previous journal entries I have discussed writing a spritefont implementation, and writing various bits and bobs for animation etc.

Today I will cover my event system which I have used to link together the component parts such as the menu, boss (tutorial character and all-round plot device) and the gameplay portion proper. The event system is at its simplest level a base class from which other classes may be derived, named "Action":

class Action{private: // True if the action is currently repeating, e.g. a held key bool keydown; // The name of the action, e.g. "Camera/Up" std::string name;protected: // Creator class FireworkFactoryWindow* creator;public: // Instantiate a new action. Creating an action inserts it into a map // of named actions where it can be located and bound to key presses. Action(FireworkFactoryWindow* parent, const std::string &actionname); // Destructor automatically removes the action from the named actions map ~Action(); // Called when repeated execution of the action is possible, e.g. key held down virtual void ExecuteAction() = 0; // Returns the name of the event std::string GetName(); // Returns true if the key bound to the action is currently held down bool IsPressed(); // Called once when the button bound to the action is first depressed virtual void Pressed(); // Called once when the button bound to the action is finally released virtual void Released();};As Action objects are instantiated, they are inserted into a global std::multimap of Actions, each of which has a sensible name which is used to identify it. Each action may be triggered manually (by locating its object and calling its methods) or by associating it with an input, e.g. a keyboard button or a mouse button. Note that although the methods are called "Pressed()", "Released()", and "ExecuteAction()" they do not neccessarily have to map to a physical input, and derived forms may implement derivation-specific methods which may be useful. For example all Actions who's names start with "Audio/" could contain for example a "SoundEffectFinished()" method...

The general idea of action objects is to disassociate behaviours with the triggers for those behaviours. Many games will directly plug the behaviour of the space bar to the fire action, for example. This is all well and good, until you later come along and want to run a demo sequence, or multiplayer, or perhaps just want to remap keys.

In Firework Factory, a seperate input buffer (fed from the windows message loop thread) populates a buffer of key presses, which are then used to dispatch events to Actions:

* This function handles input coming in from windows message loop, but buffered into our own * buffer to deal with at a time when we want to deal with it. */void FireworkFactoryWindow::Input(double frameTime){ /* We process a maximum of ten events per frame, so that all players have a constant known * input rate for fairness. Else, faster machines respond quicker. */ const UINT32 MaxEventsPerUpdate = 10; UINT32 EventsRead = 0; BufferedKey bk(0, VK_NONAME, KE_NOTHING); Action* k = nullptr; /* Iterate the buffer removing all keypresses that exist and processing them */ do { bk = keybuf.GetNext(); /* Dispatch each different event type to the right method */ switch (bk.GetEvent()) { /* Keyboard key pressed */ case KE_KEYDOWN: { ActionListKeys eventlist = keymap->Get(bk.GetKeycode()); for (auto k = eventlist.first; k != eventlist.second; ++k) { /* Note: We call Action() here too on key press, because if the * key is both pressed and released within the same set of buffered * events, Action() would not be called AT ALL otherwise. This would be * technically wrong. */ k->second->Pressed(); k->second->ExecuteAction(); } } break; /* Keyboard key released */ case KE_KEYUP: { ActionListKeys eventlist = keymap->Get(bk.GetKeycode()); for (auto k = eventlist.first; k != eventlist.second; ++k) k->second->Released(); } break; } EventsRead++; } while (bk.GetEvent() != KE_NOTHING && EventsRead DoActions();}As you can see, all input events are rate limited and tied to a fixed 16ms (70fps) clock, and handled at a set position in the code. This ensures that the input system does not run at different speeds on different PCs. The GameWindow::Input() method used here is called in a similar way to GameWindow::Update() but is seperated purely for readability. Any key may be mapped to multiple actions, and any action name may be claimed by multiple objects. At any time the key mappings may be changed by calling the InputMap class's SetNew() method, or by simply instantiating the InputMap class:

keymap->SetNew(L"Keymaps/Game.txt");There is also a method to insert and remove individual key mapping entries, which is not used any more from the public interface. These keymap text files are stored within the game's main archive file, and are a simple tab seperated list of key name and action name, e.g.

VK_A Camera/LeftTo map the names (e.g. VK_A) to an actual platform specific keycode, I programattically generated a huge header file, which contains the name and platform specific keycode for each possible key, plus a description for the UI:

#include typedef std::pair KeyDetail;typedef std::map KeyNames;KeyNames KeyNameList = KeyNames(boost::assign::map_list_of ("VK_ADD", std::make_pair(VK_ADD, "Numpad +")) ("VK_ATTN", std::make_pair(VK_ATTN, "Attn")) ("VK_BACK", std::make_pair(VK_BACK, "Backspace")) ("VK_CANCEL", std::make_pair(VK_CANCEL, "Break")) ("VK_CLEAR", std::make_pair(VK_CLEAR, "Clear"))[...] ("VK_VOLUME_DOWN", std::make_pair(VK_VOLUME_DOWN, "Volume Down")) ("VK_VOLUME_MUTE", std::make_pair(VK_VOLUME_MUTE, "Volume Mute")) ("VK_VOLUME_UP", std::make_pair(VK_VOLUME_UP, "Volume Up")) ("VK_XBUTTON1", std::make_pair(VK_XBUTTON1, "X Button 1")) ("VK_XBUTTON2", std::make_pair(VK_XBUTTON2, "X Button 2")));We now have a facility where any particular system may be called independently of its association with what the user is doing. We use this for good effect while the menu is on screen. Although the game is paused, we can continually call the Camera/Left event to rotate the playing field below the translucent menu (see the video below for this effect in the flesh):

void MainMenu::Update(double frameTime){ Menu::Update(frameTime); ActionList al = creator->GetInputMap()->Get("Camera/Left"); for (auto it = al.first; it != al.second; ++it) { if (auto cla = dynamic_cast(it->second)) cla->ExecuteAction(); }}The dynamic_cast isn't strictly required in this case, as all instances of Action must implement the ExecuteAction() method. This would be used however in a templated "CallAction" method, to call an action class given it's type and action name. Similarly, we can do the same to trigger a "quit the game" action from anywhere. We could attach a dialog box to this, if we wanted, or perform any other cleanup behaviour such as an autosave, and it would be triggered from anywhere that calls the event:

case MO_QUIT:{ ActionList al = creator->GetInputMap()->Get("Gameplay/Quit"); for (auto it = al.first; it != al.second; ++it) it->second->Pressed();}As promised, here is a video demonstrating the game so far, with all of this humming away quitely in the background. As you can see, it is now appearing much more like a game, and less like a bunch of loosely related parts, our lego kit is coming together to form the whole:

As always, feedback, votes and comments are welcome!




Making my own SpriteFont implementation

Hi everyone.

So it's been a little while since my last journal entry. Various things about the internals of Firework Factory were annoying me so in true programmer fashion i had to spend some time ripping them out and rewriting them. Refactor, refactor, refactor!

Over the past couple of weeks i have removed every last trace of D3DX from my code, and fully got rid of any dependency upon the July 2010 DirectX SDK, making sure the entire game will build just using the Windows Platform SDK.

This has been a huge success, and now I hopefully have a cleaner, and more future proof codebase. I do not want to end up in the same rut as before, with a game written in a dead technology.

As part of this I had attempted to integrate DirectXTK into the game so that i could use its texture loader, and sprite font capability. This did not all go according to plan. I spent several days trying to identify why whenever i drew fonts with it's implementation of SpriteFont, it would mess up my rasteriser state, drawing just elongated triangles all over the screen. After temporarily moving most of the scene initialisation into per-frame initialisation to troubleshoot i was still having issues, and decided that as a learning experience and to be in full control of the source code, i would write my own SpriteFont implementation on top of my existing Sprite2D implementation, instead of using DirectXTK SpriteFont on top of Texture2D.

I decided that there were some features (font rotation, font scaling etc) i did not need as i could simply do these by drawing my sprites onto a texture and rotating that if i found i needed these facilities later, and that these did not need to be part of the spritefont class itself.

This did not take as long as I had expected, and my own cut-down implementation of SpriteFont was a lot simpler and easier to read than the one that comes as part of DirectXTK.

My Sprite2D implementation is a simple 2D sprite renderer, which uses WIC to load the sprite from a PNG file stored in a zip:class Sprite2D{private: // Direct2D Bitmap ID2D1Bitmap* graphic; int* rawpixels; // Direct2D render target ID2D1RenderTarget* rendertarget; UINT width; UINT height;public: // Create a new Sprite2D from a file on disk using WIC to load the image. // Throws std::exception on failure to load the file. Sprite2D(ID2D1RenderTarget *pRenderTarget, const std::wstring &filename); // Draw the Sprite2D. DX11::Begin2D() must be called before this can be used. void Draw(const D2D1_RECT_F &destination, float opacity, const D2D1_RECT_F &source); // Free bitmap resource ~Sprite2D(); UINT GetWidth(); UINT GetHeight(); UINT GetPixel(UINT x, UINT y);};
The astute amongst you may have noticed the GetPixel() method immediately. Please do not grab your torches and pitchforks and descend upon me just yet - this is not as inefficient in terms of CPU usage as you might first think. Currently only the SpriteFont system uses this (you will see why below) and it references a copy of the actual ID2DBitmap which is copied as raw pixels into an int array.

For the uninitiated, at its basic level a SpriteFont as seen by XNA is a bitmap sprite sheet, with a bunch of metadata to identify where each rectangle is that identifies any one particular glyph. This metadata is built by the content pipeline at compile time.

In my version of SpriteFont i decided to cut out this process of pre-compiling metadata. Identifying the glyphs in the bitmap is quite fast enough to be done when loading the assets, as no player notices a couple of extra milliseconds here. In short, i am able to keep my spritefonts as just a simple sprite sheet and build the rest at runtime.

My sprite sheets for fonts look like this:


This represents each of the ASCII characters from a space (ASCII 32) to the "}" character (ASCII 125). These are loaded using the Sprite2D class above, and then passed to a Font class:// Maximum ASCII value of highest glyph in a sprite sheet, minus one#define MAX_GLYPH_ASCII 126// Representation of a sprite font.// Sprite fonts are read from a sprite sheet generated by an external application// e.g. iron Star Media Fancy Bitmap Font Generator. Usually in XNA these are parsed// as part of the content pipeline into an XML schema, some metadata and the underlying// bitmap. Parsing the bitmap ourselves isn't /that/ expensive these days and perfectly// acceptable to do at initialisation time.class Font{private: // The sprite sheet containing all the glyphs from space to '}' Sprite2D* spritesheet; // The rectangular location in the sprite sheet for each glyph D2D1_RECT_F glyphs[MAX_GLYPH_ASCII]; // Identifies if a given pixel is opaque magenta bool IsMarkerColour(UINT pixel); // The height of a line of text calculated via max(all character heights) UINT lineheight;public: // Constructor accepts a sprite object Font(Sprite2D* sprite); // Draw a string to the screen at given position and opacity void Draw(const std::string &text, D2D1_POINT_2F position, float opacity); // Measure the X and Y size of any given string D2D1_POINT_2F Measure(const std::string &text); // NOTE: Destructor does NOT delete sprite ~Font();};
The Font class constructor then examines the bitmap of the sprite, looking for the edges of the transparent areas surrounded by opaque magenta:// Fully opaque magenta in ARGB formatconst UINT32 MAGIC_MAGENTA = 0xffff00ff;Font::Font(Sprite2D* sprite) : spritesheet(sprite), lineheight(0){ // Start at ASCII value for space char index = ' '; // Clear all glyph entries so they default to a size of 0,0 ZeroMemory(&glyphs, sizeof(D2D1_POINT_2F) * MAX_GLYPH_ASCII); // Heavily based on MakeSpriteFont.cs from DirectXTK... for (UINT y = 0; y GetHeight(); ++y) { for (UINT x = 0; x GetWidth(); ++x) { // Look for the top left corner of a character (a pixel that is not the marker colour, but was the marker colour immediately to the left and above it) if (!IsMarkerColour(spritesheet->GetPixel(x, y)) && IsMarkerColour(spritesheet->GetPixel(x - 1, y)) && IsMarkerColour(spritesheet->GetPixel(x, y - 1))) { // Measure the size of this character, first across horizontally then down, pixel by pixel int w = 1, h = 1; while ((x + w GetWidth() && !IsMarkerColour(spritesheet->GetPixel(x + w, y)))) { w++; } while ((y + h GetHeight()) && !IsMarkerColour(spritesheet->GetPixel(x, y + h))) { h++; } // Bounds check if (index == MAX_GLYPH_ASCII) throw std::invalid_argument("Too many glyphs found in sprite"); // Store glyph to the array glyphs[index++] = D2D1::RectF(x + 1, y + 1, x + w - 1, y + h - 1); if (h > lineheight) lineheight = h - 1; } } }}bool Font::IsMarkerColour(UINT pixel){ // Magenta is the marker colour between glyphs. // There is normally a 6-pixel padding of marker colour between each glyph. return (pixel == MAGIC_MAGENTA);}
I based this bit of code heavily on MakespriteFont's BitmapImporter.cs, a c# program for building sprite font metadata which comes with DirecXTK.

As you can see if this was done often during the game loop it would be computationally expensive and very much a no-no, but as it stands, done at startup, this is acceptable as the time taken isn't even noticable.

Once this initialisation has run we have an array of rectangular areas, each of which represents the ASCII character glyph for a given ASCII code. We simply iterate a string's characters to draw it, displaying each in turn and iterating the X and Y coordinates to draw the glyphs at appropriately:void Font::Draw(const std::string &text, D2D1_POINT_2F position, float opacity){ // Iterate all characters in the string. Note that characters we have no glyph // for are rendered as a 0 by 0 pixel bitmap so do not appear in the output. for (std::string::const_iterator ch = text.begin(); ch != text.end(); ++ch) { // Skip carriage return if (*ch == '\r') continue; // Newline advances the position down one line using the lineheight else if (*ch == '\n') { position.y += lineheight; continue; } // Calculate width and height of current glyph const D2D1_RECT_F& glyph = glyphs[*ch]; UINT gwidth = glyph.right - glyph.left; UINT gheight = glyph.bottom - glyph.top; // Draw the section of the sprite sheet that refers to the glyph spritesheet->Draw(D2D1::RectF(position.x, position.y, position.x + gwidth, position.y + gheight), opacity, glyph); position.x += gwidth; }}
For measuring the potential dimensions of any particular string in a given font, we can use the same style of function, just with the Draw calls taken out:D2D1_POINT_2F Font::Measure(const std::string &text){ D2D1_POINT_2F ret = D2D1::Point2F(); ret.y = lineheight; // The code here is practically identical to Font::Draw, except instead of drawing // we just record the current X and Y sizes of what we would have rendered. for (std::string::const_iterator ch = text.begin(); ch != text.end(); ++ch) { if (*ch == '\r') continue; else if (*ch == '\n') { ret.y += lineheight; continue; } const D2D1_RECT_F& glyph = glyphs[*ch]; ret.x += (glyph.right - glyph.left); } return ret;}
Now we have a complete font rendering system, we can use it to build a simple menu out of sprites and fonts:


The code to do this then becomes very simple:titlefont->Draw("this is some text", D2D1::Point2F(x_pos, y_pos), 1.0f);
As for potential improvements to this code, i see no reason why i couldn't pre-render the entire string onto a texture or other 2D sprite, then blend that texture or other 2D sprite into the screen when needed. However, for now, this is performant enough for what i need to do, as you can see in the video below of it running on top of the actual game:

Comments and other feedback are always welcome!




Adding a skybox, collision detection and software cursor

Hi everyone!

I've found some time today to make further progress on Firework Factory, adding three things as mentioned in the title:
Added AABB collision detection of boxes and particles, so that the game mechanics now function entirely correctly for crates
Added a skybox, to make the game world seem less dull
Added a software cursor

Firstly, the collision detection of boxes was added. This was quite a simple change to make to the source, and luckily AABB checks are not CPU intensive, and even when i have to check against thousands of active particles, it does not seem to be too much of a problem Admittedly, you don't see many games where particles have to be collision checked with anything more than a plane (raindrops falling on the floor, maybe?) so this is a break from the norm compared to a lot of games that use particles purely as passive effects.

The skybox, well, I guess this is the technical term but there is nothing related to the sky about it... as you are inside the factory. I added an in-joke here which you will probably get if you are in England. On the right hand wall is a HSE poster, a mandatory statement of health and safety compliance for UK businesses. I've had to doctor out the royal crest in the top left (I don't want any legal trouble for duplicating the crest!) but it just serves as a joke, having a safety compliance notice on the wall of what is supposed to be a very unsafe place by design.

The game grid still 'floats' off the surface of the factory. I intend for it to always be raised off the floor like a table, and at some point later i may add legs at the bottom or chains hanging it from the roof. The crazy design is of course in no way related to any real life sensible factory.

The final change this time around is a software cursor. There are two reasons for adding this - firstly, the 2D version of the game had it, and it looked quite nice, being alpha blended and translucent. Secondly, the functions required to load and render the sprite on the screen was something I didn't know how to do in Direct3D 11 until now. Now that i have implemented it, I can easily use this for displaying GUI and menu systems, and the game's HUD which indicates the next crate, etc. The addition of 2D sprites is done via a simple sprite class:/* The Sprite2D class is a wrapper around loading and drawing 2D sprites to a * Direct2D render target, loaded via WIC. */class Sprite2D{private: // Direct2D Bitmap ID2D1Bitmap* graphic; // Direct2D render target ID2D1RenderTarget* rendertarget;public: // Create a new Sprite2D from a file on disk using WIC to load the image. // Throws std::exception on failure to load the file. Sprite2D(ID2D1RenderTarget *pRenderTarget, PCWSTR uri); // Draw the Sprite2D. DX11::Begin2D() must be called before this can be used. void Draw(const D2D1_RECT_F &destination, float opacity, const D2D1_RECT_F &source); // Free bitmap resource ~Sprite2D();};
The render target drawn to is an independent texture, which is drawn to the screen with translucency over the top of the 3D scene, therefore any GUI elements, menus etc that i draw can always be gauranteed to be on top of the action.

Next on the list is exactly that: A simple menu. Coming soon to a YouTube video near you...

As always, comments are welcome and encouraged!




Firework Factory - Junctions, Crates and Exits all playing nicely together

Hi everyone,

Another day, another journal entry!

Today I have integrated a bunch of disparate parts of the game together, and we are finally reaching the point where all the unconnected parts start to join together to form a playable, complete whole.

The junctions, demonstrated in my second journal entry before Christmas, are now correctly tied into the simulation, as are the machines, demonstrated in my previous blog post, and the level exit, which takes crates away from the playing area. These are all tied together by the Animation class, which can interpolate any object over time, adding rotations, position transformations, and scaling on all three axes.

For now, I spawn new crates for testing purposes by pressing the space bar - this will eventually be read from the level definition. Crates are stored to a std::vector, which is updated every time through the game loop: for (CrateListIter crate = activecrates.begin(); crate != activecrates.end();) { Crate* c = *crate; if (c->Exploded || c->CorrectlyExited) { crate = activecrates.erase(crate); } else { (*crate)->OnUpdate(); ++crate; } }
Whenever a crate explodes (they don't actually do this yet) or correctly exits via the exit, it is removed from play. For now, falling off the edge is treated the same as exploding.

As you can see later in the video, there is no collision detection as of yet - this is possibly next on my to-do list, and along with it comes connecting the particle emitter to the collision, which brings with it effects and other related goodness

Stay tuned for further updates, and as always, comments are welcome!




Adding machines to the level

Hi all,

Today I have managed to add machines to the level layout. The machines are the producers of the crates in the level, as seen in the video of the 2D version with cute smiley faces on top and flashing lights for a nose.

The new version still has flashing lights for noses, and hopefully at some point i will get around to adding point lights as part of the effect. In the new 3D version i have decided to give the lights square edges so that they can rotate, the movement will hopefully draw some attention.

Technically, this is implemented by grouping together related models (e.g. the light and its machine) into a class called BoxCollection which holds a std::vector of Box objects ("box" being the internal name for a model in the game).

Comments as always are welcome




Firework Factory - Level Loading

Over the past few days i have been working on two things within the game as shown in the YouTube video:

The first thing i have been working on is the input system, which handles buffering and processing of input. After some discussion on the forums, i had come to the conclusion that the following things were needed:
The input system needed to seperate the incoming messages from the game loop, so they could be processed on the game's terms, not immediately
The input system needed to be able to rate limit the number of events per second, so that people with faster or slower PCs did not have an unfair advantage and that the game played the same everywhere.
The system needed to retain a buffer from which events could be read

For the most part this new input system does exactly what it set out to do - the unfortunate side effect of an input subsystem is that it isn't something you can show to people who have an interest in your game. People making games like ourselves will look at the code in the thread above, understand what is going off and understand that a lot of time and effort has gone into it, and it has been made better. Normal users however, game fans... Let's just say they would be quite unimpressed.

With this in mind i also set out to properly load the level files which should be automatically loaded and parsed from disk when the game loads.

The level files are simple text based files, which will eventually be stored within a "pak" style archive. Each of them has a set number of instructions as shown below:VerticalConveyors 3 7 10HorizontalConveyors 3 7 9Machine 3 0Machine 10 0CrateExit 7 11OutSequence 0 mortar 1OutSequence 1 mortar 5OutSequence 1 dynamite 1CorrectOrder mortar dynamite mortarIntroTextStartWelcome to the firework factory! I am your new boss, Mr Seafor. For your first task,simply move those firework crates off the production line. BE very careful not to break any...They are a little ... volatile!IntroTextEndEndTextStartWell, all looks in order here! Congratulations on a job well done, maybe I should give you apromotion to something a little more challenging!EndTextEndFirstCrateSeconds 4TimeLimitSecs 60Music 1Pass 10
The VerticalConveyors and HorizontalConveyors fields indicate at which X and Y columns and rows there will be a horizontal or vertical conveyor belt. The game automatically places junctions at the intersections where they meet.
The Machine lines indicate the X,Y 2D coordinates of a machine on the playing field, from which crates are emitted.
The OutSequence lines indicate which types of crates come out of which machines and when, and the CorrectOrder line indicates what order the crates are expected to reach the exit. The IntroText and EndText are quite self explainatory (shown at the start and end of the level, spoken by the 'boss' character). FirstCrateSeconds indicates how long the game waits at the start of the level before producing the first crate.

I load these with a simple text file parser, which places them into a quite straightforward object:class OutSequence{private: int machine; std::string cratetype; int nextcratesecs;public: OutSequence(int mach, const std::string &crate, int nextcrate); int GetMachine(); const std::string& GetCrateType(); int GetNextCrateSecs();};class Level{public: // Position of vertical conveyor belts in the level layout std::vector VerticalConveyors; // Position of horizontal conveyor belts in the level layout std::vector HorizontalConveyors; // Positions of machines on the end of conveyor belts std::vector Machines; // Crate exit point - there can only be one in the level D2D1_POINT_2U CrateExit; // Output sequence of crates from the machines std::vector Sequence; // The expected correct order of the machines through the exit std::vector CorrectOrder; // Intro text spoken by the boss before the level begins std::string IntroText; // End of level text spoken by the boss on successful completion std::string EndText; // How long the player gets before the first crate is produced int FirstCrateSeconds; // Time limit to complete the level int TimeLimitSeconds; // Music file to play as background music std::string Music; // Percentage completion needed to pass int PassPercent; // Parses an on-disk level file Level(const std::wstring &levelfile, const int levelnum);};
These are then placed into a std::map where the key is the level number and the value is the pointer to the Level object:LevelManager::LevelManager(){ const FileList levs = Util::ReadDirectory(Util::GetExePath() + L"\\Levels\\*.lvl"); for (FileListIter f = levs.begin(); f != levs.end(); f++) { std::wstring filename = Util::GetFileName(*f); int level = _wtoi(filename.replace(filename.find(L".lvl"), filename.length(), L"").c_str()); levels[level] = new Level(*f, level); }}
Once all the levels are loaded, the system simply draws the level according to this layout, and produces the crates as specified in the configuration. These levels are entirely data driven, and a new level can be created by simply dropping a new numbered file within a directory.

Some of you may be asking why i didn't just define a two-dimensional array for the level layout, as this would be what you would usually see for a game design of this type. There are a few answers to this:

Firstly, the levels are adapted from the level design of the first game, which also did not use an array of sprite types. Due to wanting to re-use the data and designs, I decided to keep the same layout.

Secondly, designing the level in this way means that there is less chance for an error in level design. It is not possible to place a junction where there is no conveyor, or place a conveyor that ends abruptly without exiting properly, or anything of that nature. The system smartly places the conveyors and junctions just based on the one position.

As i plan to eventually let users design their own levels and publish them online, this is an important factor, the simplier i can make the level editor, the better as I want this to be something any gamer can just pick up the game and do, not someone aspiring to make games who might already be a bit technically minded.

As you can also see from the YouTube video i have added the animation now for the crate exit. Unlike in the 2D version of the game, where the crates simply dissapeared on contact with the exit, in the 3D version of the game, the exit transports the crate away off-screen, accellerating quite rapidly, then returning. The idea is that any crates left waiting at the exit whilst the transport plate is "away" will queue up in a line, which should add a bit to the challenge and add an interesting gameplay mechanic.

Next on the list to code is dispatching of crates, and crate movement around the level.

As always, comments welcome!




Implementing the particle fountain effect

So, over the past week i have been busy implementing the first of many different particle effects for the game.

A video of the particle effect can be found here on my YouTube channel.

The whole of the game hinges around pretty (and rather deadly) particle effects, so this is an important part of the design. The first of these effects is a particle "fountain" much like a roman candle firework. The effect is implemented as a combination of a pixel and geometry shader, with instancing used to display many thousands of identical quads each containing a simple texture:

This texture is used to build up the effect, with each particle having a pseudo-random velocity. Over time each particle is pulled back to earth via a gravity effect, which causes the outwards momentum to drop by 75% and the upwards momentum to be replaced slowly by downwards momentum as shown in the code below.[code=nocode:0]void ParticleSystem::Update(){ for (int i = 0; i .pos.y += particles.yvelocity; particles.pos.x += particles.xvelocity; particles.pos.z += particles.zvelocity; particles.yvelocity -= particles.falloff; if (particles.zvelocity > particles.initialzvelocity / 6.0f) particles.zvelocity -= particles.falloff; if (particles.xvelocity > particles.initialxvelocity / 6.0f) particles.xvelocity -= particles.falloff; }}
In the game proper, each of these particles will be destructive to any crates they come into contact with so it is unlikely that i will be outputting so many particles during gameplay or this may make the game far too hard.

At present the system does not free particles which have been allocated, as this is for testing only - once i have finished this portion of the game the textures which are allocated will be freed back into a pool (with a maximum of 10,000 at a time) to be displayed when needed.

The particle effect seems to run quite well at over 100 frames per second, so long as fraps doesnt get loaded as fraps does not seem to like my laptop one bit.

Now that we have a basic firework particle effect, i will add the crate movement next and conveyor belts, which are also just as fundamental to the basic gameplay as the particle effect!

Stay tuned for further updates coming soon!




3D animation, ray picking, and junction handling

So, after a week of development here are the videos of the progress so far in the 3D version of Firework Factory!

A youtube version of this video can be found here.

As you can see there is now an animation system to allow for simple animation of blocks on the playing field. The example here is the simple junction box, which can be used to change the direction of travel for each of the firework crates.

As far as graphics goes, i just have to implement machines, crates, and the particle system and all basics will then be implemented.

The Animation system works by attaching an 'animation' derived class to the Box object, and then calling the DoUpdate() method of each animation object once per frame. Constructors of the Animation derived classes contain the basic instructions required to perform the animation, as shown below:[code=nocode:0]JunctionAnimation::JunctionAnimation(Box* b) : Animation(b){ instructions += AniInstruction(0.0f, 0.01f, 0.0f, 0.f, 0.0f, 0.0f, 10), // Raise up AniInstruction(0.0f, 0.0f, 0.0f, 0.f, 2.0f, 0.0f, 45), // Rotate 90 degrees AniInstruction(0.0f, -0.01f, 0.0f, 0.f, 0.0f, 0.0f, 10); // Sink down}JunctionBox::JunctionBox(float _x, float _y, float _z, float _rotation, DX11* dx11) : Box(_x, _y, _z, _rotation, dx11->textures[L"step1.png"], dx11), anim(NULL){}void JunctionBox::OnUpdate(){ if (anim) { anim->Update(); if (anim->IsFinished()) { delete anim; anim = NULL; } }}void JunctionBox::OnClick(const POINT &p, float pickedDist, const XMVECTOR &prwsPos, const XMVECTOR &prwsDir){ if (anim == NULL) { anim = new JunctionAnimation(this); }}JunctionBox::~JunctionBox(){ if (anim) { delete anim; anim = NULL; }}This uses boost::assign to make things nice and simple and easy to read

Next on the todo list: Particle effects for the crate explosions! I probably can't re-use much of the 2D particle system i created before, so wish me luck!




Back to gamedev after a long hiatus...

My current project is a puzzle game called "Firework Factory".

This project has been sitting on my hard disk since 2010, however i haven't actively worked on it since late 2011. I started out with the concept of producing a puzzle game with a plot - looking into the puzzle games currently available very few do, they just have a long sequence of "solve this" and "solve that, now a bit harder".

The idea of the game is to get boxes of fireworks from one end of the factory to the other, re-ordering them in the expected order displayed on the screen. Doing so is made possible by the fact that the player controls various "junctions" which can be made to redirect crates in any of four directions, but must be changed manually. Sending crates down the wrong path, on a collision course, results in pretty particle based explosions, each particle being deadly to nearby crates. Getting the crates out of the factory in the correct order as soon as possible adds to your percentage completion, each level having a minimum percentage to complete (think "cut the rope" or any other game where you must complete each level to a satisfactory standard to unlock the next). As you advance through the levels, plot is revealed to you which changes the game, sometimes subtly and other times drastically. I will not ruin the plot by posting spoilers here, but suffice it to say it is quite interesting, if i do say so myself - if you really want to know the plot in full and are not concerned about spoilers feel free to PM me!

Well, as they say: "All best laid plans of mice and men". When i started on this project, I was single and living with my parents. This changed in 2012 as i settled down with my now wife and we had two babies together. This is not a situation which lends itself to free time to develop games, so the project was put on hold.

Fast forward to November 2014, and as the kids are a little older and my job has changed to one where i am finishing work earlier, and able to take breaks whenever i wish so long as the work is complete, finding myself with a little free time to get back into game development.

Dusting the e-Dust off the repository, I dig around in my code familiarising myself with it once more. After a few minutes of research i find my worst fears confirmed - Microsoft have decided to abandon XNA, there will be no XNA 5, and what's worse, it will not be supported in any form on the Xbox One. This leaves my project in free-fall, not being sure what to do next.

I weigh up the options - move to monogame, rewrite the project in something more future-proof, or just give up. Giving up not being even on the cards for me, after investing so many months producing the game (and coming so close to finishing too) i explore the other two options.

Currently, monogame does not support the content pipeline, so a straight conversion of the project files automatically is out of the question. I could rewrite all the bits of the project which don't work right in monogame, and copy and paste the rest, or i could wait for the newer version of monogame which will (i have been assured) support the content pipeline.

Being the impatient type, i decide against waiting for a new version of monogame - i have free time NOW, and i want to develop my game now, waiting is not an option as free time is few and far between for me.
Also, looking at what Microsoft did to XNA, and the fact that it will not exist on the xbox one indicate to me that targetting the xbox 360 is no longer a sane option for me - it is last generation's hardware.

So, this leaves me with option three - a rewrite. Let's be honest here, most developers when given old code look for an excuse to completely rewrite it as soon as possible, just because it isn't their code. Look honestly at yourself and try to tell yourself this isn't true, deep down ...

So, starting out on the rewrite i settle on Direct3D 11. Changing the game to a 3D game has several advantages, which are:
Most gamers will be quicker to accept a 3D game as "new" and not something "their dad played when he was a kid" - let's be honest, most gamers are materialistic and are wowed by graphics and presentation, not gameplay.
It is more future proof - the DirectX platform has been around since 1995, and isn't going to vanish next year.
Changing the view of the game indirectly makes it a little more difficult which increases the challenge - the 3D camera slightly obstructs the view, causing the player to consider more about what is going off in the game and assume more about the things he can't currently see.
DirectX 11 will just be interesting to learn - in the end, does there need to be any other reason than this?

So, this explains why I've settled on rewriting my game in DirectX 11 (and by extension changing to C++, which i was always more comfortable with than C# anyway!) and changing it to a 3D view.

On to progress - so far, i have implemented a simple camera, based upon a third person camera which is always looking to the centre of the playing field. The player may zoom in or out, and rotate around the playing area a full 360 degrees. When the player zooms in or out, the pitch of the camera adjusts so they view the playing field from a slightly raised angle, from above, to give a clearer view of all the playing field. As they zoom out the camera goes flat, closer to the level of the boxes on the playing area.

I have implemented a way to render the conveyor belts, and the boxes. This will give me the basis of a playable game soon enough, once i port all my existing game logic from C# to C++ (an easy, if not a bit of a time consuming task!).

I have also created a simple audio facility within the game which integrates with fmod (which is now, i might add, free to Indies with budgets of less than $100k... nice).

For artwork, i have realised that i can render 99% of the graphics using bump mapped, shaded and textured cubes, and scaled variants thereof, and a simple particle engine (see the project screenshots to see what i mean regarding this - everything is basically square - easy!) which means that for the time being, i do not need any 3D modellers, and i can re-use a lot of my existing artwork.

So, i will now end my first journal entry, with a promise of a simple YouTube video upload at some point in the coming week. Comments as always are welcome



  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!