Hi, I’m Tamás Karsai (Spidi) a solo game developer forming “Magic Item Tech”. I used to grind for magic items day and night, now I’m building games using technology fueled by them :D . Terminal craze: cats, game development, games, movies, toon & anime, comic books (in that order).

RSS My Blogs  (10 - 19 of 19)

KREEP, 1.1.

Spidi777 Blog

Hi all!

Small update (~announcement) this time. Operation KREEP 1.1 is available:

Posted Image

Posted Image

Now if you buy or re-download the game on one of these store-fronts you get the latest version ;).

I made a little teaser too this week for the update:

Still working on releasing it on Steam but based on the tasks left, it is only a matter of days. I didn’t really wanted to set a fixed date, like next Friday or something like that, but it is safe to say, that by the end of next week it will be ready.

I will write a “mini-mortem” for this 1.1 update and the Steam release once the whole thing is behind me, since a lot can be learned from these summary goodies + compared to the development of the original game I feel like my level of discipline and the overall organization of the project was a mess :(, so I have to draw my conclusions and keep this lesson in my mind.

Take care!

KREEP, input is king!

Spidi777 Blog

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 :D:P.

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 :D).

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 :P) + 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 :D).

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.

Hello everyone!

Yep, I know it is not the first week of March :), but I think a little irony never hurts + it is helpful to make one remember, that “man proposes god disposes”!
The first week of March was the planned finish (maybe even release!) date for the Steam update for Operation KREEP. Albeit it was a vague plan, still, here I’m close to three weeks after and I’m not even finished with the extra content.
Planning is hard, keeping yourself to your plans is even harder :(…

Oh well, at least huge progress this week :)! Here they are, the new goody goodies I’ve added to Operation KREEP:
Three new mutators made it into the update and they are fun as hell :D.

2016_03_26_GIF_1
Chaos KREEP in action. This is what I call “hard” mode, or “really chaotic” mode. The KREEP not only spawns it’s “KREEP-lings” every second or so, but moves around the map too.

2016_03_26_GIF_2
Slow missiles is really weird :D, players can race their projectiles :P.

2016_03_26_GIF_3
I suspect Explosive vandalism is going to be a real game changer but only in case of short matches, or it will enforce careful play, so players don’t blow the whole map up in an instance by shooting at large group of props accidentally :).

Besides implementing the new mutators, I made some subtle modifications on the user interface. Since I plan to add a few new levels next week, the number of levels are going to be close to twenty, and I realized, that navigating a rather lengthy list with only the arrow keys is going to be cumbersome…
I didn’t want to overhaul the whole UI, so instead of adding mouse control or redesigning to have a grid based level selection, I’ve implemented page-up/down, home, and end key support. While I was at it, I added entry number indicators to make the scroll-bars more useful.
2016_03_26_GIF_4

That’s a wrap for this week. I think it’s still too early to declare a finish date, especially based on my progress during the last two months, but I’m getting close now, so I think by the end of next month, the new content and the Steam build is going to be mature enough to release it.

As always, I’m open for critique and suggestions, and stay tuned for the next update!

Hello there!

