Showing posts with label battleballoons. Show all posts
Showing posts with label battleballoons. Show all posts

Monday, March 11, 2013

No More Free Time!

So my new year resolution to release one thing every month was a failure. It turns out I have even less free time than I thought. I am afraid it will continue to be so with E3 around the corner and my company, Respawn Entertainment, having "something" planned for it. ;-) I will be dedicating my time on that... and it's something exciting!

For the time being, I will just release what I have done so far. The idea was to make a small Dig Dug type of game. Maybe I will finish it at some point in the near future, but I think that is unlikely with my other commitments right now! Anyway, the download even includes the level editor (diged.exe) if you want to mess with that.

Download: dig-release-20130311.zip

... Or you can just watch the video below!


Monday, January 7, 2013

Almost there... !

Not almost there, actually. :) This is just a progress update.

I hooked up XAudio 2 sound support. It's good to hear those tiny, little feet thumping around again. My wife is helping me make some music now. :) The editor is also quite functional. It has undo/redo, you can place and erase tiles, save and load levels... I don't know what else more you would need! I even added support to rotate the camera, using Maya-like controls (alt + mouse button). You can see it in that screenshot below.


I recently finished adding frustum culling for the rendering. Now I plan on looking into sharing that spatial partitioning code with the physics system (right now collision detection is O(n^2)). Once that is done, I think I can start working on the game...

In other news, I finished a real-life Gnomon course for Maya awhile ago. Below is my finished, programmer art and the reference picture it is meant to be based on. Nothing great, but I did learn the basics of using Maya.


It was a pain making the trek down to Hollywood for class. After work. Twice a week. On top of a fairly heavy homework load. But I think it was worth it. It has given me an insight into what real 3D artists do and a greater appreciation for their work. It has also been a great help for my real work (which I still can't talk about). No, I don't make art, but knowing how Maya works helps with debugging.

My 2013 New Year's resolution is to release "something" around the end of each month (whenever the weekend falls, as that's my only free time). So I plan to release a "game" by the end of January. It won't be Battle Balloons, but something else. So that I can actually reach this goal, I have something simpler in mind (but hopefully still pretty cool). I can't wait to reveal it!

Anyway that's it from me... until the next post!

Friday, October 5, 2012

Editor Is Minimally Functional

I've been doing some more Battle Balloons work in the little pieces of spare time I can scavenge.

