• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
  • entries
    59
  • comments
    74
  • views
    43728

Entries in this blog

yckx

Diversions

I actually did some coding yesterday and today. GitHub says it's been about six weeks since I've committed any changes. I blame Batman: Arkham City, Dark Souls, Assassin's Creed: Revelations and Star Wars: Tho Old Republic beta weekends, and various holiday preparations. I imagine I won't get any more real coding time in until the second week of January. Regardless of any progress I can point to, I'm still continually thinking about it, so it's not abandoned by any means, just simmering on the back burner at the moment.
yckx
I've thought all day about how to compile all the maze meshes into one static vertex buffer. Right now, each corner and straight section is its own mesh, which gets transformed every frame. That's 1632 needless transformations. The issue is how and where to create an ID3D11Buffer* initialized with the pretransformed verts of all the wall meshes. The Maze and GFXDevice classes know nothing about each other, and I don't want them to. Passing a vector of entities to the Renderer (which owns the GFXDevice), or vice versa, feels kludgy--I don't want to have to call the renderer when I load a new maze before I actually need to draw it.

While typing the above, I thought of doing it in the MeshCache. It makes decent sense--the Cache creates, stores and fills requests for mesh data. It will require some small interface redesign, but it's doable. Why didn't I think of this before? I wish I'd come to this realization before 1am. My coding life is filled with eureka moments immediately after powering down the pc or as I'm turning out the light. Or even moments before I would have fallen asleep had the epiphany not occurred. And I'm still working on resuming a normal sleep schedule; so while I could stay up and implement it (I'm exhausted by my damnable sleep patterns, but not really feeling tired at the moment), I really should take a sedative and go to bed.

There's (almost) always tomorrow ;)
yckx

Return of the Cage

It took longer than I'd expected to return to this point, but here I am:

gallery_37843_205_33069.png

And to be honest, I don't care that it's taken me a while. I'm having fun, I'm happy and satisfied with the improved quality of (most of) my code, and I have mo deadline to meet. Sure, I'd love to see this project reach a completed state, but there are days when it feels like working on DRON is the only thing keeping me focused enough to maintain mental stability. None of my other hobbies or interests currently provide that comfort, so I look to the eventual completion of this project with some small trepidation ;)

I still need to get rid of that ungodly flat shader. That's high on my list, but I also want to get the maze mesh into a default buffer since it doesn't need to be updated per frame. Also, I'd like to get scripting set up so that I can throw the maze definition parsing (it's defined as a char string for easy editing) and maze generation code into a Lua script.
yckx

Progress!

I've taken a lot of time and care over the rendering code the last several days. I'm also using DirectXMath SIMD optimized datatypes and functions. Memory alignment is something I'd never really dealt with before, and it took a bit of time to get used to, but things are going swimmingly now.

The below screenshot doesn't look like much, but it shows a few things:

gallery_37843_205_18761.png

The active GameState passes a std::vector of Entities to the Renderer, which sorts all the entities with a RenderableComponent into batches, and then renders each batch (currently with a crappy flat-color shader). Color and transformation are instanced data. There are multiple instances of two meshes: a straight wall section and a right-angle wall section. One wall section is colored differently, and the bottom wall section is non-uniformly scaled to stretch from one angle to the other.

Eventually I'll transform the maze bits once at the beginning and store the transformed data in a larger buffer, since it's static. But now it serves a useful purpose letting me test the Renderer changes as I make them.

I wish I were more productive with my time, and had more time to spend, but I've decided to choose sedatives over coding on my sleepless nights (in the interest of promoting good mental health), and my days are surprisingly filled with other things that need to be done while the rest of the world is predisposed to social interaction.
yckx

Abstraction

I've spent my coding time the last couple of days refactoring my Renderer class. Up until this point, all the D3D code was in Renderer. It worked, but it was difficult to easily pick out what was going on when looking at the code. So I decided to create wrapper classes for the various D3D11 interfaces I was using. My code is much cleaner now, and I can more easily see and isolate what's being done where.

It's not a complete refactor yet--there are still a couple vertex buffers I need to deal with, and some minor bits of the draw routine. But I'm pleased with it. Also, there's some DirectXMath library stuff still going on in the Renderer class that I'm not sure if I want to try to encapsulate or not. I'd like to be able to completely encapsulate/abstract away DrectX from the Renderer class, but I'd just have to replace it with another math library. I'm not convinced it's worth the effort.