It looks like I fail to stick to my plans regarding this development blog, and sadly overall to becoming a bit more organized :(. Instead of listing the well known and common indie dev. distractions which bog me down too I jump onto this months “achievement”: the achievement system :P .

When I designed the Steam update for KREEP and selected the features that will make the cut (self imposed time constraints, that I already ran out of :() Steam achievements were no. 1 on my priority list. So I knew, achievements have to happen, but when I sat down to design the software changes required, I came to the conclusion, that simply implementing the whole thing in the game project would be messy and foolish, and the bulk of the achievement system could be implemented as a “low level” service in my framework code!

I wrote down the following points, as the design guidelines and requirements for this lower level service:

  • An achievement is not much more than a boolean flag (state) whether it’s unlocked or not, and some accompanying rules about unlocking circumstances and presentation (description).
  • The game logic itself already implements fine details regarding when and how something relevant to achievements occur and it only needs to signal these events to the system (this is the only thing that has to be added to an otherwise complete game code for fully working achievements).
  • The game code shouldn’t need to know or care about whether the achievement state is read from a file or downloaded from a network back-end, or gathered using the SteamAPI. This logic is especially irrelevant for the part of the code where certain events unlock achievements, but at the meantime the service should support multiple persistency modes, since not everyone is a Steam user and achievements would be a nice addition to non-Steam buyers too!

This is what I came up with and implemented:
2016_03_16_UML

A little more description:

  • The API user interacts with the AchivementSystem class almost exclusively.
  • For unlocking achievements “events” (string or integer IDs) have to be fired/signaled to the system, e.g.: “XYZKilled”, “Level1Complete”, “BossDead” etc…
  • For finer control of some achievements, time-frames (again string or integer IDs) can be started and stopped on demand, e.g.: “First10SecondsOfRound”, “JustRespawned” etc…
  • The AchievementDescription instances are shipped as a game asset, the AchievementState instances are gathered using the persistency manager, and they are matched with their correct description using a string ID (external reference). The API user can not directly influence or change the state of these objects. It must be done ( for the sake of clean code and my sanity :P ) through the AchivementSystem using “events”.
  • Achievements can have a counter (optional), for “collection” based achievements, e.g.: “Kill 1000 zombies”, “Respawn a 100 times in one match”
    These counters can be accumulative (“Achieve 100 kills”) or they can be connected to time-frames and reset immediately upon a stopped time-frame (“Achieve 100 kills within the first 10 minutes of a match”).
  • State persistency management is automatic and almost entirely hidden from the game logic, only configuration and implementation selection required: instantiating the wanted AchievementPersistencyManager implementation e.g: File, Network, SteamAPI. Persistency handling is “session” based, so unlocked/progressed/reset achievements can be collected and flushed together (but it is optional), which is usually useful for both file and network based serialization.

A small video footage of a sample built using the system:

Here is an achievement description from the sample in XML format:

<?xml version="1.0" encoding="utf-8"?>
<AchievementDescriptor>
	<ExternalReference>Backspace</ExternalReference>
	<Name>Back out seconds</Name>
	<Description>Hold down backspace for 10 seconds!</Description>
	<ProgressCounter>
		<MaxValue>10</MaxValue>
		<Format>{1,2}/{0} ({2})</Format>
	</ProgressCounter>
	<ResetOnTimeFrameStop>true</ResetOnTimeFrameStop>
	<EventNames>
		<string>HoldBackspaceForOneSec</string>
	</EventNames>
	<TimeFrames>
		<string>BackspaceDown</string>
	</TimeFrames>
</AchievementDescriptor>

It describes the “Backspace” achievement, keeping state using a counter (10 seconds), progressing for every “HoldBackspace” event fired (this is fired in the sample every second if the backspace key is down), and resetting if the “BackspaceDown” time-frame is stopped (this is started when backspace key is pressed, and stopped when it is released).

There are other useful features in the system, which I didn’t mention yet, and a lot of planned ideas to extend it (like multiple named counters for achievements) but I often end up with a huge writing so I’m calling it a day at this point :).

Hopefully the next writing will be about concrete new features in KREEP and maybe about a release date on Steam ;).
Stay tuned!

Hi everyone!

It’s been a while since my last post. Lately I had to focus on a lot of things (KREEP, Steam, paperwork, framework development, day-job, health issues, new cat :) !!!), and I wound up not being able to actually focus on any of it…
Now I’m trying to catch my breath, doing the best I can to organize my time better, and I’m going to restore the habit of telling the story of my progress in game-development land (getting back to posting every week or two). Starting it, by delivering a long ago promised follow-up for the game software testing topic ;) !

In the last post I summarized the design goals of the (halfway-)developed framework. The main purpose was to create an automatic testing system which provides a trivial way to create and extend high level (integration/functional) test cases for my game projects. Since then, I finalized most of the features and inner workings, and made a regression set for KREEP with a pretty decent code and functionality coverage.

