KREEP, apples and penguins.

Hi everyone!

Haven’t written for months now about Operation KREEP. It is time to revisit this old buddy bud bud of mine!

Yes, as the title suggest, it is cross-platform time 😉 …

2017_03_23_boxartmultiplatform

Not official, but soon…

Nope, sadly no official release yet 😦 , but the Linux build is ready and tested (at least on my Nix machines) and the MAC build is ready for testing too. This means, that in a week or two an official release can happen, although a little piece of the puzzle is missing.

I require additional pylons!

I have two PCs, so I tested the Linux version of the game on two Ubuntu versions, but more would be nice (zillion distros 😦 ) + I HAVE NO MAC MACHINE 😦 …

This means, that the MAC build essentially never ever been started! I would really love to release the cross-platform builds, players already asked for them, but without sufficient testing it is not going to happen. Buying a MAC would be a somewhat logical investment at this point, but Operation KREEP (and my whole game development venture for that matter) is on an extremely tight budget as it is not profitable so far, so I will try to postpone that a little.

Feedback, results, “compensation”

Based on the differences between the builds (almost 0 code change, only packaging varies), I think a few simple checks would suffice. Whether installation works (files copied, icons set etc…), whether the game starts and basic configuration settings checks (settings work and are saved to correct application data folders) + a short test play round just for fun 😉 .

I know it is shady to ask for free QA for a product, but this is the reality of the situation I’m in 😐 . If you would like to help out I thought about sharing a limited amount of Steam/itch.io/IndieGameStand keys for the full game as a “payment”.

I put together a short form to ease reporting results: KREEP, apples and penguins

If you dislike sharing any personal information, but still would like to help out, please simply post results as comments here or contact me by e-mail: spidi@magicitemtech.com

I guess contact info of a cheap&used MAC reseller in Hungary could help too if you know any 🙂 .

Demo builds

2017_03_24_logo_mac 2017_03_24_logo_nix

Porting tech stuff

Just a little tech talk as closing words. The windows version of the game was made in C# using XNA. Two really cool projects were born to both preserve and enhance XNA in the last few years. MonoGame and FNA. Both are great and well established/tested at this point, but I choose FNA for porting Operation KREEP to Linux and MAC. My reasoning was the following:

  • Around a year or two ago when I was using MonoGame to work on my Linux machines I encountered some difficulties. MonoGame on Nix platform was using OpenTK for window, input and OpenGL context management and as I know, that library had it’s fair share of bugs and there was no real support/contribution/fixes for it for a long while.

    Remark: as I know the MonoGame team changed to SDL2 lately, the same library FNA uses under the hood so it is probably not the case by now. 

  • MonoGame favors a per-platform build approach, which looking at all the possible target platforms (desktop, mobile, consoles) is a logical choice, but requires managing and building multiple executables for each target. FNA from the get go approached this with a common desktop runtime, so one build works on all major desktop platforms (only packaging has to be taken care of per target).
    Remark: if I’m not mistaken, last year a “common desktop” build was introduced for MonoGame too, so technically it could work the same way as FNA for desktop.

  • The FNA developer Ethan Lee had laser focus on cross-platform desktop XNA development and delivery, and the wiki for FNA had a really nice documentation about both working with FNA (differences and extras compared to XNA) and packaging + delivering games using it for Windows, MAC OS X and Linux. This documentation seemed really helpful and complete.

All in all I suspect both libraries could work perfectly for publishing your games to the three major desktop platforms, but I wanted to give FNA a try too. I was pleasantly surprised, most things worked like a snap without much fiddling.

That is it for today, in a few days I’ll post a new video & blog entry for I am overburdened. If you decide to help MUCH LOVE, SUCH WOW 🙂 and thanks awfully!

Take care!

I am overburdened, nobody make a sound!

Hi everyone!

This post is going to be more like a tutorial, than a journal entry. I highly recommend checking out the video version, as it is heavily audio oriented + it contains some recent game-play footage 😉 .

I missed out creating an entry last week. I juggled between projects and tasks a lot, which led to me feeling a bit weary + no significant progress was visible on any front due to working just a tiny little on many aspects, so I decided to postpone it a little. Nevertheless, I’ve spent the last few days on finalizing the audio and sounding of I am overburdened.

Chip tune or not?!

My two completed games used pixel graphics and as a natural fit they were armed with 8-bit style sound effects. This is a really economical approach since making matching effects with a tool like sfxr takes only a few hours tops. From the get-go I wanted to try something different for I am overburdened, both for personal development and because some pixel games with realistic sounds (Canabalt) made me want to experiment with this style. I’m even less qualified as a sound engineer than as an artist 😀 so take my words with a grain of salt! All my mumblings here are based solely on tutorials scattered around the INTERNETZ + some fiddling with tools…

Recording

I decided to record and process as many effects of the game as I can. Last week almost a day was spent clowning with common household items to create noises 🙂 . If you are thinking about a similar approach, start by throwing together a DIY “recording studio” (sponge box). Even if you have a decent microphone it will help immensely with canceling noise and reverberation. Some sponge (check the boxes of your PC parts 😉 ) or a curtain can do the job. Otherwise you may end up with really echoing results (noise can be helped with software!).

2017_03_02_foam_11

2017_03_02_foam_21

Audacity to the rescue