I hope to have something worthy of screenshotting soon....
yckx

Design Flaw

I've realized a design flaw in my entity/component system: I don't have a good way to actually initialize component data! Looky here:
[source lang="cpp"]
Entity e = entity_system.CreateNewEntity();
entity_system.AttachComponent( e, COMPONENT_XFORM );
/* e can now have position, scale and rotation, but how to initialize it? It
* feels kludgy to dispatch a message or fire an event *after*
* creating/attaching the component to initialize it, so I'm thinking of adding
* a parameter to AttachComponent() to pass a struct of initialization data.
* I don't really want to derive all component data structs from a base type,
* but templates don't feel right either. Le sigh...
*/
[/source]I guess I'll spend some time pondering my approach.

Edit:
For the moment, I've changed my approach somewhat, to this:
[source lang="cpp"]
Entity entity = entity_system.CreateNewEntity();
BaseComponent* bc = entity_system.CreateComponent( COMPONENT_RENDERABLE );
dynamic_cast< RenderableComponent* >( bc )->SetData( data );
entity_system.AttachComponent( test_entity, bc );
[/source]I don't really like the idea of handing out pointers to components, but it is workable enough for me to move forward until I can come up with a cleaner solution. I guess what I really need to do is something like [font="Lucida Sans Unicode"]entity_system.CreateAndAttachComponent( entity, COMPONENT_TYPE, component_type_data_struct )[/font]. After thinking about it, it really seems the cleanest way from an interface perspective. Unless someone has a better idea.

But it's 1a.m. and I really need to try to resume a more normal sleep schedule or I'm going to sleep through my early morning Important Doctor's Appointment on Monday. So no more coding for me tonight :(
yckx

Square One

I had coded myself into a corner a while back, not being able to effectively manage the ghosts. Also, I didn't like how some sections of my code were working out. It became evident that it would be easier to start over than to try to shoehorn fixes into the existing code. Well, I actually can use much of the existing code, but it was easier to restructure and refactor from scratch rather than directly modifying the existing code. So I started a new project and created a cleaner design, copying and pasting much of the existing code, but leaving behind large chunks of it as well. I also took the time to create an entity/component system, rethink my Lua strategy, and convert my renderer to D3D 11. This is, oh, perhaps the eighth or ninth time I've done this since I came up with the game idea back in 2003.

There's a reason the guys on the fora tell newbs to start with Pong. But I'm stubborn and I'm having fun, so fie on all detractors :D

And in the spirit of starting over:
gallery_37843_205_2614.png
yckx
I code in a vacuum. I learned C++ from books and the 'Net, never took a class, and all my friends are humanities types. So I can't get any kind of RW peer review. That's where you come in.

I've taken a first pass at an entity/component system. I've neither written nor used such a system before, and while this code compiles and preliminary tests produce expected results, I suspect there may be pitfalls in my design. Also, my brain is a little fried at the moment.

The approach is that entities are integer ids, components only contain data, and that other systems (logic, input, collision, etc.) use and act on components relevant to their purview. I've liberally adopted code from and been inspired by numerous websites and -pages over the last couple days, and I'm too close and too frazzled to it to spot trouble spots. If you react with a WTF please let me know. Thank you.

ComponentTypes.hpp, incomplete--just a few to test out the system
[spoiler]
[source lang="cpp"]
#ifndef _COMPONENT_TYPES_HPP_
#define _COMPONENT_TYPES_HPP_

enum COMPONENT_TYPE
{
COMPONENT_CAMERA,
COMPONENT_MOVABLE,
COMPONENT_RENDERABLE,
COMPONENT_XFORM
};

#endif // _COMPONENT_TYPES_HPP_
[/source]
[/spoiler]

BaseComponent.hpp
[spoiler]
[source lang="cpp"]
#ifndef _BASE_COMPONENT_HPP_
#define _BASE_COMPONENT_HPP_

#include "ComponentTypes.hpp"
#include "../EntitySystem.hpp"

typedef unsigned int Entity;

/*********************************************
* BaseComponent
* This simply provides GetType()
* and a common base class, of course ;)
*/
class BaseComponent
{
public:
virtual COMPONENT_TYPE GetType() const = 0;
};