The testing system and work-flow is based on “capture and replay”. This means, that for creating a test case you actually play the game, trying out various facets of the program, and the engine captures events (e.g.: input events, key and game-pad presses, etc…) while doing so. These events are than saved to a file, and the engine itself can run in “replay” mode, to replay these events later on. This alone would not allow things to be validated in an automatic fashion, but a special event type serves the role of replay based checks. These “Check” events implement the same interface as other common events, so replaying them can be done right before a given “Update” call, and they define specific assertions for game objects in the running game. Since components have a string identifier tag, a check can search for given entities (like the player, or a map element, or any enemy monster etc…), and with a little reflection magic, assert on any of the properties of these components. Filling the replay files with these checks to be done before given “Update” calls creates the actual validating automatic test cases.

Here is the class diagram (simplified) showing the architecture. It’s clearly visible, that the record & replay systems and their building blocks are mirrored (as their functionality/goal) and it is easy to extend both systems with introducing new leaf implementations (recorders and events):
2016_02_14_UML

I’m already experimenting with other “Check” event types. Screen-shot compare check compares the state of the back buffer to a given reference image. This approach has both great advantages (e.g.: sanity checks for rendering/graphics code + validates huge amount of the functionality leading to a given state of the game) and disadvantages too, since it is quite unstable (changing a sprite or a model a little can cause the comparison to fail, but smart comparison algorithms, like histogram or color-channel-distance based comparisons can help) + they are not really helpful until the game is (or at least larger parts of it are) in a quasi finished state. This is why I haven’t based the validation aspect around this approach, and why it is still not a fully flashed out part of the test framework. Game-object hash value checks will be a somewhat similar beast. They are just like the standard property checks, but instead of asserting on scalar values/properties, the hash-code of a game-object (Object.GetHashCode) is recorded and checked when replaying. This is also quite fragile, because adding a new component or a new property to a game-object could break a test, so it is a type of check which is more useful when larger parts of the code approaches the finished status, but it can validate a huge part of the game state too! At least it is not hard to update broken but not actually failing tests with new hash values and screen-shots…

For achieving deterministic playback (at least supporting it in the lower level systems), the events are captured and replayed on a specific “step” of the game-loop instead of using timestamps, so a space-bar press polled on the 15th call of the “Update” function is played back right before the 15th “Update” call. For this to work as intended a “fixed delta time” game-loop is ~required, but it is not a hard-coded limitation, since both the record and replay systems support extensions (as seen on the UML diagram), and optionally a delta time can be saved for each step and replayed again as the delta time since the last “Update” call (viola, deterministic replay for “variable delta time” game-loops). Another aid to reliably test stochastic parts of the code, is seed events, usable to capture the seed of a random number generator and reset a given generator to the recorded seed when replaying right before the set game-loop step. Later on if a game or some parts of a game become non-deterministic, I hope, that due to the events are actually being a higher level abstraction, not tied at all specifically to input devices and input events, could be used for replaying non-deterministic game sessions with special game events instead of capturing input (e.g.: disabling a non-deterministic physics system upon replay and relying on “PhysicsDiagnosticEvent” instances).

As I mentioned, the events are serialized to a file for later replay. I chose XML (but could be anything similar) since I already have a lot of code, helpers and tools built for working with this format + I find it quite comfortable (+ a natural choice for .NET). Here is a simple replay file containing only a few key press events:

<?xml version="1.0" encoding="utf-8"?>
<EventStrip>
    <EventsToPlay>
        <RelativeEvent startFrame="10">
            <KeyDiagnosticEvent key="Down" />
        </RelativeEvent>
        <RelativeEvent startFrame="20">
            <KeyDiagnosticEvent key="Down" />
        </RelativeEvent>
        <RelativeEvent startFrame="30">
            <KeyDiagnosticEvent key="Enter" />
        </RelativeEvent>
    </EventsToPlay>