First things first, download Audacity. It’s GIMP for sounds so to speak. Its interface is relatively straight forward (all what you would expect: select, copy, cut, paste, new track, the ‘z’ key ?! for clean cut selection etc…), but Youtube is filled with video tutorials (even with advanced tips and tricks) if you get stuck.

2017_03_02_audacity

The following is a good repertoire to familiarize yourself with from the “Effect” menu:

  • “Noise Removal”: for sampling noise profiles (noisy but otherwise silent segments of a track) and noise canceling.
  • “Change Speed/Tempo/Pitch” and “Bass and Treble”: for mixing and changing effects (e.g.: making them play slower/faster or higher/lower etc…).
  • “Echo” and “Reverb”: for making sounds feel more spatial, and for creating some fancy voice effects (e.g.: making yourself sound like a ghost, demon or a robot etc…).
  • “Fade-In/Out” for correctly starting and cutting off sounds, especially alongside cuts.

My approach, which helped me out learning the ins and outs of effects, is to change back sliders to default positions (0Db, 0% +/-0) and experiment a lot, gradually trying out various modifiers, to see how something affects a sound.

2017_03_02_effects_1

2017_03_02_effects_2

Here is a short reel of what I was able to record and mix for the game:

Public domain

For I am overburdened approximately 50% of the final audio were recorded (some stuff is just hard to record in your room 😦 ), the other half came from OpenGameArt.org and Freesound.org. Both of them are wonderful sites full of really good content, many even final production quality. After listening to an hour worth of sound effects I selected the best matching ones based on my list of requirements and remixed many of them using Audacity for even better results.

2017_03_02_opengameart

2017_03_02_freesound

One thing to be aware of before browsing around these sites is licensing. Keep in mind, just like code, various assets like pictures and sound effects can only be used under strict terms. Some only require author attribution, but some permit fully free modification or commercial use. If you don’t really want to dig into the topic, simply make sure you search for and use assets under CC0. This means the asset is essentially public domain, you can do what ever you want with it, even for commercial purposes!

2017_03_02_cc0

Runtime tricks

You should be applying effects runtime too, to make the sounding of your game more dynamic. I constantly need to remind myself of this practice, I tend to forget about it. Few simple examples are: dynamic pitch, panning and volume control. If a sound effect is played a lot (e.g.: footstep, attack, shoot, hit) and your API of choice allows to set the pitch value (e.g.: XNA SoundEffectInstance) throw in some minor, but random changes! This will make it feel more varying. If your API does not allow this, have no fear! Pre-generate some good sounding variations for the often played effects and randomly select between them.

Example walking cycle in I am overburdened:

If you are not really into the video series but want to hear the difference between the placeholder sounds and the final sounds of the game, here is a timed link: Sound effects comparison

That is all for this post. I already cranked-out tiles and some sprites for the game, so I’m guessing the next entry will be kind of similar, but focusing on the art side.

Take care!

I am overburdened, loot is forever.

Hello everyone!

This entry turned out to be lengthy and pretty technical. Sorry about that, but last week was spent only on “under the hood” stuff. I did my best to make it interesting though 😉 ! So the agenda is the item system which became really sophisticated, especially compared to the size of the game + the difficulty and pacing management.

I settled on the video format of the last entry, because EP 3 was the most pleasant recording experience and in my eyes it was the most enjoyable video so far. So from now on, I’m going for condensed and “scripted” logs focusing on the features and development of the game.

Items, loot

2017_02_19_screenshot_1

The plan for the game is to have a wast and diverse set of unique items (approx 100). Since no leveling will take place, the player will have to risk collecting as much loot as possible during the journey and focus on customizing the play-style by carefully picking which items to wear. So the technology behind the game has to support a great number of skills and excessive customization of the items, but also has to allow lightning fast iteration times, since I will be spending a significant amount of time during the upcoming 2 to 4 weeks with designing and balancing the possible loot.

Attribute bonuses

2017_02_14_gif_1

The easiest development was attribute bonuses on items. Adding the following piece to the descriptor of an item in the loot configuration file will provide the given bonus attributes to the player while equipped:

<Attributes>
  <Attack>1</Attack>
  <Defense>2</Defense>
  <Vitality>3</Vitality>
  <Speed>4</Speed>
  <Luck>5</Luck>
</Attributes>

I highly recommend calculating most of the final modifiers and attributes of a character in RPGs every time one is needed. The more caching you introduce into these systems, the more groundwork you lay for pesky bugs to occur, so keep it low! Usually these calculations are pretty simple (will never be a performance hit) and the hard-coded constant formulas will be really straight-forward to follow.

public class Attributes
{
    public int Attack;
    public int Defense;
    public int Vitality;
    public int Speed;
    public int Luck;

    // events ...
}

public class Player
{
    public Attributes Attributes;

    // handle pick-ups and other logic related to permanent attributes...
}

public class Inventory
{
    public Attributes Attributes;

    // handle item pick-ups and other logic related to item attribute bonuses...
}

The player data holds the permanent attributes of the character (starting attributes + permanent power-ups) and the inventory holds the sum of the attribute bonuses from the equipped items (only a tiny bit of caching) recalculated every time it is changed (e.g.: item pick-up, item swap etc…). The final value of an attribute is the sum from these two structures and the modifiers queried from the extra skills of the equipped items applied to it.

Skills, event system

For a high level of flexibility and to have a varied set of special skills I implemented an event system. I followed a similar but a bit more dynamic approach as the built-in event language feature of C#. Essentially an event is a string (the name of the occurred event) and a context holding additional data related to it and a skill is an event handler implementation.

