PsySal's Livejournal (Developer Blog)

Syndicate content PsySal
PsySal - LiveJournal.com
Updated: 1 hour 6 min ago

Context is the KEY!

Sat, 08/16/2008 - 00:56
Very generally speaking, the way I do autogeneration is from a broad description to a more specific description. You can have as many layers as you need along the way, in the end you've got to have pixels. This is really just the same thing as multilayered abstraction and it's basically what computers do, period.

Anyhow, one of the lower level abstraction layers is that of a "renderable". This is just a description of cubes, planes, effects, animations, and so forth to be fed to the rendering engine which is in C++. So this represents the lowest level, roughly, that I go to while in Lua (remember that Texas is mostly made in Lua, with a core engine in C++).

Renderables can operate on each other, so you can wrap one particular renderable (say a bathtub) in a reflection effect (for the porcelain). Or you can wrap another (say a windmill) in an animation (spinning); you could even wrap the whole thing again to have a reflecting, spinning windmill. It's actually not that complicated once you get the idea.

The beauty and simplicity of renderables is that they don't have very much context, really. They are ultimately going to represent unknown sets of GL (drawing) commands to be sent to the graphics card together with a bit of local context (i.e., specific to each renderable so it is opaque) and an update (T) function.

Sometimes you need a little more context. Normally, you want to avoid additional context. You actually want to keep things loose, and intentionally *NOT* care how big something is, for instance, or whether it's an effect or an object or whatnot. You can still have code internally that sorts this out, but when you're generating these things, you ordinarily just want to know that you've got yourself a Renderable, and not worry beyond that.

Which brings us to my current situation. The one bit of context that is useful, the "next most basic bit" of context as it were, is spatial context. Not in terms of position, but in terms of size. So we'd like to know, not just that this is a Renderable, but this is a Renderable that "somehow fits" into a given 2D (L, W) space. When I call this context, what I mean is that it's public context. So think of this as an AreaFiller, not just a Renderable, because it "fills" a given area which you pass in. When we want to "draw" an AreaFiller, it not only needs it's own local opaque context, but also (L, W) context to passed in by the user class. When we "draw" an AreaFiller we're actually producing simple renderables.

Here are examples of some AreaFillers:

1. Books. We can create a books areafiller by describing the properties of the books it will fill. We specify everything about the size and shape of the books, including their overall height. We could conceivably specify a number of books, as well, but more likely we would specify a "density" factor.

2. Towels. Sort of like books, but laying down. We'd specify the average width of a towel, how many tall they could stack, and so forth.

3. Trinkets. We could specify a big list of renderables (or, functions generating renderables), along with some way to change their sizes slightly.

You've now created your AreaFiller, let's use it. Let's create a shelf renderable. Pass in the dimensions of the shelves, how many there are, the type of wood to make it of, thickness of the boards, that sort of thing. Also pass in an AreaFiller. What areafiller? It doesn't matter. The shelf can use the AreaFiller to put things on itself; the shelf when generating knows the (L, W) context of each individual shelves. Because AreaFiller defines only areametric space, not location context, we can also place the objects wherever we want.

Voila, we've now separated shelves from their contents, making it mix-and-matchable. Better yet, when we create a table we can also use AreaFillers to put trinkets, towels or books on it. Hopefully you get the picture. These kind of things are actually my deepest, hardest won secrets of autogeneration.
Categories: Developer's Blog

Flexibility and Staying in Touch!

Thu, 08/07/2008 - 02:26



Flexibility means being able to change your plans; being an indie game designer, this is one of your greatest assets. If you see something isn't working, you can throw it out, and there's nobody to convince but yourself. Likewise, if you feel that an idea or implementation idea has lost some of it's lustre, or isn't big enough, then you can throw it away and replace it with something else.

Staying in Touch means keeping to concrete, small ideas which together will lead to the complexity and fun you ultimately desire. As a well meaning game developer you can plan any number of game systems that don't work in the end; and in fact I have done this on a number of occasions. It's so hard not to think ahead, to envision even just something semi-grandiose! But that never works. You have to to stay in touch, do things one step at a time, and try always to make the best decision for now, not for later. Because by the time you get to later, things are rarely coming together as you'd hope.