</EventStrip>

To be able to better organize test cases (extract common parts), and to aid the creation of test cases by hand instead of capturing game-play footage (really useful for UI/menu tests), I’ve implemented an “include” attribute for the “EventStrip” type, so that the contents of a replay can be defined in multiple files. Event strips are actually specific event implementations containing a list of “relative” events which can be replayed/started at a given frame relative to the starting frame of the strip itself. This way multiple events can be replayed “parallel”, and it is easy to capture multiple separate event footage and play them combined simultaneously:

<?xml version="1.0" encoding="utf-8"?>
<EventStrip>
    <EventsToPlay>
        <RelativeEvent startFrame="0">
            <EventStrip include="ReplayPlayerOne.xml" />
        </RelativeEvent>
        <RelativeEvent startFrame="10">
            <EventStrip include="ReplayPlayerTwo.xml" />
        </RelativeEvent>
    </EventsToPlay>
</EventStrip>

To be as compact as possible, both memory, disk-space and mental-health wise :D, the basic building block, the “DiagnosticEvent” class is not defined and implemented as a “once-only” event like in most event architectures. It has a duration, and any concrete event implementing it’s interface can decide to span over and be played for multiple “Update” calls. The most common example is a key-press. There are multiple ways to capture and replay a user pressing a key, than later on releasing it. Most common approaches are with their cons. against them:

  1. Save keys in pressed state every single frame as a distinct event. This takes an awful lot of memory and disk-space, and it is close to impossible to edit by hand…
  2. Save two events for each press, an event for pressing and an event for releasing. This is a much much better approach than the first one, but I still hated it’s concept, since any time you wold like to edit an actual key-press, for example make it happen a couple of frames earlier you have to modify two events, and you have to make sure they align well, the frame numbers are correct, the release event is not missing etc… since you may accidentally end up with a replay which presses a key and never releases as a bad example.

The third approach, which I used, and I think is the most feasible solution, is one event which can define how many frames it spans over. As an example a player presses fire (e.g.: left mouse button) and holds it down for 30 frames. That is one event that should be replayed for 30 frames from it’s defined relative starting frame. This way it is easy to make a press take longer or shorter. Also to move around a button press within a test-case, e.g.: to make it happen earlier or later on, only one number has to be modified ;) !

<?xml version="1.0" encoding="utf-8"?>
<EventStrip>
    <EventsToPlay>
        <RelativeEvent startFrame="10">
            <KeyDiagnosticEvent durationInFrames="30" key="Space" />
        </RelativeEvent>
        <RelativeEvent startFrame="20">
            <KeyDiagnosticEvent durationInFrames="10" key="LeftControl" />
        </RelativeEvent>
    </EventsToPlay>
</EventStrip>

Here is the last XML example, a simple check used in the test suite for KREEP, requiring, that the first player (Red) is alive. The game-object for this player is tagged “Player One”, the players are contained within a game-object composition tagged “Players”, and the root component of the game is the “ScreenManager” which doesn’t need more explanation :) .

<?xml version="1.0" encoding="utf-8"?>
<EventStrip>
    <EventsToPlay>
        <RelativeEvent startFrame="0">
            <CheckComponentsDiagnosticEvent>
                <FindComponents name="ScreenManager/Players/Player One">
                    <PropertyChecks>
                        <PropertyCheck name="IsAlive" type="System.Boolean" value="true" />
                    </PropertyChecks>
                </FindComponents>
            </CheckComponentsDiagnosticEvent>
        </RelativeEvent>
    </EventsToPlay>
</EventStrip>

If this check is included for a given frame, and while replaying, on that frame the value of the “IsAlive” boolean property of the game-object is false, or the game-object is not found an exception is generated. That is how I validate things, and hopefully discover early if I mess stuff up with my modifications.