Event systems can be implemented a number of ways each having their strengths and weaknesses, but all-in-all the following is pretty close to the my solution:
WARNING pseudo code incoming!

// Actual skills need implement this class:
public abstract class Skill
{
    public void HandleEvent(string name, EventContext context)
    {
        if (this.EventsHandled.Contains(name))
        {
            // Additional checks related to the context...

            TakeEffect(name, context);
        }
    }

    protected abstract void TakeEffect(string name, EventContext context);

    // Some helper methods...

    public HashSet<string> HandledEvents;

    // Additional requirements for the event & context...
}

// Special events extend this structure to "add" extra data to the event context:
public class EventContext
{
    // The creature whose action lead to the event:
    public Entity Creature;
}

The execution of the “TakeEffect” method can also be chance based (luck of event firing creature is taken into account). so a skill may only take effect with a given chance (e.g.: 10% chance to “XYZ” types).

An item can have a list of skills listening for events when equipped by a creature. Some events pass in an extension of the “EventContext” class with extra information, like the damage dealt, or the target creature attacked etc…

Few of the most common events in the game:

  • NextDungeonReached: the player reached the next level.
  • Attacking: a creature starts attacking.
  • OpenChest: the player just opened a chest.
  • Pickup: the player picks up a bonus item (e.g.: health potion, gold sack etc…)

Some of the existing skill implementations:

  • Attribute: grants a “bonus” for the upcoming trial (e.g.: +10 luck for the next luck trial).
  • Cripple: interrupts the next attack of the target.
  • Thorns: reflects a “bonus” amount of damage to the attacker.
  • Vampiric: a “bonus” amount of the damage dealt is healed to the attacker.

“bonus” == modifier applied to an integer value. Can be an integer like +/- 5 or a percentage like +/- 5%. The integer bonuses are applied first and the percentage modifiers afterwards.

Most of these events and skills took only a few lines of code to integrate and I have several more ready and working. Combing and configuring them to take effect on specific events with various chances is already an immensely versatile system to build items 🙂 !

Tags

String tags can be added to a creature when describing it in a configuration file, like: undead, deamon, boss etc… The event system allows to define tag requirements for targets before a skill can take effect. A creature meets a given a requirement if it does not have any tags from its “can not have” set of tags and has all the tags from its “must have” set of tags. It is as simple as that.

2017_02_20_gif_1

2017_02_20_gif_2

This tiny addition allows skills which have real “character” to be made. Some cool examples would be monsters tagged as “undead” and a life-steal granting sword which does not work on them (pictured in the GIF), or a holy shield which grants enormous extra defense, but only when attacked by monsters tagged as “deamon”. This also allows to disable certain skills against bosses which could make them too overpowered otherwise.

I’m still at the beginning when it comes to designing the concrete items, but with these systems in place I hope I’ll have a pleasant experience while implementing the actual artifacts. As closing words for the loot topic, here is a rather complicated item description just to show how this is all put together in configuration files:

<!--
  Forearm armor:
    +1 Defense
    20% chance to cripple non "Boneless" enemies
-->
<ItemDescriptor>
  <Type>Forearms</Type>
  <Name>Vambraces</Name>
  <Sprite>Item22</Sprite>
  <Level>1</Level>
  <Attributes>
    <Defense>1</Defense>
  </Attributes>
  <Skills>
    <Skill>
      <Cripple>
        <EventHandled>InflictDamage</EventHandled>
        <ChanceBased>true</ChanceBased>
        <Chance>20</Chance>
        <TargetTags>
          <CantHave>
            <string>Boneless</string>
          </CantHave>
        </TargetTags>
      </Cripple>
    </Skill>
  </Skills>
</ItemDescriptor>

Difficulty, pacing

It’s important to constantly introduce new content and to increase the difficulty curve so the player always finds a challenge while progressing deeper into the depths of the dungeon. I achieve this with a construct called “dungeon profile”. For each level of the story (currently planning to have around 30) a profile will specify which tile-set to use, what kind of monsters can be spawned and what type of pick-ups, treasures and chests can be placed. Of course this data is read from asset files and it is fed into the dungeon generator after constructing the layout for a level. This gives fine control over the length, the pacing and the minute to minute difficulty changes of the whole game without modifying a single line of code.

2017_02_20_pacing_1

Yep, last week was rather busy, though I’m behind my schedules once again 😦 . A little more than a week ago I was confident I will have some (even if not many) art assets done for the game by now. Sadly slipped a little. This is the next step though, so the following entry will have pretty sprites and screenshots 😉 !

Stay tuned!

KREEP, missed tap.

Hello everyone!

In my last post about Operation KREEP, I mentioned that for the 1.2 update of the game I made some improvements to the input handling logic and hinted a near future deep-dive into this topic. Quite a while ago, right before releasing the Steam version, I wrote a similar post describing the input handling enhancements I made back than. Although it is a bit lengthy, if you are interested in the technical details of high level input handling logic I highly recommend it. Not a requirement though, since I’m continuing this post with its summary to level up your knowledge for easier digesting of the upcoming technical details.

Short recap

The game plays on a grid and all entities move complete tiles (no standing in between two tiles). Each “move” action by a player will actually take multiple frames to complete (precisely 12 which is 200 milliseconds under 60 fps). The players usually do not feel this (it does not feel laggy/bugging), since it is a quite fast and action packed game + 200 ms is not much and the overall rules/design of the game is deeply intertwined with grid based movement.

