Skip to content

June 29th, 2014

June 29th, 2014 published on

Things continue to go smoothly. The event system has long been wrapped up, and scrolling is half done (which is actually the technical half, the other half is just interface details). So at this point all I need to do is to build sample widgets, convert existing systems over to the new one, and build a few more common ui layout builders. So quite literally just grunt work at this point. I need an intern for this stuff. The actual implementation of new UI will be a gradual process over time since it’s partially dependent on artistic design and partially dependent on more of the proper game design being nailed down.

That’s about all for this week. Not a lot to talk about. Maybe next week will be more interesting if I decide to work on proper game stuff on the side, but I wouldn’t count on it.

 

June 22nd, 2014

June 22nd, 2014 published on

This week has been pretty smooth. The event system is getting pretty close to done, despite me taking half the week off for design work. At this point I’m only really worried about getting scrolling functional, since it’s a complicated weave of several systems. Most everything else is just going to be grunt work. Takes time, but not much thought. Getting it done this month is still pretty bleak, though.

Design work was all over the place. A lot of stuff is still very much in the realm of, “I know how this needs to work, but don’t know how to fill in the details yet”. What I can talk about is the conclusion I made about battles. Right now it’s very hard for players to get much of a sense for their progression, any idea what a given tier of difficulty requires, or even feel very good about the rewards they get. All these problems have a central problem: players aren’t in battles long enough to get a sense for anything. They also aren’t required to be in battle that often for them to care about being more powerful in battle. No one really loves having to fight the same enemy over and over again in an RPG, but the fact of the matter is that it actually serves a vital purpose. The key is to not go overboard with it.

One of the more recent updates added more battle opportunities to the map by placing chances of encounters between every non-battle area on the map. It was an improvement. But it’s not enough, since the system still relied on luck so it was still possible for players to miss out on battles. The new system I’ve proposed flat-out requires every player to engage in combat if they want to move around the map. It works by placing a monster encounter on every tile. Once a player defeats that monster encounter, they’re free to move there without having to fight it again.

Whether an encounter is cleared is actually instanced for every player, so people can’t just follow someone else around to avoid battles. I was really hesitant to make it instanced since I think instancing things tends to make the multiplayer element a little more detached. But then I considered the fact that having random encounters is also instancing in a sense, since one player rolling a battle doesn’t influence the odds of another player rolling a battle. I began to get more comfortable with the idea of instancing after that.

A lot of fringe benefits start to fall out of this system, too. A major problem with the game was that players can very easily snipe rewards that other players found, diluting the joy of exploring the map. By requiring a battle and having it instanced, the player who beats the battle first will also get first dibs at the reward. This also creates moments of tension where the player who can kill the monster encounter faster will get the reward at the other end. Since these encounters are instanced between players it also means where each player can go on the map changes over time, creating some strategic movement choices.

I’m not completely confident that this particular system is going to be the right solution (and it definitely won’t erase all of our problems), but I feel like I’m probably headed in the right direction now.

June 15th, 2014

June 15th, 2014 published on

sheets

 

As you can see, the new character sheets are fully functional in-game. The active player’s sheet is made larger than the other player’s as well as fading out the inactive player sheets a little bit in order to emphasize the player who’s turn it is. The client playing the game is always first in the list, so it’s easy to keep track of who you are. The list is also arranged in the actual turn order so you can tell how far away your next turn is at a glance. Of course character sheets aren’t entirely done just yet, there’s many polishing touches that will have to be done later, but it’s a good foundation.

Stopping to make something functional with the display portion of the system was one of the few smart things I’ve done lately. A whole lot of things had to be changed to get it working properly that will affect future systems, so I saved myself some hassle of having to update them for the changes. Not only that, but being able to do something practical that is actually getting used in the game is a huge morale boost compared to spending months chugging away on code with no visible results.

Playing through the game with the new interface was interesting. Being able to easily see a comparison of player states made some things a lot more obvious than they were before (namely spotting exactly when and where another player starts falling behind). In general the game is more comfortable to play since there’s less in the way of missing information for players. It’s a valuable lesson to learn: for testing purpose having an ugly interface is fine, but just because it’s ugly doesn’t mean you shouldn’t make sure it’s displaying all the necessary information for players.

 

June 8th, 2014

June 8th, 2014 published on

Lots of minor problems this week. So player sheets aren’t entirely done yet. But I do have the basics drawing now:

Those images-representing-health/mp-percents are one of the reasons I went on this mad quest.