This is what it means to break new ground. If you're just implementing a tried and true formula, the rules change. But that's not the point of doing indie games, or at least, not for me.

To this end, I'm going to sort of only stick loosely to the original game plan that I had, at least in terms of story. I think that the castle that I've implemented, which is huge, is an excellent and fun parallel universe. So why give it the minor role it had in my original plans? Instead, I'm going to start the story here, in the real world. The basic premise for the game will not change, and the many gameplay ideas and story elements I've sketched out over the past year or so I'm sure I'll end up using, but ultimately I'm going to just look at this concrete, fun gameplay environment I've created and ask myself, "What should I implement right now?".

I'm going to ask myself that, and keep answering it, over and over, until it's done.
Categories: Developer's Blog

Detour: World Design

Thu, 06/19/2008 - 17:00
Been awhile since I posted. Here is a juicy screenshot, it's the courtyard in the real world:



I have made a probable mistake, or rather meta-mistake in the design process! It turns out that I need an alternate world, these are little areas of the castle that you visit to obtain certain items. I decided to create this world "realistically", that is, in parallel with the real world. I carefully positioned the doors to this alternate dimension close together, so this area would not be too large, but alas it's really a large large amount of level design.

Anyhow that's what I've been doing for the last six weeks, really. A bit of a detour, to be sure, but it will work out alright in the end. And I have to admit, it's pretty fun crafting levels/items/objects using this game engine and my now-solid skills with it.
Categories: Developer's Blog

The Blue Door

Sun, 05/04/2008 - 16:36
Well, it took some searching but I found the story design docs I did that I need to progress. I'll worry about the player/enemy interaction issues that I wrote about yesterday later on; it will make more sense in the context of a greater overarching story sequence, anyhow.

The first stage in implementing this story is to put in the "blue doors". These represent your links to the real, real world, and also play into the system of upgrading your guns, so once they are in I will probably put the system in place that you need in order to get your guns. There won't be much in the way of obstacles to do this, but I can at least put the basic sequences in that you have to walk through in order to get your weapons. This represents effectively the backbone of gameplay progression.
Categories: Developer's Blog

Next phase: story! And player/enemy interaction issues...

Sat, 05/03/2008 - 02:47
It's time to move into the implementation of the story. I plan on taking what I have, which is sort of a rough outline, and implementing it-- a rough sketch of the overall gameplay but without too much in the way of actual constraints. So the events/places/items/etc. will be laid out something like how they need to be in the final draft, but without worrying about constraints just yet.

So, if the gameplay graph is a requirements graph with nodes and lines between them indicating requirements (i.e., "to get to Y you need X") then the first step is just to put the nodes in without worry to connections. Interestingly, this is the same approach I have taken with enemy AI. Draw a graph of the enemy's behaviour, and then implement each state, then worry about the transitions separately. Works smashingly!

On the technical side of things, I'm starting to run into some trouble with the player interaction model. Essentially, drones (enemies) could "take control" of the player; for instance, a mummy drags the player underground, so to do this, we freeze the players control and then the mummy AI takes over. This works, but only to a point, since what happens if two mummy's want to grab control? Or worse yet, what if a story element takes place?

My idea is that this control scheme has to be transferred onto the actual player. So the player becomes it's own state array, with transitions in between states. This isn't perfect; I think that the individual AI states will need to have a "default" behaviour. Imagine if there is a player.set_state_dragdown () method, which causes the player to be dragged underground. This will return true if it was possible to transition to this state, or false if it wasn't. The mummy needs to call set_state_dragdown () when he wants to drag the player underground, but also needs to respond to the true/false conditions.

This is probably the cleanest solution to this particular problem, and not difficult to implement and keep organized. Since the enemies already have a broad range of effects they can carry out on the player, it's important to keep these all in one place where the relationships and transitions between them can be carefully analyzed, rather than spread out ad-hoc over all the enemy AI routines.
Categories: Developer's Blog