The initial movement handling logic was utterly simplistic. If a direction button is pressed the player moves towards that direction, with a silly hard coded priority for handling cases when multiple direction buttons are down: “Up” beats “Down” beats “Left” beats “Right”. When a player is already moving and the corresponding direction button is held down it will be handled with highest priority, so continuing movement forward is considered “important/intentional”.

Warning, warning incoming pseudo code:

void handleIdle() {
    if input.isPressed("up") {
        startMovement("up");
    } else if input.isPressed("down") {
        startMovement("down");
    } else if input.isPressed("left") {
        startMovement("left");
    } else if input.isPressed("right") {
        startMovement("right");
    }
}

First pass of input handling in “Idle” character state.

void handleMoving() {
    if (input.isPressed(currentDirection)) {
        continueMovement();
    } else if (input.nonePressed) {
        stopMovement();
    } else {
        // this will handle direction change
        // the same way as in "Idle" state
        handleIdle();
    }
}

First pass of input handling in “Moving” character state.

That is it. This simple control mechanism was really easy to code certainly but it wasn’t intuitive nor responsive, and clearly intentional actions were missed out from time to time. It took me some time to realize that it was bugging many players and it could be improved a lot.

Around the 1.1 (Steam) release, I made significant changes to this system, by introducing some smart checks to figure out the intentions of a player as best as possible. These rules included:

  • Checking the surroundings of the player character.
  • Taking non-walkable target tiles into consideration (making them a less preferred choice).
  • Taking dynamic blockers like other players, props or the KREEP, into consideration (just as important targets as walkable tiles).
  • Saving the elapsed time since the last press of each direction button to use it for prioritization (presses closer to the direction change in time considered more important/intentional).

These modification made a huge difference back than. At least the “testing committee” (a.k.a. friends) had an immediate positive reaction, although I still had some ideas for improvement I was thrilled by the results. For more details about these enhancements, please check the old post. I’m jumping onto new stuff now!

The missed tap

One thing that was still bugging me related to these movement controls and the overall responsiveness of the game is the “missed tap”. Due to one move action taking 12 frames, the direction change evaluation logic runs “rarely” and it is easy to miss it by a frame or two. An occasional maneuver is trying to change “lanes”, by moving one tile perpendicular to our current direction, but continuing in the original direction right afterwards.

Operation KREEP lane change maneuver GIF

Some players (including me), try to achieve “lane changing” by holding down the main direction button and tapping the perpendicular direction button. The perpendicular direction gets bigger priority, due to the press occurring closer to direction evaluation in time, so it would be selected as the new direction for the player.

Operation KREEP lane change maneuver input handling GIF

But being a short tap the button state may be released one or two frames early and usually the following happens:

Operation KREEP missed lane change maneuver input handling GIF

Based on my guesswork, trying to achieve “lane changing” with a tap fails 3 out of 4 times (may be even worse). This is not hard to detect and sort-of can be made sure to be not mixed up with different intentions, so here comes my solution.

Implementation details

Instead of saving only one elapsed time since the press of a direction button, two timers are saved for the last two states (regardless whether it is pressed or released currently). This way we can buffer the most recent changes and the preceding actions of the players related to movement (buffering input events and their timings).

struct BufferedInput
{
    bool pressed;
    float currentElapsed;
    float previousElapsed;

    void update(bool state, float dt)
    {
        if (pressed == state)
        {
            currentElapsed += dt;
        }
        else
        {
            previousElapsed = currentElapsed;
            currentElapsed = dt;
            pressed = state; // pressed changed, timers swapped, current restarted...
        }
    }
}

That is the most crucial part of the solution. From now on we can detect the “missed taps” when evaluating the player movement, since we have all the required data. I think each game needs a little fine-tuning / trial and error regarding this part as timings and speed wildly varies between them, but my logic and my numbers may be useful:

const float FrameTime = 1f / 60f; // frame time in case of 60 fps
const float MovementTime = 12 * FrameTime;

bool detectBufferedTap(BufferedInput input)
{
    if (!input.pressed)
    {
        var tapTime = input.currentElapsed + input.previousElapsed;
        if (tapTime <= (MovementTime - 2 * FrameTime))
        {
            if (input.currentElapsed &amp;lt;= input.previousElapsed)
            {
                return true
            }
        }
    }
    return false;
}

This means that the game considers a situation a missed tap, when a direction button is released during evaluation, a press occurred at least 2 frames after leaving the last tile (last direction evaluation) and the button was in a pressed state for at least as much time as it was released during these x <= 10 frames.

Input buffering technique frame-by-frame depiction

Taking these “missed taps” into account with just as much priority as a pressed input button, while the player is moving and a direction evaluation occurs, reverses the 3 out of 4 failures, so approximately 3 out of 4 times (maybe even better) a short tap is enough for a tile lane change. Tried tweaking this logic and the numbers, but could not really improve the consistency further. I’m happy with these results though. And again, after this update, controlling the game felt much better than before!

Probably there won’t be updates for (nor posts about) Operation KREEP for a long while, since despite my efforts the game could only reach a miniscule audience + I’m getting fully occupied by my upcoming game Unified Theory, but who knows what the future holds…

Take care!

Magic Item Tech, honesty and shame…