The editor is minimally functional now, so I can finally start making the actual game. Too bad I foresee even less free-time in the short-term... too many other things happening at the moment (both work and personal)! So this will probably be the last update for awhile. :(

If you want, give it a spin (not sure if it will work, as it's not seen much testing at all). Just download the .exe below and run ballooned.exe for the editor and balloon.exe for the game. By default the game loads the level, data/game/start.level.lua, but you can specify a different one as a command-line argument.

Good luck!

Download: battle_balloons-release-20121005.zip


Thursday, July 5, 2012

Native GUI editor and a bit more...

Been awhile since the last update, so here it is...

As usual, I'm busy with real work (at Respawn Entertainment), so Battle Balloons has been put on the back burner. :( But I have been occasionally chipping away at it. So far, the major changes have been:

  1. rolling my own 2D physics engine (for multiplayer support later),
  2. Direct3D 11 based renderer (OpenGL ES will still be supported too),
  3. Lua scripting (also replaces YAML as the serialization format), and
  4. a level editor that now uses native GUI controls (only testing with the Win32 C API for now, but I want to support other OS's too).
I really should stop messing around and finish the actual game, but I can't help get distracted with wanting to learn new things. Once this editor is done, I'll get right to it!


P.S. Also, Abbie (the community manager at Respawn) did an interview of me here!

Saturday, September 10, 2011

WIP on placeable tiles


Quick video on initial placeable stuff (with snapping) for the level editor. I have been messing around with engine/low-level stuff for such a long time now, it's refreshing to see signs of my game returning again! Left to do is code to merge tile meshes together (no seams) and hooking it up to my barely-tested output serializer.

In unrelated news, my fiance wanted me to make a simple website for our wedding. So I took the opportunity to learn and mess with the Google App Engine and Go programming language. You can go to it here, but there is not much to see, unless you have a Google account that is actually invited. :(

What I can say though is the experience working with the Google App Engine has been pleasant. Quite easy and fast to get things up and running (compared to Java EE).

UPDATE: I put up a newer vid showing actual static boxes being placed! That's pretty much all I could get done with the little spare time I had for the weekend. :(

Saturday, August 20, 2011

Scrolly thingy


Nothing special today: just a scrollable list box for selecting types (to place on the level). It has been interesting dabbling in implementing my own UI controls, but I am also happy I will be moving on to actual editor things now!

So apparently Ludum Dare (LD48 for short) is on right now (this weekend). For those not familiar, it is a competition to quickly create games in 48 hours. I have always wanted to participate in one of these, but never seem to be free on the weekends it's on...

Maybe I can show this off at a LD17520. Yep, that's right - according to the revision history, I have been working on Battle Balloons for two years! To be fair, in that time I have also been busy working on releasing BioShock 2 and soon-to-be-released The Darkness II. These commercial titles put the food on the table, so they have always taken priority. :)

Anyway, time to drive to Toronto to visit some buddies for the weekend!

Sunday, July 31, 2011

Preliminary level editor work

Decided to do some long-overdue work on Battle Balloons this long weekend. Been beaching it up every single weekend before this, so a weekend indoors is a nice change (along with fattening myself up on the ribfest outside!).

The pieces for the UI toolkit (which run in-game) are beginning to come together. I have a bunch of windows you can drag around and overlap. Font rendering could be better, but this will suffice for now. The editor is going to be super-simple; much like the VVVVVV editor actually (which I have been messing around with). If I ever did want something more, I would probably use a real UI toolkit (maybe QT) rather than write my own.

Anyway, just thought I would report on some Battle Balloony stuff for once, rather than The Darkness II (which is coming along real swell - heaps of polish going in and more to come... it's gonna be awesome!).

One more day to go... let's see what I can cook up!

Basic windows (taken from an OS X build)!


UPDATE: Made a bit more progress today. Mainly just a list box and blinding/folding windows. Video below (from a Windows build this time).


Sunday, July 17, 2011

San Diego Comic-Con


If anyone is going to be in San Diego this month for Comic-Con, we have been furiously polishing a playable build of The Darkness II that will be showing there... so please check it out! It will be at booth #2629. There will also be free copies of The Darkness II: Confessions comic and a chance to win a sweet Darkling figurine (pictured above)! Take a look at the 2K blog for more details.

Anyway, hope you enjoy playing our demo! :)

P.S. This was the first weekend in a long time I had to myself. Did a bit more editor work for Battle Balloons. I have the UI framework done and working on the "look" now - aiming for something like that minimalist window manager, Blackbox. Loved using that thing back in my Linux days...

Hard to find an original screenshot, but Blackbox kind of looked like this.


Saturday, May 28, 2011

Morphological Anti-Aliasing (MLAA) with OpenGL ES 2 & GLSL

Managed to squeeze most of this in on the weekend, just before flying off to the Cayman Islands for some R & R... :)

The Battle Balloons rendering system now features morphological anti-aliasing (MLAA)! It is an anti-aliasing technique that works by finding vertical & horizontal edges and blending them based on the edge's length and end point conditions. The original paper by Alexander Reshetov explains this in more detail. It includes source code, but is apparently too slow for real-time rendering. God of War III is the first title I know to have taken this technique and optimized it to work in real-time (on the PlayStation 3). Jorge Jimenez and friends later published another real-time approach with DirectX/HLSL (officially called Jimenez's MLAA), which I have based my own OpenGL/GLSL implementation on.

This is actually a distraction I succumbed to while working on the level editor. It still has some bugs to iron out, but soon it will be out of the way and I can return to level editor land!

On a related note, I just found out about Timothy Lottes' FXAA technique yesterday at work. This looks even better, but I think I will hold off on implementing that... for now. Too many other things I need to get on with first.

Without MLAA: Lots of ugly, hard edges.

With MLAA: Hard edges blended/blurred together.


Saturday, November 27, 2010

Tile-Based Mesh Generator

I put together a quick prototype for a tile-based mesh generator for Battle Balloons today. It is getting increasingly cumbersome to create levels by manually typing out YAML properties for each level, so I am now focusing on speeding up the content-creation process.

This came about from my latest programming hiccup, which was related to depth buffering. I originally thought I could simply stack my tile meshes (rectangular boxes) together as-is, but when I tried it on a scrolling level, I was seeing seams flickering in and out, along the tile boundaries. It was hard to get a screenshot, but here is one I caught while inspecting the normal render buffer (or render target for D3D folks):


The teal-coloured line on the left is what I was crying about! Teal represents normals pointing left; I store normals in RGB, mapping the range [-1,1] to the range [0,1], use a right-handed coordinate system and camera facing down negative Z. So it seems like the left face of those particular tile meshes were bleeding through. Note that I had back-face culling turned off at the time. After some searching, reading & head-scratching, I figured out the cause...

I naively assumed the front (camera-facing) faces would cover up the left/right faces behind. But this would only be correct most of the time. When depth sampling (which presumably happens at the centre of each pixel) hit the exact edge of a left face, that face would receive a depth value equal to what the front-face would later get - and so begins the gruesome z-fight between left-face and front-face over that one pixel. :)

To confirm this theory, I put in some quick hacks in my vertex shader to snap all vertex positions (after transformation to clip space) to the closest pixel corner. For a grid of axis-aligned meshes like my scene, this ensured no pixels were ever centred over the edge of any left faces. This did fix the seams, but is not a good, general solution (only works for axis-aligned boxes).

It makes complete sense now... but not immediately obvious to me in the beginning!

Learning my lesson, I now weld tile meshes together - any overlapping/shared faces are hidden. My tile meshes group their triangles into sections (one section for each face) and I can selectively turn off sections for a particular mesh instance. For now, the tile generator just handles all that cumbersome work of turning off the appropriate face if there is a neighbouring tile. But I plan on retro-fitting more content-creation goodness later.

Here's a video of the latest build with some scrolling action (and no seams!). The generator is being used for the floating islands:

Wednesday, November 17, 2010

Serialisable Enums in C++ Using Templates and the Preprocessor

I have been too busy at work lately to spend any significant time on Battle Balloons. On the upside, it has been very interesting late-night work delving deep into console graphics (both Microsoft Xbox 360 and Sony PlayStation 3)!

Anyway, here's a little bit of unrelated C++ hackery I use in Battle Ballons code. It allows you to declare an enum once (even within a class) and have it automatically convertible to/from strings - all without any auto-generation scripts. I use it to allow my config files (specified in YAML) to reference C++ enums defined in code. Super-useful since Battle Balloons is heavily data-driven!

Common implementations out there seem to use code-generators or multiple #includes of the same file. This is similar to the latter, except I pass in the list of enums twice (automated for you through a small macro).

The template class is not entirely necessary - you could easily embed the same code into the macro. But the big advantage the template has here is that you can actually step through the code in a debugger (at least in Visual Studio you can)!

More details in the code snippets below. It is rough and references project-specific code not shown, but the general concept is there and should be possible to reproduce.

First, a quick example on how it is used:
ENUM_CLASS(TestEnum, TE_A, TE_B = 2, TE_C, TE_D = 6);

void testEnum
{
    ASSERT(TE_A == 0);
    ASSERT(TE_B == 2);
    ASSERT(TE_C == 3);
    ASSERT(TE_D == 6);
    ASSERT(MAX_TestEnum == 7);

    TestEnum te;
    ASSERT(te == TestEnum::max());
    ASSERT(te == MAX_TestEnum);

    te.setFromString("TE_A");
    ASSERT(te == TE_A);

    te.setFromString("TE_B");
    ASSERT(te == TE_B);

    ASSERT(TestEnum::getEnum("TE_C") == TE_C);
    ASSERT(TestEnum::getString(TE_D) == "TE_D");
}

Header file (.h):
#define ENUM_CLASS(Name, ...)   enum E##Name { __VA_ARGS__, MAX_##Name };                           \
                                struct Get##Name##EnumString                                        \
                                {                                                                   \
                                    static const Char *get()                                        \
                                    {                                                               \
                                        return #__VA_ARGS__ ", MAX_" #Name;                         \
                                    }                                                               \
                                };                                                                  \
                                typedef EnumT Name

void tokeniseEnumString(String *enumArray, Size enumArrayCapacity, const String &enumString);

template <class Enum, const Size MAX_ENUM, class GetEnumString>
class EnumT : public EnumBase
{
public:
    static const String &getString(Size i)
    {
        ASSERT(i <= MAX_ENUM);
        return enumNames()[i];
    }

    static Enum getEnum(const String &s)
    {
        for (Size i = 0; i < MAX_ENUM; ++i)
        {
            if (enumNames()[i] == s)
                return static_cast(i);
        }
        return static_cast<Enum>(MAX_ENUM);
    }

    static Size max() { return MAX_ENUM; }

    EnumT() : m_value(static_cast<Enum>(MAX_ENUM)) {}
    EnumT(Size value) : m_value(static_cast<Enum>(value)) {}
    EnumT(Enum value) : m_value(value) {}

    EnumT &operator=(Enum e) { m_value = e; return *this; }
    operator Enum() const { return m_value; } 

    virtual bool setFromString(const String &s) { m_value = getEnum(s); return m_value != MAX_ENUM; }
    const Char *str() const { return *getString(m_value); }

private:
    static String *enumNames()
    {
        static bool s_init = false;
        static String s_enumNames[MAX_ENUM + 1];
        if (!s_init)
        {
            s_init = true;
            tokeniseEnumString(s_enumNames, MAX_ENUM + 1, GetEnumString::get());
        }
        return s_enumNames;
    }

    Enum m_value;
};

Implementation file (.cpp), which is is just the tokenising function that splits the enum declaration string (passed by the ENUM_CLASS macro function) into its individual names (and also respecting explicit number values, if given). This is only called once (on first use) and the result is cached off for all future calls:
void tokeniseEnumString(String *enumArray, Size enumArrayCapacity, const String &enumString)
{
    Size enumArraySize = 0;

    Size cIndex = 0;
    while(cIndex < enumString.len())
    {
        String name;
        bool hasExplicitValue = false;

        for (; cIndex < enumString.len(); ++cIndex)
        {
            const Char nameChar = enumString[cIndex];

            if (nameChar == ',')
            {
                ++cIndex;
                break;
            }

            if (nameChar == '=')
            {
                hasExplicitValue = true;
                ++cIndex;
                break;
            }

            if (std::isspace(nameChar))
                continue;

            name += nameChar;
        }

        if (hasExplicitValue)
        {
            String numberStr;

            for (; cIndex < enumString.len(); ++cIndex)
            {
                const Char numberChar = enumString[cIndex];

                if (std::isspace(numberChar))
                    continue;

                if (numberChar == ',')
                {
                    ++cIndex;
                    break;
                }

                ASSERT(std::isdigit(numberChar));
                numberStr += numberChar;
            }

            Int intValue;
            ASSERT(numberStr.toInt(intValue));
            ASSERT(intValue >= 0);

            const Size value = static_cast(intValue);
            ASSERT(value >= enumArraySize);
            while (enumArraySize < value)
                ++enumArraySize;
        }

        enumArray[enumArraySize] = name;
        ++enumArraySize;
    }

    ASSERT(enumArraySize == enumArrayCapacity);
}

Thursday, October 28, 2010

Performance Work

So I decided to take a peek at performance lately. Although it was not bad (it was still capping out at 60 fps), I was still curious to see how I was spending my time. So I hooked up some timers and it turned out my occlusion tests were taking up around 50% of frame time (the other 50% roughly going to rendering - but that would include time waiting for vsync)! Some simple early returns using spherical tests brought it back down to 10% of frame time - a simple fix for an unexpected problem!

On top of this, I added some face merging/simplification code for my sprite-to-mesh generator. Again, not necessary - it was just for fun. Previously, I was generating vertices for each pixel from the source image, and using vertex colours to colour them. Ugly, I know, but dead simple and it worked.

Anyway, after a week of banging my head against a wall coming up with a working algorithm, I finally have results! It uses a fairly simple heuristic: try form the biggest face along the local horizontal (U-axis) and with that merged face, try form the biggest face along the local vertical (V-axis). It will not always find the most optimal result, but it is good enough and still a massive improvement from before.

This new mesh structure also means I cannot colour with vertex colours anymore. So colouring is now done through texture lookups of the original, source image. The texture is mapped in a following pass, once the simplified mesh has been generated.

Check out the images below. Happiness!

I do not have any hard performance numbers to show though. I think these changes would only be evident in GPU performance (not CPU), and I actually don't have any tools installed to measure that. I will hunt for some in the near future, but any recommendations in the meantime would be highly appreciated!

UPDATE: I realised this a few days after and thought I should note it here in case anyone tries it. The face merging algorithm described is bad. It creates T-junctions, which will produce rendering artifacts. The approach can be modified to correct this, but it is low on my priorities (I am not vertex-bound at the moment).

Before - no simplification

After - with simplification!

Saturday, October 23, 2010

Nearly Done With New Title Screen

Decided to put in some time to implement a proper physics-based character controller for walking. It was a bit tricky... but I'm fairly happy with the results. Hooked up a basic SFX and music system too. Just a bit more polish left and on to more things! Build is available for download here too (you can try move the players around if you want). Music is from Jorge Boscan and sound effects generated by as3sfxr!

Friday, October 1, 2010

It's A Cold Night To Be Out...

Here is a really brief video of what I have been up to. It's the new title screen. It might not seem like much, but a whole heap of work has gone into this under the hood. There's the new deferred rendering, new behaviour tree for AI (a patrol behaviour is driving the dog back & forth), reworked serialization system, and just generally much, much, much cleaner code. It took awhile... but I think it will show its true worth in the future. More updates to come very soon!

If you want, you can download the build too. I have only tested this on like two computers though. ;-)