/**********************************************************
* AutoRegistrar< T >
* This auto-registers Create(), which creates a new T*,
* with the EntitySystem.
*/
template< class T >
struct AutoRegistrar
{
AutoRegistrar()
{ EntitySystem::Register( TplComponent< T >::GetTypeStatic(), AutoRegistrar< T >::Create ); }
static BaseComponent* Create() { return new T; }
};

/***********************************************
* TplComponent< T >
* Each component T derives from this class.
*/
template< class T >
class TplComponent : public BaseComponent
{
public:
TplComponent() { }
virtual COMPONENT_TYPE GetType() const { return _type; }
static COMPONENT_TYPE GetTypeStatic() { return _type; }

private:
static COMPONENT_TYPE _type;
static AutoRegistrar< T > _registrar;
};

template< class T > AutoRegistrar< T > TplComponent< T >::_registrar;

#endif //_BASE_COMPONENT_HPP_
[/source]
[/spoiler]

XformComponent.hpp, sample component
[spoiler]
[source lang="cpp"]
#ifndef _XFORM_COMPONENT_HPP_
#define _XFORM_COMPONENT_HPP_

#include "BaseComponent.hpp"
#include
#include

struct XformData
{
XMFLOAT4 _position;
XMFLOAT4 _scale;
XMFLOAT4 _rotation;
};

class XformComponent : public TplComponent< XformComponent >
{
public:
XformData& Data() const { return _data; }

private:
XformData _data;
};

COMPONENT_TYPE TplComponent< XformComponent >::_type = COMPONENT_XFORM;

#endif //_XFORM_COMPONENT_HPP_
[/source]
[/spoiler]

EntitySystem.hpp
[spoiler]
[source lang="cpp"]
#ifndef _ENTITY_SYSTEM_HPP_
#define _ENTITY_SYSTEM_HPP_

#include
#include

enum COMPONENT_TYPE;
typedef unsigned int Entity;

class BaseComponent;
class EntitySystem
{
public:
EntitySystem() { }
~EntitySystem();

/**************************************************
* Returns a new Entity with no attached components
* If there are any entites in the dead entities list
* it will reuse one of those.
*/
Entity CreateNewEntity();

/**************************************************
* Deletes all components attached to the Entity,
* then moves the entity from the live entities list
* to the dead entities list.
*/
void DestroyEntity( Entity );

/**************************************************
* Checks to ensure the entity does not already
* have a COMPONENT_TYPE component attached.
* Then, creates a new COMPONENT_TYPE component
* and attaches it to the Entity.
*/
void AttachComponent( Entity, COMPONENT_TYPE );

/**************************************************
* Populates the vector with all entities
* that have a component of COMPONENT_TYPE attached.
*/
void GetEntitiesByComponentType( COMPONENT_TYPE, std::vector< Entity >& );

/**************************************************
* Populates the vector with all components
* attached to the given Entity.
*/
void GetEntityComponents( Entity, std::vector< BaseComponent* >& );

/**************************************************
* Registers a component creation function and
* associates it with COMPONENT_TYPE.
*/
typedef BaseComponent* ( *ComponentCreator )();
static void Register( COMPONENT_TYPE, ComponentCreator );

private:
// Prevent copying and assignment
EntitySystem( const EntitySystem& );
EntitySystem& operator=( const EntitySystem& );

BaseComponent* CreateNewComponent( COMPONENT_TYPE );

/**************************************************
* I don't like these std::map typedef names, but
* they work, and I can't think of anything better.
*/
typedef std::vector< Entity > EntityVector;
typedef std::vector< BaseComponent* > BaseComponentPtrVector;
typedef std::map< Entity, BaseComponentPtrVector* > EntityComponentMap;
typedef std::map< COMPONENT_TYPE, EntityVector* > ComponentTypeEntityMap;
typedef std::map< COMPONENT_TYPE, ComponentCreator > CreateComponentMap;

EntityVector _entities;
EntityVector _dead_entities;
EntityComponentMap _entity_map;
ComponentTypeEntityMap _component_type_map;
CreateComponentMap _create_component_map;
};

#endif //_ENTITY_SYSTEM_HPP_
[/source]
[/spoiler]
yckx
I haven't worked on anything in a while because a co-worker of one of my housemates lent me Demon's Souls. That's an addictive game.