The last big magic trick I added to this whole mix is a test-case runner system. I’m a big “fan” of one-click stuff ( who isn’t :P ;) ? ). I’ve looked around how to do this, and since I’ve been using NUnit for a while now, it was my first trial/choice. Thankfully NUnit has both a command line and a gui based test-execution application, proper result reporting, and a built-in way to programmatically generate test cases runtime! So I’ve built a simple ~application thingy which generates test cases for the NUnit harness from replay files and some meta data ( again in an XML file :D ). When these tests are executed by NUnit, the glue app simply launches a pre-defined application linking my engine, e.g.: KREEP, starting it in “replay” mode and feeding the path of the replay XML file to be loaded and run ( achieved with huge amount of reflection magic and some extra inter-process naughtiness :D ). If no exception occurs during the replay, it shuts down the game, nice and clean, than advances; otherwise the un-handled exception propagates to the application domain border, and the glue app fetches it with some inter-process serialization magic (again) to make NUnit know about the failure situation and cause. All in all the glue app is pretty small, has no dependencies at all besides NUnit, it utilizes some tricks ( a.k.a hacks :P ), but nothing out of the ordinary (actually pretty “common” stuff for core .NET programmers), and as the last and best addition, it will work out of the box without any modifications for any game project which is built upon my framework (no special implementation/preparation is required from the game application either!).

I recorded a little footage with Bandicam to show how this looks like in action. In the first part of the video, I execute three selected test-cases, all passing. Than I edit the third case to add a deliberate failure. This modified case checks the “Energy shield” mutator. It expects, that when a match starts with this mutator set, all players have an active shield, and a laser shot hitting the second player will not score a kill, but the shield will be disabled right afterwards. This expected boolean property (ShieldActive) is changed to “true”, which is obviously wrong, as the shield do wear-off right after the shot, and the test runner signals the failed assertion:

This way, I just have to press a button, and within a couple minutes I know whether a new/modified version of KREEP is ready to be released or not.

Lessons learned, conclusions, plans for the future:
It exceeded my expectations. I know it’s my brain-child and stuff :D, so who else would be pleased if not me, but I do believe it is going to make my life much easier with game releases and patches in the future, and probably will help a lot mid production phase too. It took approximately two work days, recording and creating test-cases, to reach an 80% code coverage on the KREEP code base. This framework is a pretty decent result and I’m happy for making and having it :) ! Also there are a lot of handy utility features already built-in, since I upgraded some parts while I was using it to make it more comfy, but this post is already enormous to talk about all those stuff :D …
A “limitation” which I’m going to fix for my next project is the time it takes to run a full test. It is not yet unbearable or anything ( it takes approximately 5 minutes for KREEP, so a coffee and/or a cup of tea :) ), but for a project with a lengthy single player campaign it could take “too” long, and parallel test-case execution (which NUnit supports) would not help too much (though with save-games it could be helped). A simple antidote to this, on which I’m already working on, is a special game-loop, which “fakes” a fixed 60 times-per-second update rate, passing down 16.66 elapsed milliseconds to game-objects, but actually steps the simulation as fast as possible ( poor CPU :D :P ), so to speak achieving a fast-forward speed-up mode.

This post became pretty lengthy and heavily technical, but I wanted to share my latest big achievement in detail (yes, I love tech-talk…).
Meanwhile the work on the Steam release for KREEP is ongoing. It goes much slower than I expected, so the early march release is in danger currently, but I’m doing the best I can. Not all is lost yet. The paperwork is done, I’m a Steamworks partner, it’s official :), and I’m working on integrating the SteamApi. Also working hard to add extra content for the release (achievements yeah!!!). I hope it’s going to be cool.

Next time I’ll do a more detailed status report on KREEP+Steam…
Stay tuned!

Hello all!

Small update regarding Operation KREEP. I’ve started working on the game again. As I’ve mentioned before, it is number one priority now. When it comes to decision making I’m usually really slooooooooow, but this week I came up with all the must have and all the won’t have time for them (but still would love to have them) features and their designs. I guess the hard time limit worked miraculously. This means the following for the Steam release:

  • It is going to happen in the first week of march.
  • Some new features will be added by than (not only to the Steam version).
  • Most probably a few minor patch may follow, containing new content too besides bug-fixes, if there is even more interest towards the game.