Haven’t written in a while about what is up with Operation KREEP or my next game, not even game-tech related posts, and I think it needs a little explanation ( at least me, myself, are in desperate need of some honesty towards myself 😦 ).
After I finish my rambling about “life and stuff”, there will be some tech talk too in the topic because I dislike not showing anything fancy, so if you are only interested in that part, scroll down a couple paragraphs 😉 .

So why isn’t the next game announced, I’ve already mentioned it twice before, that it is close to being playable, and in the upcoming weeks I may even distribute an open alpha build…
It is still not ready for that (no kidding 😐 ?!).
The last month was somewhat “wasted” from a gamedev perspective. Wasted is a harsh word for it, but the truth is I feel a bit ashamed of how the last few weeks played out (development wise), so it kind-of fits. Instead of mostly spending my time with the development of the new game, I’ve mostly spent my time with “engine-tech”. The worst part is, that it got a tiny bit out of control, since if I’m going to be really honest with myself, at least a week worth of development was 100% unnecessary for this upcoming game.

A little back-story:

As many of you may already know, I’m developing my games using C# and the framework of my choice is XNA/MonoGame. This goes way back in time (almost 10 years): Unity did not exist and XNA was a hot new tech (in BETA or 1.0 which was extremely bare-bones can’t remember) when I started learning programing ( University + the ultimate purpose of being able to make GAMES!!! 😀 ). Back than it was a natural choice and worked wondrously. Fast forward to today and MonoGame is still a great choice, if you have professional programing experience (or want to learn programing) and you are ready for some game-system/engine development compared to Unity, but for a more complex game, lots of stuff has to be coded (no physics, no advanced rendering system, no UI system etc…).
I actually like this level, I feel comfy working this way + I’ve been building and growing my own “framework” (or whatever it should be called) on top of XNA/MonoGame for years now. I have a keen eye for software quality and I’m especially proud of it’s feature level and stability, and I’m really productive when using it to develop a game.
I think, that last one (productivity) is the most important part when it comes to “choice” regarding your language/framework/engine/tech!
But, and here comes the BIG BUT:
It is still only a light-weight game development framework. Not, that there is a problem with that 🙂 , but if I would take the time to get proficient in Unity, most probably I could be just as much, or even more productive, especially looking at the current situation when I go in to game-tech feature creep craze 😦 .

Nowadays, I’m trying to make more out of working on games (living / business), so this becomes an increasingly important question, whether my time is spent well working on this framework. The answer is probably no, but my current level of productivity and emotional attachment ( I don’t know what else to call years of hobby development 😐 ), keeps me working on it. Of course I have more rational reasons than that, but the post would be humongous and it is already big 😀 . From now on, I have to be brutally honest with myself when it comes to this question and be more self-aware when it comes to tech development decisions.

A little more detail about the current project/situation:

I wanted to upgrade my testing framework for this upcoming project which went surprisingly well and happened pretty fast, but this game I started working on required numerous other features which were lacking from the framework too. I decided, that I’m going to spend approximately two weeks on development of these features in isolation, not really jumping into coding the game beforehand (just only the basics), so I can focus on delivering clean and stable code for starting production.
This became four weeks, due to various “common” reasons: underestimation (only a little), forgotten pretty important framework related developments ( these were not even estimated in my backlog 😦 ) and a week amount of feature creep.
The only conclusion here is the same I mentioned before, I need to re-think how much energy I pour into this code-base, and whether it is going to be “worth it”.
Now, that I have everything in place (and got out of this spiraling feature-creep menace), the development of the game is advancing, but it is still far from a presentable state 😦 .

Here comes the technical part, what I’ve been working (wasting my time) on:

The major part of the tech development was a proper UI/Widgets system. For Operation KREEP I used a simple approach, where each UI element was a simple graphic object positioned relative to it’s parent UI element. Nothing fancy just a simple base class with a position and an attachable graphic (e.g.: sprite, text etc…) arranged in a tree-like hierarchy, lean and clean.
No built-in serialization logic, no scaling, no anchoring, no alignments, no padding or margins, even mouse input handling and a good event system was missing! For the most part it was OK for KREEP (not much UI and pretty simple), but it was certainly an insufficient solution, and a lot of stuff had to be done in the project code-base and hard-coded while working with it. Yep, pretty ugly 😦 .

The current strategy game I’m working on is much more UI heavy and will have a pretty different look (not pixel graphics + different resolutions), so the before mentioned “problems” had to be resolved. I heavily extended the old system, and implemented a two-pass layout engine (measure the elements of the hierarchy first, than arrange them based on their requested size), with some fancy additions (e.g.: nine-patch sprites).

This is how it looks now:
2016_08_09_Widgets_UML

And, than it hit me, I forgot about auto-tiling 😦 …

Yep, I pretty much forgot to estimate and put this feature into my backlog when designing the game. And no, it is not some fancy tooling stuff, which I don’t really require, but plays a kind-of an important role in the game. It plays a big role in the looks of it, which IS important, so I had to implement a run-time auto-tiling feature. This is how it looks in action:

It only handles one type of surrounding tiles (supporting multiple ones is ridiculously difficult + the game did not need it) and supports both four-way and eight-way rule sets.

And, while working on auto-tiling I made a performance bug…