I tore myself away from the PS3 this weekend just long enough to finish this latest little mini-project: using Lua as a data file format. Here's my minimal test file:


DRONMesh {
name = "Triangle",
verts = {
{ 0.0, 0.5, 0.5 },
{ 0.5, -0.5, 0.5 },
{ -0.5, -0.5, 0.5 }
},
tris = {
{ 0, 1, 2 }
}
}

I said it was pretty minimal ;)

Anyway, DRONMesh is a lua function that creates a new Mesh object, populates it with the data given in the table, and registers it with the resource manager. I need to expand it to handle materials, bones and whatnot, but I'm happy that I got it working. I haven't stress tested it in any way, but all the models in my game are fairly small (< 100 vertices), so I'm not too worried about long load times.
yckx
I'm having to rethink my approach a bit--if I expose a struct, say a Vertex, to Lua that has something like an XMFLOAT* or D3DXVECTOR* member, I get an access violation when I try to instantiate one from Lua. Took me a bit to realize that was the issue. I'm not sure I can make it work without going to plain old float members. I guess I can write a function on the C++ side that handles mesh creation based on a Lua table, but I was really hoping to be able to do it all in the script.
yckx
I haven't been doing much coding on the game lately. I've been trying to shorten my to-read stack, and just haven't felt like getting on the computer too much. Also, the house took a vacation to my parents' home last week, so I was without a dev machine. When I have been at the pc, I've been learning Blender, which is significantly different than any other modeling software I've used. It's frustrating to know that something can be done and yet not be able to determine how in an interface that only makes sense after learning it; but after watching several video tutorials it's beginning to come together. I can understand why it's set up like it is, but I apparently don't think the way the UI creator does, so any new thing I want to do requires another Google search, since I'm taking the approach of How do I do what I want to do instead of working through tutorials in any logical order ;)

So I've made a simple Pac-Man player model, am using bones to animate it, have applied materials, etc. Then I exported it as an X file. Taking a look at it revealed that my 94-vertex model suddenly had 546 vertices! Some quick investigation revealed that each vertex was repeated for each triangle that used it.

I'd been considering what file format to use for the game's models for some time, and PiL (bn)(amazon) has a bit about structuring data files in such a way that they can be run as Lua programs. I like the idea of this, and so I've decided to go this route. While I'm at it, I thought I'd write an optimizer/converter in Lua that would take an X file and strip out all those extraneous vertices, re-index the triangles and spit out a model file that could be run by the Lua vm. Doing this will give me more experience with using Lua, to which I'm still quite new.

The optimization routines are nearly done--there are still some issues with handling the faces, but I should be able to finish it tonight. After that, I'm on another hiatus as I need to return to my parents' for a week or so due to a death in the family.
yckx

Fun with SWIG

I've been exploring the use of SWIG as a Lua binding for the last day or so, and I've found I kinda like it, which surprised me. It took me a while to figure out how to use it--it appeared at first that the bindings had to be compiled into DLL modules before being used, which is cool as a feature, but absurd as a necessity. After looking around a bit, I found this GD.net forum thread, in which owl mentions the [font="Lucida Console"]luaopen_*()[/font] function that SWIG creates, allowing you to load the module from within your app. Owl gets a thanks and a +1 for that.

After that, I was toying with what I could do, and how. My initial attempt to expose objects to Lua was to use a getter function, so I could do something like [font="Lucida Console"]app = yckx.GetApp()[/font] in Lua. But it was a dirty hack and felt kludgy. I disliked writing it, much less using it. After some more Google-fu I found this mailing list thread, which solved the problem much more elegantly.

So, yay! I'm making what feels like real progress. But finding these two bits of information really tells me one thing: it's going to take a while to discover the ins-and-outs of SWIG.
yckx

My Glorious Return

I was gone longer than I'd expected to be. I spent less than a week at my parents', working the honey. Fun times. But when I returned home, I had no desire to do anything with my computer. Just powering it on felt like a chore, and the thought of actually sitting down at the keyboard was detestable. I wanted to want to code and play Rift, but I didn't. I even unsubbed from Rift, which is a game I really enjoy playing. Now, I'm not sure if I'm going to resub any time soon.

So I spent my new-found free time this past month reading and playing guitar. It was cathartic.