And as you might hope, it scales up to larger resolutions as needed:

1920

Here’s Sew‘s original mock up for this piece of interface (as you might notice, I haven’t gotten around to actually filling in the experience bar yet)

Concept

So I’m pretty sure I’m going to get this thing up and running in game next week (assuming I handle the too-boring-to-talk-about issues that continue to plague me). And then I’ll be moving on to finishing this thing off with event handling (so it can actually be interacted with), basic ui widgets, and functional scrolling. It’s looking more and more like the cost of this is going to be 4 months. Regrets weigh heavily, but it has been encouraging getting to work with something. And the system is legitimately a delight to work with.

June 1st, 2014

June 1st, 2014 published on

This is the week I begin regretting implementing this in C++. In short the display part is compiling just fine now, but still has a bit of remaining work to get it to start actually drawing stuff on the screen. Since most of this week was spent fixing rote (but painful) errors, there isn’t much of anything to talk about here. Looks like this UI overhaul is going to cost 3-4 months instead of 2. Really hoping for that 3.

I’m aching to get back to work on the game proper. I might even sneak in some work on it on the side? After being away from it for a couple months the biggest bang for buck that sticks out in my mind is cleaning up the main quest to make every portion of it potentially game winning. I’m starting to warm up to more player choices in quest lines to provide an initial sense of “wonder what happens if I do the other choice” to keep players coming back, though I worry that using it too much will result in players assuming each choice always results in the same thing. Something about side quests still seems off to me, but I can’t put my finger on it yet. Suspect that time management will start to fall out of the main quest changes and give me a better idea.

Right now the game is on the verge of a very big choice. We can either lean much heavier into multiplayer, or we can keep it at a distance in the hopes of also having an engaging single player mode. Leaning into multiplayer has a lot of benefits for the game proper: the more places we put players the more replayable the game as a whole becomes, having battles built around pvp makes the game better in multiplayer, and the more places we put other players the less boring the pacing of turn based becomes in multiplayer. Basically the more emphasis on multiplayer, the better the game becomes at multiplayer (duh) and as a whole. But putting out a multiplayer-focused indie game is basically playing with fire. If you successfully gain a long-term player base, you will warm your house for a very long time since that player base will naturally expand itself. If you don’t gain a long-term player base you will have burnt down your house because no one wants to buy a multiplayer-focused game when there’s no one else to play it with. Given all the niches this game hits (JRPGs, turn based, etc) that are traditionally single player games it’s really hard to tell if hitting these niches with a multiplayer focused game is brilliant or suicide. At the end of the day the choice is obvious: we started this game because we wanted to play a multiplayer version of these, so we should just make the best possible multiplayer version of one. Even if no one else agrees.

May 25th, 2014

May 25th, 2014 published on

I had hoped to get the display part of this thing up and running this week, but illness happened. The code part of it is complete, but doing the necessary additions to related code and making it capable of actually compiling still need to be done.

You might recall last week that I decided to make sprite caching operate by having parent scale/tint/rotation/etc applied to the cache texture instead of the individual cached sprites that make up the texture. At this point I had the idea of storing a second set of world coordinates for each of these cached sprites to keep track of where they really were in the world rather than where they were relative to their cache texture.

This idea was rather naive in that I considered world coordinates to be calculated the same way as if the cache wasn’t there. Of course in reality scaling up a texture that has a sprite in it isn’t the same as scaling that sprite up directly- its position ends up shifting as part of the scale operation! Once my head had cleared I ended up shifting to a system where collision coordinates are converted between the render targets as needed for nested cache sprites, as well as other systems such as the map camera.

May 18th, 2014

May 18th, 2014 published on

I suppose you could split the implementation of this thing into 4 parts: display (inheriting parent properties, drawing to screen including complexities like caching, etc), events (detecting collision types and dispatching relevant events, handling those events), layout generation (arranging children in more sophisticated manners), and ui widgets. That first part is nearing completion in terms of code written, though fixing/testing that code to actually run hasn’t started yet. It’s hard to estimate how long these things are going to take since a number of unknown factors are involved. It could be worse, I guess?