It was a mistake I did not discover while testing my code. The internal data-structures were handled incorrectly, and with an imperfect stop condition, from time-to-time the auto-tiling took more milliseconds than a frame should at 60 fps, so I sat down to hunt for the reason of these frame-spikes. Needless to say, that I already had a vague idea how to approach the problem and where to look + an existing .NET profiler would have revealed the exact issue in mere minutes (if not seconds), but somehow I felt this is the sign of the “NEED” for a visual profiler ( I don’t know what pills I took that morning 😐 ).
I was already way out of my frame-work development time budget but still the creep emerged from the dark depths of the unknown and engulfed me. I took the time (few days) to develop my own visual profiler integrated into the framework…

cthulhu_and_r27lyeh
This is how I imagine that mental state from now on. I can’t exactly remember or picture it, so this will do 🙂 .

After this point, I’m still not over the feature creep, but starting to grasp reality!
Took a couple more days to wake up from the refactoring madness too…

That is enough from the wall of shame of Spidi. Next week will finally be about my upcoming game.
Best regards.

Magic Item Tech, testing – part 3.

Hi all!

It is time for some software testing framework talk again 🙂 !

As you know, I’m a big quality/testing advocate (especially when it comes to software!!!), and I’ve been working for a while now, in my “lab”, on a high-level testing and automation framework, since I’ve reached the limits of usefulness of unit testing my game projects.

I’m going to showcase the newest addition to this testing framework, so if you completely missed it and interested, here are the two older posts summarizing the design and some implementation details ( with showcase video 😉 ) about it:
Testing – part 1.
Testing – part 2.
A quick recap, if you would not like to read through the usual pile of text 🙂 , but still interested in this dev. log. entry:
It is a “capture and replay” based framework, where you can record (or edit/create) input events (or special ones, e.g.: network, debug events etc…) from the game to replay them later. For checking certain functionality, the replay files can be filled with assertions targeting the properties of any game-object within the game world at any given frame of the replay.

So the system served me well while developing the Operation KREEP update. It took less than two work days to reach a pretty high coverage of game-play features and the UI work-flow (around 80% code coverage in 12 hours). This test-suite helped me a lot while releasing the Steam version, besides keeping my sanity by covering and assuring, that most of the high level features work, it saved me from introducing a few pesky bugs while coding the new features!

After a while though, execution times grow as it is to be expected. The 67 replays for the final Steam build(s) which checked the UI work-flow, completed the tutorial, played till getting most of the achievements and so on and so on, requires around 11 minutes to fully execute ( more than a cup of hot beverage takes from inception to getting it into the belly 😀 ). I knew, that after a while this is going to happen, worked before with similar frameworks, but also already had some ideas in the back of my mind to fight it if it may become a problem. Obviously this was not a big irritation yet, but for a larger game it may become a certain source of frustration.

2016_07_17_Execution

The most simple and obvious solution was categorizing test-cases within a suite (UI, Options, Graphics, Tutorial etc…) and only execute immediately required categories. This took only a short time to develop and configure as NUnit already had support for it. I just had to put some extra properties here and there.
This was nice and worked well, taking less to test the crucial/modified parts faster, but of-course there was a much smarter idea there from where this one came from ( a full test still required 10+ minutes 🙂 , no way I could not improve on that 😉 )!

    
    
        
        
            Match Pause Restart
            Tests\ReplayMatchPauseRestart.xml
            
                
                Match
                Pause
            
        
        
    

2016_07_17_Categories_1  2016_07_17_Categories_2

So I investigated two common solutions to this problem (actually there is a third one which is manual: modify test-cases to make them simpler and shorter, but that is not a general solution, takes time and the gains are small), and I went with the “speeding up test-case execution” route. I haven’t find any good/common name for it, although it is a known solution, so I called it the “unlocked” game-loop. The concept is simple: when replaying the test-cases a different game-loop is used, which runs as fast as it can ( no vsync no sleep nothing like that, exercising the CPU/GPU like a mad man 😀 ), but the elapsed, total and accumulated time calculated and passed to the systems and game-objects of the game is mimicking the normal game-loop, so the game “believes” it is running at normal speed with the target 30 or 60 frames per second. I was certain that it is going to speed up execution, and at least cutting execution time in half with a simple game. I was wrong, it became much much faster 😀 . After the new game-loop, the full test set took not much more than 2 minutes instead of 11…

Take a look:


Note: the first two minutes show the normal execution of 6 test-cases and the rest of the video show the same tests executed with the “unlocked” game-loop.

The approach has some down-sides (as with every route in software development), e.g.: the game may use system time for certain features (although I think this should be avoided, since the game-loop provides an elapsed total time of the game execution handled the same way as the elapsed/accumulated time) and another one is full-screen/windowed mode toggling which is not supported by this feature at all (maybe in the future, I guess it could be done, just it would require some hacks, don’t know yet). For these problems I “cleverly” introduced a per-test-case setting to override the game-loop-unlocked configuration, so the execution speed-up can be disabled for “unstable” test-cases.

    
    true
    
        
        
            Toggle Fullscreen
            Tests\ReplayToggleFullscreen.xml
            
            false
        
        
    

Another “I’m not so happy about it” thing is, that it is a bit hackish and fully platform dependent solution currently, but I guess in time I will solve this problem 🙂 .