Over the weekend, the idea of powering on my pc grew less distateful, and today I'm actually sitting down, listening to Pandora, and typing out this journal entry. And I don't dislike the experience, which is a good thing.

I hadn't stopped thinking about Pac-Hedron, however, and what I wanted to do on it once I came back to coding. I've decided to take a look at SWIG. I don't really like the pre-proces approach it takes, but a few people on GD.net whom I respect and whose journals I follow seem to enjoy it and do neat-o-keen things with it, so I figured I shouldn't dismiss it without giving it a try.

So that's what I'll be doing over the next day or two.
yckx

Downtime

Won't be coding for the next week. I'm going to visit my parents and help collect honey from their bees. I actually enjoy it quite a bit.

See you all in a week or so.
yckx

Pac-Hedron HUD

It's beginning to feel like a real game! Now I just need to make it update...

gallery_37843_205_417256.png

I need to tweak my font to look better at small sizes and through the bloom in the menu. Also, I don't like the '3' or the '4', but I don't know if I can come up with anything better. Bloom is still ramped up pretty high in this image. Also, I need to work on the maze shader (I think I want something like a neon tube look), but that's fairly low on the todo list.
yckx
When I first started this project, each game object had a two-dimensional position and an index to indicate what side of the cube it was on. When necessary, I would transform the object's x,y position and local rotation by it's side's xform matrix. I naively thought it would be easier that way. I came to the realizatin the other day that I could greatly simplify and generalize the draw routine if objects keep complete 3D xform data. So I decided to go through my code and switch out the old way for the new. It turns out that it simplifies a lot of code. Pretty much everything except for object creation routines, which is okay by me.

The downside is that there is a lot of code to go through and revise and refactor. And weird bugs happen when pre-revision code and post-revision code interact. Such is the price of naivete.

Update: Done revising camera movement and rendering code. Now I get to go through the player movement/collision code. Then, I think I'll be done with this overhaul.
yckx

Fixing the Text

The text strings in Pac-Hedron are simple chains of squares, with each square's texture coordinates adjusted to display the appropriate bit of the font texture. The entire string is a single mesh, which is saved in a std::map along with all the other meshes so it can be reused. This is bad design.

I came to realize some time ago that displaying the score would break this. Every score update would result in a new string being requested, created, and subsequently stored for later use, causing the program to eat up memory with every pellet eaten. Not good.

So, tomorrow's task is to have each character be a separate mesh, and modify the draw routine to iterate through all the characters of all text to be drawn, compiling them all into a "master" vertex buffer and index buffer, and then draw them with a single [font="Lucida Console"]DrawIndexedInstanced[/font] call.

That sounds right to my 2 a.m. self, although just thinking through it for this post has lead me to adjust the design a bit. I'm concerned it will become a more involved task than I believe it to be. But that's usually the way it goes.

Also, I spilled a very little bit of Red Bull on my keyboard this evening, and it went spastic, sending random characters as if a monkey were banging on the keys. I've been using a spare IBM keyboard my housemate has. We hates it. First order of business tomorrow is to go get a new keyboard.
yckx
I've been trying to improve the rendering code lately. I've reworked it so all the meshes are now [font="Lucida Console"]ID3D10Mesh[/font]es. This lets me approach everything more uniformly and lets me streamline the drawing code. I haven't been able to figure out how to use [font="Lucida Console"]ID3D10Mesh::DrawSubsetInstanced[/font] yet, but I haven't spent a whole lot of time with it. Right now I'm just extracting the buffers and calling [font="Lucida Console"]ID3D10Device::DrawIndexedInstanced[/font]. It's working well enough for the moment.

I had been pushing the maze and the pellets to the GPU as points, and expanding them in geometry shaders. Converting everything to [font="Lucida Console"]ID3D10Mesh[/font]es meant I had to move away from this approach for the time being. I actually achieved a significant increase in my framerate due to finding a badly written loop in the pellet rendering code that was iterating far more than it should have been. I still think that pushing the maze and pellets as points would be faster now that the loop is corrected, but I should probably approach those as particle systems, which is a game element I've yet to implement.