A fair number of new design problems popped up while implementing this thing. But none of them are terribly interesting. Ended up going with the “scale/tint/rotation/etc of a cache renderer node are applied to the cache texture instead of being inherited” model once I realized that fonts aren’t scaled up and would instead properly resize the cache texture for proper readability. Decided to move refreshing (the queuing of re-applying inheritance rules that is delayed until the next update) to its own handler so that later on we could have refreshing that only applies to things that depend on each other (ie you change the tint which has no dependencies it only refreshes the tint) and so that component objects have a more restricted knowledge rather than having access to the entire node. Decided to let individual nodes decide whether they use a stable sort on their children or not, since in many cases it doesn’t matter while in a few (namely windowing) it does. A little bit of premature optimization there that might bite me later when I forget how it works. Nothing exciting, just a few details that get missed in planning.

I’d really like to get this thing done this month (marking 2 months down the drain for it), but that isn’t looking likely at the current rate of progress. Troubling. Had a thought about how to visually handle NPCs yesterday that cheered me up, since it solves a big problem with the story lacking emphasis.

May 11th, 2014

May 11th, 2014 published on

At long last, planning on the new sprite/ui system has come to a close. This week has nothing really special to talk about. The majority of the remaining problems were all about filling in the last few things that hadn’t been fully documented for the latest changes (dual graph system, collision handling, scrolling, etc). Implementation is going smoothly so far, but since I made the unenviable choice of doing it on the C++ engine side I know full well that there is going to be some heavy debugging costs later on.

Not just that, but large swathes of the existing game are going to have to be updated for the new system (how maps are managed, battle backgrounds will accessed very differently, map objects are going to be handled as sprites instead of tiles, how every sprite in the game needs to be handled is changing, etc). So there’s still a lot of work ahead. On the plus side I feel like the last parts of the core engine that I was displeased with are finally getting into order. Once this work is done I feel like I could use the engine to make future games easily, instead of the weirdly cobbled together game-specific mess it started out as.

Unforeseen Consequences: Collisions Collide!

Only one design entry to talk about this week since there weren’t that many. Last week I decided to split the graph into two: one to inherit display/position properties, and one to indicate draw order. There was one thing I hadn’t considered when I did that, which is that linking those two things is extremely useful when it comes to collisions. By having every child be within every parent with the transform graph, it allows the property of only checking children for a collision when it collides with their parent. By having the layer graph order indicate draw order, it allows collisions to be intercepted by sprites towards the top of the draw order- ie if the user clicks on a window that’s on top of another window, only the top window actually receives the collision. These two properties are crazy useful, but by splitting the graph I had to choose one or the other.

At the end of the day the layer graph won out, since it’s a useful property rather than just an efficient property. But I didn’t just discard the transform graph’s filtering, I just made it an option for parents to pass collisions to children even if they themselves don’t collide (alternately, they can just encompass the entire world). Since the majority of the two graphs are identical only the few exceptions need concern themselves about this. It’s not ideal (more because these details are easily forgotten and create problems later, than from inefficiency), but it’s good enough.

 

May 4th, 2014

May 4th, 2014 published on

I think planning is finally actually coming to a close this week. This is probably the third week I’ve said that. But I think I mean it this time. I’m eager to see how implementation time pans out.

This week’s problems:

1. Who’s renderer is this anyway?

As previously discussed, sometimes you want to pre-render complicated unchanging visuals to a texture and then just draw that instead of each individual element every time. Naturally this means coordinates need to start being relative to a sprite’s parent. It also means that the renderer object- the thing that decides whether it’s doing a dynamic or cached render- needs to start being what decides what to do with those relative coordinates. A dynamic renderer is going to want to use the accumulated xy positions of its parents. A cache renderer is going to want to start fresh since it’s having its children draw to it instead of directly to the world.

This caused a great deal of pain in terms of deciding whether the object handling all general positional information should deal with these final coordinates, or whether the renderers that changed the behavior to begin with should handle the coordinates. Eventually the renderers themselves won out at the logical place to put it.

2. Draw order is a pain.

Generally the draw order of a scene graph is determined by the ordering of the graph itself. This causes some issues in a 2d game. The scenario I use to illustrate the problem is this: characters have nametags positioned above them. Logically, these nametag sprites should be attached to the characters since their positions are related. But the draw order of these things is very different. Since characters are drawn in y-order, you end up with nametags being placed underneath characters when they should always be above all characters!

This doesn’t seem to be that commonly discussed of a problem online. I’m guessing most people just work around this relatively rare case by manually positioning such nodes elsewhere in the code, but that defeats part of the point of using a scene graph to begin with! (in early drafts of my work around I tried building this type of functionality directly into sprites, but ran into it quickly becoming a mess). In one case I saw a library using parts of OpenGL directly to accomplish differing draw order in special cases, with a host of caveats attached to it. A friend I asked used the technique of having draw order completely unrelated to the graph by having sprites associated with layers that determine their draw order.