As I mentioned there was another route I could take to speed up test execution. I think it is a somewhat superior solution, but would have taken much more effort both software and hardware wise, so I decided to go with the simple one. NUnit has an open parallel execution engine add-on, and I think it requires no explanation why that route is superior, since the limiting factor would only be the number of machines I could harness, but setup (and stability?!) would be a much more complex issue. In time I may try it out, since I’m interested in the actual setup time it takes + I’m certain with a couple of boxes execution time would match the time it takes to run a unit test set 🙂 , but the current solution fully satisfies my needs and my work-flow.

The testing framework is in an extremely stable and usable state for production by now. I’m going to make good use of it for my current game too. In time I’m planning to add more features to it, so a “testing – part 4” entry may happen 🙂 , but not anytime soon + most probably I will only focus on smaller, usability enhancements and additions.

I’m still working on some framework-y code from time-to-time (maybe next entry will be similar, mostly technical) and the current game project is not yet ready for announcement, but with this game I’m going to do a more open development. So starting from the working prototype till the finished product, I’m going to post (weekly maybe?) releases with limited content to get feedback and improve on usability, balance and overall features from the first days and to reach more players interested in the game, even before going to greenlight/itch.io/hopefully-Steam etc…
Expect a somewhat playable version soon (I think within weeks).

Take care!

KREEP, input is king!

Hi there!

I’m not going to go into a big yakking this time about the obvious again. Summarizing: still not advancing as planned and my online presence is still far from adequate, but the update I’ve been working on is “finished”. Finished in the sense, that I’ve added all the features, fixes and fine-tunings I really wanted to add, but it is not yet released, so a final test and a last big “marketing” push is ahead of me…

This time I would like to talk about the last feature I’ve implemented, and as the title suggests, it is input handling related. I feel like it was bit of a daring act, but in the final stage of the development I’ve decided to rewrite most of the input handling logic of KREEP as the finishing step. Yep, it was kind of a bald move, and took some serious effort, both design and implementation wise, at least compared to other features I’ve been working on lately, but it made such a huge difference, that I’m really glad I made it!

A while ago I had a rather lengthy test session with some friends and colleagues. They told me they had a blast, but I could squeeze out some constructive ( negative 🙂 ) criticism too. It was targeting the input handling, notedly the movement of the player characters. While I was observing my peers playing, I noticed this sentence come up a couple of times: “it’s not moving in the direction I want it to move”. It wasn’t angry/bad, but heard it enough to start thinking about it, but when I asked around, no one could actually pinpoint the problem, or describe it in more detail, only there was “something annoying” about the feel of the player control.

Some other developer friends, actually praised the controls before, stating, that it is really tight, and feels like older Pac-Man or Bomberman games, so it took me some time to figure out the problem, but approximately two weeks ago I had an “a-ha” moment while playing and realized what was bugging my buddies. The game indeed feels like old Pac-Man or Bomberman games, but I discovered some problems with this scheme (at least with my implementation). The movement is discrete as in the mentioned games, so by pressing a direction key, your character will not stop until it reaches the next tile and the game is pretty fast. It takes 0.2 seconds, so 12 frames (with 60 fps fixed loop), for a player character to move a full-tile distance. When trying to do tight “maneuvers”, so turning around a corner, or entering a door, or simply changing your direction at the right moment, you have to be spot on, otherwise you can miss the corner/door! Based on what I’ve found, this 0.2 seconds is already lower than the average reaction time for humans to a visual stimulus (which is 0.25 seconds by the way). This is pretty common in games, so reducing game speed was not something I planned to change though, especially because it would modify the design and game-feel a lot. I went further down the rabbit hole and found, that not only you have to be spot on in KREEP, but the logic I’ve implemented for deciding which direction to “prefer”, when multiple keys/buttons are pressed in a given frame, does not “aid” the player. It is pretty much stupid (simplistic) and fails utterly in a sense, because in the before mentioned situations (maneuvering), you usually have two buttons pressed…

Here it is what I’m talking about, what the user intends to do is on the first GIF, and the second and third GIF shows what happens from time to time:

2016_05_09_GIF_1  2016_05_09_GIF_2  2016_05_09_GIF_3

In the first “failure” case, the player is holding down “Right” and “Down” together for a split second and releases “Right” too late, and in the second case “Down” is pressed too late. The latter problem is really hard to battle, but can be done to some degree (still experimenting with that, more on it a little later), but the first one is actually not “fair” (at least the players feel that way: “it’s not moving in the direction I want it to move”) and it can be fixed using a simple idea + a full rewrite of my previous input handling logic 😀 😛 .

So previously I used a pretty simple input handling logic for controlling the player character movement (warning, warning incoming pseudo code):

void handleIdle() {
    if input.isPressed("up") {
        startMovement("up");
    } else if input.isPressed("down") {
        startMovement("down");
    } else if input.isPressed("left") {
        startMovement("left");
    } else if input.isPressed("right") {
        startMovement("right");
    }
}

Input handling in “Idle” character state.

void handleMoving() {
    if (input.isPressed(currentDirection)) {
        continueMovement();
    } else if (input.nonePressed) {
        stopMovement();
    } else {
        // this will handle direction change
        // the same way as in "Idle" state
        handleIdle();
    }
}

Input handling in “Moving” character state.

There is a huge problem in both parts. One is that a direction “preference” is hard-coded, so “Up” beats “Down” beats “Left” beats “Right” and the other is that while “Moving” the current direction is again “preferred” over other directions, for no real obvious reasons ( except for it is easy to code 😀 ).