UPDATED: Changed the video (and download)... now with actual balloons! :)


Friday, September 24, 2010

Reconstructing View Space Position from Depth in OpenGL ES 2.0

There is a lot of information scattered around the Internet on this (some of which seems wrong). Here is some rough code for my solution to the problem. I only just got this working, so I hope it is correct... you have been warned!

First, I will describe the inputs:

  • winPos - Pixel position (from gl_FragCoord.xy).
  • winSize - Size of window in pixels.
  • depthSample - Raw depth value from the depth texture (should be in the range of [0, 1]).
  • nearFar - Distances of the near and far planes.
  • u_top, u_right - Top and right limits of the near plane.

For u_top and u_right, I derive it from my vertical field of view angle and aspect ratio (width / height) like so (C++):
    m_top = m_near * Math::tan(0.5f * m_verticalFov);
    m_right = m_top * m_display->aspectRatio();
Given all that, here is the GLSL function that will return the view space position for the given pixel position:
vec3 viewSpacePos(vec2 winPos, vec2 winSize, vec4 depthSample, vec2 nearFar)
{
    vec3 position;

    float depth = depthSample.x;
    position.z = -nearFar.x / (nearFar.y - (depth * (nearFar.y - nearFar.x))) * nearFar.y;

    position.x = (((winPos.x / winSize.x) * 2.0) - 1.0) * u_right;
    position.y = (((winPos.y / winSize.y) * 2.0) - 1.0) * u_top;

    float scale = -position.z / nearFar.x;
    position.x *= scale;
    position.y *= scale;

    return position;
}
Hope this helps someone out there! It might be best you try derive it yourself too, so you can debug it (if you ever need to)... :)