Finally, I've been toying a bit with the maze shader. If I remember, I showed an image in an early post which showed how the maze shader broke at the corners. This has bugged me since the very beginning of this project. I'm now using a completely different shader that feels a little Tron to me, which is cool, but not what I want. I'm going to need to implement a volumetric shader to get the look I have for it in my head, which is also new territory for me. I understand the theory of it quite well, but implementing it is a bit more complicated, and it doesn't help that my prime coding time tends to be late at night, with the resultant cognitive dissonance of ignored weariness.

So, yeah, I'm still working at it. No visuals this time, since the rendering code is still half dismantled. Once I get it put back together, and have some visually noticeable progress, I'll let you all know.
yckx

Hard Drive Oddness

A few weeks ago, my computer froze while I was playing Rift. Upon rebooting, I got an error stating "hard disk read failure" or something similar. It was disheartening, but I had a spare drive, so I switched drives, installed everything, and was good to go.

A couple days ago, my computer started pausing for maybe a minute at a time. Specifically, some programs or windows would become unresponsive, while others remained responsive. It was damned odd. I haven't been keeping up with my computer fixing know-how for a long time, and I was fearing it would be beyond my capacity to solve. But it seemed like hard-drive access was the initial cause of the problem. Not every access, but often enough. Backing up info to my Passport worked fine, but updating DirectX took over two hours. Playing around some more, but in a completely let's-see-what-happens-when-I-try-this fashion, it seemed like writing to the drive was what caused the problem, although it didn't always occur.

So I decided to swap it out and put in an old drive I used to have in this computer, with XP installed, just to make sure it wasn't an issue with the controller on the motherboard.

I got my drives mixed up, and grabbed the original one that had the hard drive read failure. It's working fine. I'm running on it right now, no problems (so far...)

So, uh, where do I go from here? I seem to be avoiding the problem rather than fixing it. And now I expect to begin having problems again any time. What do I do then?
yckx

Bloom!

It seems I never work on next what I say I will. I decided that I wanted to look at something a little nicer when playtesting Pac-Hedron, so I spent the last couple of days implementing a bloom shader. This took more doing than I expected. All the hlsl resourced I was able to find were aimed at older versions of the API, with which I am not familiar; and not being all that well-versed in Shader Model 4.0, either, I didn't want to confuse myself looking at older older code. Also, I'd never written a multipass shader before, so that took some experimentation to get correct. (I somehow thought I needed one more pass than I actually needed.)

In the end, I found this bloom shader writeup on GameRendering.com to be the most useful. It presented how to do a Gaussian blur plainly and clearly without the math upon which it is based (which I usually like, but it was distracting me from getting results).

So, this morning I had a nice bloom glow. But now that I had it, I wanted more: since this game is intended to be synaesthetic, I wanted the bloom to pulse to the beat. It took some time to figure out what intensity and speed looked good, but I quite like the results.

I also made the power pellets blink.

Video:
[media]
[/media]

The drum track now fades to its target volume instead of jumping there directly. At least, most of the time. There are occasional instances when it seems to jump to max volume instead of ramping up; I'm not sure whether this is a real bug or a "trick of the ear." I need to mute the other tracks and test it further.

Incidentally, I noticed while preparing to make this video that Fraps reported a frame rate of 95 in the menu, and 29 while playing the game (running at 1290 x 720 windowed). I'm working on an Intel Core2 Duo 3GHz with 4 GB ram and a NVidia 9600 GT. Not the top of the line anymore, I know, but I expect my rendering code is horribly inefficient. Maybe I can optimize it to improve performance at some point.

I just realized I may need to remodel the player model. It chomps while moving, but more often than not the model is facing (obliquely) away from the camera. I guess I should give it a bigger mouth or have it open wider.
yckx
I've tweaked the music--instead of the drum track stopping when the player isn't eating pellets, it drops to one-third volume. It's an improvement, but it still seems a bit jarring. I think I'm going to ramp the volume up or down over a beat, or maybe half a beat. Quick, but more gradual than an immediate jump from full to one-third volume.

I also have the player model doing an eating animation now. It was easier to implement than I expected. The model is essentially a three-quarter sphere, like a globe placed sideways so the polar axis goes horizontally. Vertices are given an additional parameter (currently called "group" due to lack of proper descriptive skills), with all vertices on one longitudinal arc being given the same group number. These are numbered sequentially from 6 on the "upper lip" to -6 on the "lower lip."