2016_01_10_Steam


As I wrote the last time, I really don’t want to overdo this, but there were some “love to have, but they aren’t going to make it” features when the game was first released, so some new stuff will find it’s way in there, with a proper Steam integration. Here they are, the plans I’ve cooked up and started to implement this week:

  • Achievements (not exclusive for the Steam version).
  • Some new maps.
  • A few extra mutators to stir the existing rules up a bit :).
  • And possibly a “challenge” mode (sort of like a single-player mode).

No time for more sadly. Even these additions will require some overtime during the weekends :D, but I’m excited about extending the game, so I’m going to make it happen! There are still things in the back of my mind what I would love to add (like full controller support besides XInput, or extra map elements like “trap” tiles etc…) but those are going to happen as post-Steam-release updates only.

Stay tuned, will write updates about my progress as I go…
See ya!

Hi there!

Woke up on the 28th of December, checked my mailbox and gazed over a mail with the following subject:
Congratulations, Operation KREEP has been Greenlit!
I was shocked, checked the mail in a hurry, than the greenlight page of KREEP, crossing my fingers and hoping, that it is not a joke or a fake mail :D.
2015_12_29_Greenlit

I have to tell you, I did not expect this at all. I believed, that the game is going to be stuck on greenlight, since it was a really simple game, with a niche target audience and humble results so far. I already moved on to starting the design phase of my next project and preparing technology for having a smoother development process for my upcoming games.

After 133 days on greenlight:
2015_12_29_Stats

I’m super happy now :)!!!

As I’ve mentioned before, I knew it is not a big thing nowadays getting a game on steam, but still, it is like a dream come true. I learned a lot while creating this game, and actually putting the game onto steam will be even more useful from that point of view (both from a technical and a creator perspective).

Hence the name of this entry. I decided, that I’m going to sit back to the “KREEP drawing board” for a little while, and I’m going to make an update for the game, besides the steam integration, to further polish it and fill it with some extra content. I feel like I really have to make the most of it, especially now, since I’m really grateful for all the votes, and for everyone who already bought the game!

I’m still sorting out what I’m going to update and for how long it is going to take. I don’t want to spend too much time on it though to not fall into feature-kreep (pun intended :P), so I’m going to draw a line the same way as I did at the beginning of the project. I’m thinking of two months now. That should be enough to add some juice to Operation KREEP.

As a side note, I’m going to post the “part 2” entry for the testing topic I’ve started last week soon. The implementation is refined, fine-tuned and battle-tested, but I need a couple of days to complete my writing about it. Christmas, family, friends and XCOM kept me busy in the last couple of days :), sry.

I’ll keep you updated on the state of the game.
Thanks again everyone, and I wish you a happy new year!

Hello all!

Haven’t written for a long time, but I’ve been busy working on my “tech”, mostly preparing for my upcoming project. When I started to think through what I would like to write about, I’ve realized, that it is going to be a rather long one, hence the “part 1” in the title, as I’m planning to continue this topic in a week or two.

Now onto some tech talk, but before I go on, I have to tell you, that I’m a BIIIIIG software testing advocate, and this topic will mostly be about it. If you think, that thing is gibberish, do not continue ;)!
So, I’ve been working in the last few weeks on improving my testing work-flow and the tech supporting it. As I’ve probably mentioned before, I have a small but really STABLE code-base, which I nicknamed “Magic Item” (lets call it framework from now on). I use this framework to build games. It is based on XNA, but mostly uses it for rendering, sound and input handling, and provides a bit higher level services, like a game-object framework, animated sprites, collision handling etc., that are common to all games regardless of their type.
I’ve emphasized stable for a good reason. Every single function, that gets into this framework is unit tested and documented. I’m confident, that it is close to impossible to develop software (especially big ones) in a long run without a proper automated regression and sufficient documentation. The way to achieve it, can be argued upon and is somewhat a personal preference (some like unit tests, some do not and prefer more focus on module/functional tests, some like api docs, some do not and prefer more of a feature based high-level documentation not tied to the code), but I hope many agrees, that it is a must (yes I’m being naive, I know).