Both problems and the previously mentioned “multiple buttons pressed” issue can be eliminated easily by adding time-stamps to button presses! Instead of simply checking one button after the other, we always check each direction and the later a button was pressed the more “preferred” it is, due to a simple logic which is: the last button pressed by the player is most probably is the “intended” new direction. This logic off-course can be further enhanced with another trick. It is most probably isn’t the “intention” of a player to face a wall when multiple direction buttons are pressed and some of them would mean simply trying to move into concrete, so besides time-stamps, possible directions are checked also.

Here it is, the further enhanced “smart” input handling algorithm (warning, warning incoming pseudo code again):

bool canMoveTo;
direction target;
time pressed;

void handleIdle() {
    canMoveTo = false;
    target = null;
    pressed = time.min;

    detectTarget();

    if (canMoveTo) {
        startMoving(target);
    } else if (target != null) {
        changeDirection(target);
    }
}

void detectTarget() {
    foreach (direction) {
        if (input.isPressed(direction)) {
            if (canMove(direction)) {
                // prefer movement over hitting a wall
                // if no walkable target is detected yet use this one!
                if (pressed < input.pressedTime(direction) or not canMoveTo) {
                    targetDetected(direction);
                }
                canMoveTo = true;
            } else (not canMoveTo) {
                if (pressed < input.pressedTime(direction)) {
                    targetDetected(direction);
                }
            }
        }
    }
}

void targetDetected(t) {
    target = t;
    pressed = input.pressedTime(t);
}

New input handling in “Idle” character state.

bool canMoveTo;
direction target;
time pressed;

void handleMoving() {
    canMoveTo = false;
    target = null;
    pressed = time.min;

    detectTarget();

    if (canMoveTo and target == currentDirection) {
        continueMovement();
    } else {
        if (canMoveTo) {
            changeDirection(target);
        } else if (target != null) {
            changeDirection(target);
            stopMovement();
        } else {
            stopMovement();
        }
    }
}

New input handling in “Moving” character state.

And here is the representation of the inner workings of the new algorithm in action:

2016_05_09_GIF_4

The direction arrows represent the pressed direction buttons by the player and the lighter color means the most recent button press. Both possible directions hold an orange question mark until the decision about the direction is made (this is not actually checked or saved anywhere until the respective frame). The frame in which the decision happens is “frozen” for a tad bit in the GIF so the choice is clearly visible.

It worked wondrously 🙂 !!! The movement become a bit easier using the keyboard, the multi-press problem disappeared, but the gamepad + thumbstick based control feel got a real “level up” due to this modification! It is really cool. After completing and trying it, I felt that all the updates I’ve added to the game (new maps, new mutators and achievements) are simple gimmicks compared to this modification. It really makes a difference and I’m really happy I made it.

After a lot of testing, I’ve found a situation where the new logic was kind of detrimental, and I felt like it may not actually follow the players intention. When a corridor gets blocked by a dynamic entity (a player or the KREEP), the new logic actually “tries” to move the player in a different direction, like in the following situation:

2016_05_09_GIF_5  2016_05_09_GIF_6

Here the player presses “Down” than a bit later “Left” in both cases, but in the second case another player blocks the corridor. Since “Down” is still pressed, due to the new logic, the player starts to move downwards as there is nothing in the way. I felt like in most cases this could be counter intuitive, since the player usually tries to move towards these “dynamic blockers” (due to the game rules this is the most logical goal), so I introduced some extra code, which separates dynamic and static blockers (collidable map tiles) and handles dynamically blocked tiles just as much “preferred” as walkable tiles, so that only the button-press time-stamp makes the difference in these cases. Again this worked like a charm, but all-in-all it is pretty ugly and “duct-taped” ( so no pseudo code this time 😛 ) + the whole thing took a long time to experiment, implement and test thoroughly.

What I’m still fiddling with, but is not going to be in the upcoming Steam release, is the second issue from the original “perceived” control problems: pressing the intended direction too late. This is much trickier and it is much more a player fault than the first one, but can be helped a little with an “input window”. For one or two frames, you buffer specific situations where different input state would have ended in a different direction. Than later you reposition the player, if still possible / makes sense, and it is much more likely, that the given direction is only a late press (e.g.: in the new position it would be blocked by a wall and no other directions are pressed at the current “late” frame). Most probably in these situations a one or two frame continuation in the same direction will not be noticeable by players, but will extinguish almost all late-press annoyances. Here it is, a little animation showing the inner workings of the “input window” algorithm in action:

2016_05_09_GIF_7_1  2016_05_09_GIF_7_2

In the GIF there is a one frame “window” represented. This frame in which the decision and reposition happens is “frozen” for a tad bit so the choice is clearly visible. The second GIF shows the animation sped up to the same level as the characters move in the game. Even on this GIF with rectangles and lines, the one frame “window” and repositioning is barely visible so I have high hopes, but the implementation is tricky, so it’s going to take some time + I’m already in a “I really want to release this game on Steam” mood 🙂 !

Overall working on this problem was a wonderful experience, because it taught me how much difference good input handling makes (input IS king 😉 !), and that it is worth putting energy into seemingly miniscule issues/ideas too, since they may end up awarding huge benefits ( + I F’ING LOVE GAME DEVELOPMENT 😀 ).

I’m planning to release the update in two separate turns. First giving it out to those who already bought the game on itch.io and IndieGameStand within a week or two, than releasing the game on Steam a week or two afterwards.

Sorry for the long write again, stay tuned for more 😉 !
Best regards.