I take the time since last beat over the beat length, multiply this ratio by 2 pi. The absolute value of the sin of that gives me a variable that goes from 0 to 1 to 0 to 1 to 0 over the length of a beat. (If you can think of a better way, let me know.) This "chomp factor" gets passed to the shader that draws the player. There's a check to make sure the player is moving before that calculation is made. If the player is stopped, the variable is set to 0.

In the vertex shader, I construct a rotation matrix. Vertices on the upper lip are 45 degrees off the horizontal. Their group is 6; 45 / 6 = 7.5. So I take group * 7.5 * the chomp factor to determine how far to rotate the vertex this frame. Longitudinal arcs farther back have lower group numbers, and those on the bottom of the model have negative values, so it works out pretty well. The mouth closes a given amount, and the other vertices space themselves out evenly as the surface of the player model expands.

It worked on my first try.

I likely need graphics to better describe the method. I'll get them up soon.[s] Also, no video with this update, much as I'd like to. It takes a couple hours to upload a video to YouTube on our connection, and the housemate works from home on Fridays; I don't want to eat up his bandwidth. I'll do my best to get one posted Sunday or Monday.[/s]

Video:
[media]
[/media]
yckx

New Video, with Sound!

The game feels a lot tighter to me now that sound is in:

[media]
[/media]

All sounds are from FreeSound.org.

In the beginning, you can see menu actions are synced to the beat of the music. Once in game, the drum track only plays while the player is actually eating pellets. This is how I envisioned it, but now that I see it in action, it's a little discontinuous sometimes when the drums kick back in. A more straightforward drum track, with each beat sounding the same, may improve that, but I think a better fix may be to lower the volume significantly when not eating pellets, instead of stopping playback altogether.

It's a lot more fun to run around the maze now.

I'm unsure what to work on next. Most likely the HUD. I also want to add a countdown that displays "3", "2", "1", "GO!" or something similar at game start or when resuming from the pause menu. Also, a win condition check for no pellets remaining would be nice; right now, after clearing the maze, nothing really happens.

Oh, yeah, I need to think about finding a sound artist to do actual game music/sfx at some point.
yckx

Beat Syncing

Thanks to FreeSound.org I have a techno-ish track composed of separate melody and drum tracks. I also have a single kick-drum hit that I trigger when moving through and selecting menu items. The request to play the kick is queued, and it's played on the beat or half-beat. It almost works.

There are a couple problems:

One: the sound is queued, but the menu highlight occurs immediately. I'd hoped that sound triggers on beats and half-beats would be fast enough for it to mesh with menu traversal, but it just doesn't work out that way. I'm going to need to delay menu response to sync it to the beat as well. I wasn't counting on having to sync the menu. I think the best way to approach this is to expand the timer class to emit a beat signal, and have both the menu and audio systems (and possibly others) trigger their queued actions on that signal.

Two: Pressing the up or down arrow, or Enter to select a menu option, right on the beat (or as close to it as I can humanly get) should trigger the sound immediately. Instead, it seems to be just missing the beat, and waiting until the next beat trigger to play. I'm not sure how to solve this. I'm thinking of testing to see if I'm within the first XXX milliseconds (I'm thinking maybe fifty or so) after the beat, and playing the sound with an offset of however much time has elapsed since the last beat. This will require finesse if it works at all. Too small a window will be ineffective, and too large a window will cut off too much of the sound to sound good. I guess the only way to see if there's a window length that won't cause either issue is to implement it and try it out.

So that's what I've been working on today.

Oh, yeah. My eye surgery went well. As I expected, the anticipation was far worse than the event, but that didn't make it any easier. Now that I've been through it once, I won't mind much if/when I need to do it again; knowledge dissipates fear. Honestly, dealing with the bandage for a day was the worst part. There is no longer any blood in my eye obstructing my vision. It's hazy (think looking through a petroleum-jelly--smeared lens), but that's typical after eye surgery, and my vision is improving daily. It should be back to where it was before the hemorrhage in a couple weeks.
yckx

New Video: Camera Fix

I fixed the camera shift this morning, which created an odd tilt when moving sideways, but that's preferable to the previous behavior. I intend to try to tweak it some more, but I'd be comfortable releasing the game with this camera behavior, so I'm moving on for now. It has caused me to believe that the game will cause motion sickness, however.

Video:
[media]
[/media]

I've noticed before that I need to hide the mouse cursor. Sorry about that.