I didn’t like any of these solutions because using the scene graph for draw order is extremely useful to me. You want a window’s contents to be drawn on top of the window? That’s the default behavior! You want to move a window to the top of the window draw order when it gets selected? Simple as moving it to the top of its parent’s child ordering. You want JUST these sprites to be y-ordered? Set their ordering metric to their y values when they change. It allows for dealing with complicated draw order problems in a simple manner, especially when it comes to UI.

So I finally settled on an unnervingly complicated solution. There are now two graphs: the transform graph (inheriting position etc) and the layer graph (determining draw order). Most of the time these graphs are identical, but in cases where they need to diverge they can by giving a sprite a different layer parent than their transform parent. I don’t really like how complicated this makes things. Bugs are almost certainly going to arise from me forgetting which graph I’m concerned about at a given moment. It’s wasting some resources for every sprite that only a few sprites need to worry about. But it does solve the problem.

3. Scrolling is pain.

Supporting UI scrolling is basically death by a thousand cuts. You need to a scroll offset to shift children around to create a scrolling effect, but you must only pass that offset to your children instead of using it yourself. You must be a specific type of sprite so that you know to create scrollbar children to adjust you. You must use clipping/masking on your children to deal with partial visibility. Scrolling has its fingers in a lot of different pies, which makes structurally containing it a nightmare even if the individual parts aren’t so complex.

April 27th, 2014

April 27th, 2014 published on

Planning is slowly coming to a close now that I’m down to API specification. Slower than I’d hoped. But I’m still managing to solve important problems so I don’t feel too terrible about the rate of progress.

Programming strategies are a funny thing. For any given established design technique it’s not very hard to find a counter argument against it. Which isn’t really surprising, when you get down to it there’s no single perfect piece of code for any sufficiently complex problem. The best you can do is optimize for the specific angles that are most important for your project. Losing sight of that is the danger of doing extensive planning like I’m doing right now.

And I fell into it this week. I got too worried about what the right way to split up a task into objects was (dang ol’ Law of Demeter got stuck in my head). Spun my wheels in the dirt for a few days. Eventually managed to let it go, realizing that if this part of the code needed better modularity later it wouldn’t be hard to add it after the fact since the part that other things touched was sufficiently contained. I feel like a code hypochondriac most days, worrying about potential problems that will likely never materialize. Which then leads me to overcompensating the other direction of embracing under-planning and ending up with an actual mess. Fortunately I only spent a couple days on these worries, and I managed to stop before it became an actual problem.

————————

Other dumb problems I worried about this week:

1. Enumerators in Python suck, or languages with flexible namespaces have ruined me

This is a problem I’ve hit my head against pretty much constantly. And I still don’t have a comfortable method to deal with it. There’s basically two common methods for enumerators in Python. You can use magic strings which then requires extensive documentation for what the available options even are (yuck). Or you can use an object with properties representing the available constants (which is essentially the method that got incorporated into Python3).

What I don’t like about the latter method is that it feels incredibly overbearing to have to import the enumerator object (in my particular case I want to use enums for setting the mode of something. ie, additive or subtractive or alpha blending). Like I just want to casually manipulate this sprite object somewhere and now I have to import something just to tell it to be left aligned? To say nothing of the fact that it basically requires documentation to figure out that a method wants that specific type of enumerator in a language without strong typing (after finding out 3 has argument annotations I’m probably going to take the speed hit and finally switch to it. When you start working with a big enough codebase for long enough, no typing leads to a lot of incredibly long argument names for the sake of clarity).

The closest I’ve come to what I want is to make an enumerator object of sorts that just has a bunch of methods for setting it: SetAdditive(), SetSubtractive(), etc. It’s ok I guess? I feel a little weird about it. Maybe it’s okay.

2. Size and scale are different things.

Because telling an SFML sprite to hit a target size is done by giving it a scale parameter, I ended up mixing up the concept of size and scale into the same component of a scene node. Specifically the properties of “match the size given by our parent sprite” and “make this sprite’s base size match this target size regardless of its loaded size” ended up getting put into the scale component. This is an awful idea because you don’t want to have child scene nodes inherit this particular scaling. Eventually I realized my mistake: a size component handles these things, and then the scale component scales it up, and finally the low level sprite is given a scale to match the resulting size of the two.