UPDATE: Made small correction to how scale was calculated. Oops!

Sunday, August 29, 2010

Deferred Rendering Done!



Just a quick update - finally finished the deferred rendering system for Battle Balloons! Guerilla Games has a good presentation for Killzone 2 on the theory behind it - but mine is not as advanced. Not much to show as it's pretty much all under-the-hood at the moment. But this excites me because I no longer need to worry about how to limit the number of lights in the game - they can now be practically unlimited. I went with a fairly simple approach:
  1. the scene normals are rendered in RGB as-is (if it's good enough precision for Insomniac Games' Resistance 2, then it's good enough for me!),
  2. pixel world position is derived from the 2D screen co-ordinates and depth buffer value, and
  3. lighting happens in two stages: a spherical mesh is first rendered for each light onto the stencil buffer and the light shading is then calculated for each pixel not masked out by the stencil.
In the process of doing so I also removed all legacy, fixed-functionality OpenGL code. Everything is now pretty-much OpenGL ES v2.0 compliant. Now with this out of the way, it is on to adding networking support; the last, major, technical hurdle for this project! :)

Saturday, July 17, 2010

Approaching Feature-Complete...

I've been banging away at Battle Balloons in my spare time lately and here's the latest progress! I have most of the features I need now (but still quite a few more to add...). The code is starting to look a bit messy though, so it will just be clean-up work at this point. No more updates for awhile. :( Enjoy the video! You can also download the build (for Windows) and try it out if you want.

Saturday, June 12, 2010

Battle Balloons Is Back!

Well, here's what I have been hammering away at lately. It was originally meant to be an entry for the TIGSource Assemblee Competition but real-life came and the deadline was missed. Since then, I have made my own art and after furthering tinkering, this is the result so far.


Source for my base library is available at my Mercurial repository: http://hg.epicfinalboss.com/glutinous/src/tip/base/

The Windows binaries used for the video are also downloadable there.

Sunday, May 11, 2008

A Bit of Work on Battle Balloons

I've been getting back into doing work on my Balloon Fight clone again. I decided to rename it to Battle Balloons, just to avoid infringing any potential naming legalities. I kind of started getting back into this as an experiment to see if I could avoid writing a game in C++. I battle it out with C++ all day at work, so I would prefer something a little nicer when writing my own hobby projects. :) Kind of worrying I am spending what little time I have on this too. More late hours. I wish sleep was optional.

Basically, it's written in a mix of C and Ruby. The C is used for accessing the SDL library, which is a portable gaming library that works on many operating systems including Windows, OS X, and Linux. The rest I intend to be all Ruby. I'll jump back into C as needed.

As for the game itself, I don't really have much to show at the moment. I have just been working on infrastructure so far. :/ If you're a curious coder, then you can take a peek at what I've done so far at: http://code.google.com/p/battleballoons/

Anyway, time for some Battlestar Galactica... and then sleep. :)

Friday, August 3, 2007

Quick Update

Have not really had time to do much on this site. Even though it is nearly done (just need to clean up the code a bit more and also the side bar on the right there). I will soon hopefully. :) Anyway, I spent this morning uploading a short clip of a game I am making, Balloon Fight. I have been working on it in the little spare time I have (when I am not working on Fury, which is a real game). Speaking of which, we will be releasing the game VERY SOON (early October), which means I will have even less time for doing other things... oh well. -_-

Anyway, here's the YouTube video (http://www.youtube.com/watch?v=WtQfQoILXvg):