2015_12_21_NUnit
I love the look of green test results in the morning :D.

2015_12_21_OpenCover
This means I’m pretty thorough :P.

I’ve tried to create a lot of games before, from which many failed due to being too ambitious ideas or me not being persistent enough, but usually I could at least salvage some code from these projects, and build it into this little framework of mine. I’ve been developing the framework this way for years now, and every time I stumbled upon a feature, which could be useful for many games, I properly integrated it, by designing, implementing, testing and documenting the code. It is a small library, since this has always been more of a hobby endeavor, but due to it’s level of polish, working on it or with it to create a game cheers me up!

KREEP Banner

Then came Operation KREEP. This was my second completed game project, but I’ve realized something really important during the development. I had to write a lot of code, specific only to this game, and I think this is pretty shameful, but I had no proper regression to back it up. In the last weeks of development I’ve been doing hours of manual testing just to make sure I did not break anything accidentally. I considered this a failure from a developer perspective, since I perfectly knew what I was doing and still did not prepare, wasting a lot of time. Though I also thought, that unit testing only just a small part of the high-level code in KREEP was not such a bad idea, since it is not the type of testing method which is able to cover a lot of functionality with a small time investment. So in the meantime, I’ve realized, that I have to find a cheap/smart way of testing the actual games I make, in an automatic fashion.

I’ve decided, that unit testing works perfectly for the framework code, but I have to reach a much higher test level for the game projects. My other requirements were, that it has to be stable (as deterministic as possible), simple to automatize, and really easy to create or extend test cases which are able to cover a lot of ground. Yep no worries, this is a trivial task :D!
I’ve been working on this testing method in the last three to four weeks, and I believe I’ve arrived at a really good compromise. I’m not going to go into too much detail in this post (I want to leave some stuff to talk about for next time :)), but here goes the overall design:
The testing system and work-flow is based on “capture and replay”. The framework provides an extensible system to capture events while you are playing and a mirror construct for replaying them (e.g.: like input device events, key presses, mouse moves etc…, but the client can define event types and capture+replay mechanisms). Other than replaying input events, replay files themselves can be extended to be filled with various checks to be done at a certain time or frame, and with some reflection magic, even tiny details can be checked in the game-world. This way, you can capture game-play footage as you are playing with the game, it can be replayed any time later, and it is easy to create test cases and to build a regression out of your recordings by adding various asserts and checks at certain points in them. I did my homework, I know all the positives and short-comings of “capture and replay” based testing. I worked my ass off to come up with a good solution for most of the problems, or at least to make the system work for me, instead of against me.

Most of the implementation is done. I’ve already hooked it up into NUnit, so replay based test cases can be executed with the NUnit runner (I use NUnit for unit testing too, so it was a natural choice), and the whole concept seem to work surprisingly well! I’m really proud of the result :). Testing the final build of my next game will be a breeze :).

In my next post (probably sometime around next week) I’m going to talk about details of my implementation and how I’ve approached the design of the system to achieve my requirements.
Until then, I wish you and your family a merry Christmas, and if I happen to be too busy (or lazy :D) during the holiday and postpone the next post, a happy new year too!

Magic Item Tech

Spidi777 Blog

Hello world!

I’m Tamás Karsai, an aspiring game developer from Hungary. This is the sync. of my game development blog. It is for posting my progress as I discover game-dev land! Hope to make reading about my journey just as much of a roller coaster ride as treading in my shoes.

I've decided to sync. the contents of my game development wordpress blog here on Indie DB, since this a great community and a great website. Stay tuned, see ya!