Entry 31 or editing and modelling
Mar 23, 2011
My internet went down for a couple of days, so I’ve spewed up quite a wall of text/pictures “today”. In today’s episode I’m convincing myself modelling is worth it.
Let’s fix up the editor:
Getting this in-game:
Eventually, I want users to be able to create custom maps. Although, that’s a very ambitious goal, I can aim high, can’t I?
This allows arbitrary prop placement, i.e. at any coordinate:
Let’s make a toxic water and borders, so we can have little pools of radioactive sludge to contrast otherwise dark “background”:
Here’s a simple Maya plant model:
Which looks like this in-game:
Here’s an upgrade of the crystal with a model isntead of sprite:
Here’s a comparison in change:
Here are some barrels floating in toxic waste:
These are, again, just a single model “filmed” at different angles:
Modelling has three major advantages over raster drawing.
Firstly, I can never resize a sprite in Photoshop while preserving hard edges and proportions. I cannot depth-rotate a sprite at all. I can never add/remove/adjust individual or depth-rotate components either. This is where a 3D model gives outstanding flexibility. I can position the camera wherever I want and adjust whichever part I need. A problem with a prop/object is 1 problem in Maya and 6 problems in Photoshop. So it is almost always more efficient to fix issues in Maya.
Secondly, a 3D model preserves depth information. With a correctly placed orthographic camera I can perfectly simulate isometric view. I can hardly preserve “3D” look of sprites while drawing in Photoshop. I will inevitably end up producing props that are angled wrong; and it is extremely expensive (in time) to redo these.
Finally, I can render the same scene rotated in however many angles I need. This is perfect for mobile units and moving building parts, as I only need to model once and not worry about inconsistencies between frames. Additionally, many types of props/objects can be rendered from several angles and each resulting sprite would appear as a different prop/variation. Thus I get 6 sprites for the price of 1. Even if some look bad, I can discard them, as they are cheap to reproduce and based on the same model.
The disadvantage of modelling is that I end up with 3D-ish bland look of objects. It is very easy to spot if something was made in a 3D software or drawn “by hand”. To counter this, I must design many details within a model and add noise and other adjustments to the final sprites. But even with this discrepancy, modelling beats drawing sprites directly.
Here is a quickly drawn “bubble” animation for the toxic water:
I made the props to animate either by constantly looping (fireplace) or occurring at random intervals once then not showing up for a while (bubbles). So putting some 30 or so in the pool creates a nicely looking “boiling” sludge:
Entry 32 or prettification and improvements
Mar 25, 2011
I’m getting side-tracked by art and modelling again.
Here are some grass bushes:
Which come from simple sprites and models (with a pre-defined, modified Maya “brush”):
Here are some rocks:
And some “stalagmites” for the lack of a better word:
In addition, I upgraded the editor to draw a grid between tiles and highlight impassable tiles. This makes it a tad easier to edit the map and place objects with path-finding in mind.
I also fixed A* properly. First of all, each frame (i.e. each of 60 frames per second) is allowed to run A*, but only up to a fixed limit of processed nodes (searched tiles). Anything more will have to wait until the next frame. Additionally, A* that fails to find a path after a limit of nodes will also return. This fixes the main problem of units with no path attempting to find path all the time. Limiting A* iterations stops the game from freezing.
Also, the corner cutting is now implemented:
So the unit approaches the corner directly:
The proceeds to the final coord at once:
The blue dots are the coordinates that are checked along the path for collisions. The A* path and the actual path takes can thus be quite different.
Entry 33 or zombie evolution
Mar 27, 2011
I wish no one cared about graphics and focused on gameplay. Yeah, right.
Time to upgrade my zombie model into something half decent. Here are some modelling steps:
The new model has some protruding bones here and there. It is quite demonstrative how small details can make the model look complete different. Basically, featureless parts appear to be “missing something”. Hopefully, this is a step away from “legged watermelon” and a step closed to “zombie”. It is not even important if every detail is clear or recognizable, it is the lack of uniformity that matters.
I also rigged up the model and animated it (again):
So here’s the walk loop:
Phew. Now may be I can work on the actual gameplay/buildings/resources/micromanagement.
Entry 34 or pathing
Mar 29, 2011
Current goal is to fix path-finding and make sure units behave. I cannot think of the project as going well when there are units bumping into each other and entering endless path-finding loops.
Currently units look for a path once, then remember it, and follow it choosing the next visible tile along the path.
Now, when the path is blocked, the unit can no longer reach its target without ugly collisions.
So, as soon as this is detected, the unit tries to find a new path:
This works reasonably well for several moving units at once (that is, moving units block paths for other moving units):
But there’s an issue with this: group movement or “what every multi-unit RTS must deal with”.
Will you be there when I come?
Consider two units (blue circle and purple circle) moving to their targets (blue cross and purple cross respectively):
Both unit find a valid path at the time of path-finding . Then they both move to the next tile in the path:
But now the blue circle can no longer reach its destination this way — the path is “blocked” by the purple circle. So it must find a new path:
This would be fine if the purple circle wasn’t also moving. In fact, blue circle can just keep following its path as the purple one will have moved away by the time the blue one gets there. So for the purposes of blocked path checking, we can ignore units in our way that are moving away from us (say, at least 45°) away.
I have been thinking about the story and the setting. I have been making objects such that they can be incorporated into any setting (fantasy/sci-fi/contemporary/ancient/etc), like trees and rocks. The story and setting I pick will have to be compatible with my art ability and time allowance. I will not do buildings or cities, because I cannot “afford” to draw all the art. I won’t do hundreds of NPCs and races because I suck at organic modelling. I can do cool magic or sci-fi effects. I can do decent weather. I can potentially do various global and local lighting.
I know I want resource (micro-)management, because that is something I like. I always enjoyed Settlers 2/4 or TTD/OpenTTD, even HoM&M. And part of game making is actually enjoying what you make. If I cannot be asked to do it, then nothing good will come out of it.
Entry 35 or holes
Apr 3, 2011
What I want to make is “holes” in the ground — canyons, crevices, pits, whatever. This really just comes down to cleverly designing several new tiles to fake the vertical drop look:
And Photoshmake then:
And test them in-game:
Looks promising. Now, I tried doing border from the black void underneath to the walls, but this created a mess at the “half tile” corners (wall + void). Besides, most of the combinations wouldn’t be used. So, here’s the tiles themselves edited to include a little void leak:
And finally, a simple border from dirt to any “hole” tile:
Works well enough, so I can now manually create chasms and stuff:
Looks retarded, I know! But all this really needs now is some fog animation in the void, higher walls, and decent dirt cliff borders.
What an excuse for progress while I’m trying to think of a good setting for the game…
Entry 37 or harvesting
Apr 8, 2011
Time to spend a little more time doing constructive work, or — to be precise — do some new features.
We need the units to be able to gather resources. First, a resource class is made. Then certain props need to have an optional gatherable/contained resource and available amount values. For example, rock props may have 40 stone resource. Second, units need an optional carried resource and amount values. Third, units needs a gather prop definition command, simply go to target prop and gather. Then a simple command issue to current selection of units by right-clicking a prop that has harverstable resource. Then a simple implementation of move to and gather resource, same as attack building — if close-by to the target prop do gather, else move towards with usual path-finding.
Here is player issuing a gather/harvest command:
And here the bot arrives at the target and “gathers” (technically idles nearby):
And a UI/cursor/selection check to make sure only unit that can gather, get to gather:
Now, it wouldn’t be too hard to make the robot visually “carry” something. For example, a little container mounted on the back with the current resource visible from above would be sufficient. From modeling perspective, this means rendering the same robot while changing between various carried containers. In code this means using different sprite images/textures when different resources are carried.
Now, let’s make the unit get the resources back. This is basically the same logic as gathering, except target is the delivery building. First of all, we need a building. Let’s make a placeholder:
Cute. Now the building can be set to take an “input list” of resources and produce an “output” resource. So in this case, the building accepts iron and returns steel. Now the unit needs a return command, temporarily also issued by the player. Finally, that is only applicable if the unit is carrying something that can be delivered to the building.
Now the unit needs to start doing this automatically. This is why we do a Job. The gatherer job gets assigned by requesting a drone robot to gather a resource. It should then proceed to gather, then return the resource. It should also remember where it gathered the last resource to return to the same location. Similarly, where it delivered to last, in case the base is destroyed, so the units don’t stay at their potentially more dangerous gather location.
So here’s the plan (without account for inaccessible buildings/props):
Now the player doesn’t give the gather command directly; rather the unit is given a job.
So here’s the little guys running back and forth (resources don’t expire and harvest/deliver times are 0):
I now have a nice little “AI” hierarchy (not really AI though, just a basic unit logic):
* Immediate action — slide 3,-2 pixels
* Command — harvest iron ore
* Job — gather and deliver iron ore
* AI — assign these units as iron ore gatherer (not implemented)
So this is nice and object-oriented and easy to expand on each level.
Fun fact: I have 56 files and a bit more classes….
Entry 38 with exploring and fog of war
Apr 14, 2011
Let’s make one RTS characteristic thing: fog of war and exploration. Well, technically that’s two things but they are very much the same. Basically, a Boolean flag for whether a tile is explored and another for whether the tile is currently visible (not under fog of war).
Fog of War
Let’s start with fog. Here is simple tile/prop tinting on a per-tile basis:
The fog is generated similar to light — in a tile-based circle around a unit:
(I will have to make this into an actual lookup array instead of doing Pythagor’s square root calculations every frame — I know! awful practice.)
Let’s improve this; instead of darkening/tinting the tiles, let’s draw “fogged” tiles on a separate layer and apply a desaturation shader for a nicer effect:
Cool! Sounds simple, but takes some fiddling around. Visible and fogged tiles are now drawn separately. The visible tiles are then sent to draw buffer as is. Fogged tiles are passed through a post-processing desaturation shader, that kills 90% of tile color.
Only issue is that I have no clue how to make this smooth together with the main routine. I bet I’d have to make a shader similar to light blurring that passes how much each pixel is to be desaturated. I have no idea how though, so I’ll leave it as is for now.
Now, let’s by default hide unexplored terrain:
As the unit moves in, the territory is revealed:
Then, moving out, the terrain gets “fog-of-warred”:
The problem is props/units/buildings that get drawn “saturated”, i.e. not in multiple layers. I could hide them while out of line-of-sight, but that wouldn’t make sense for props and most building, as they are unlikely to “move” or “disappear”. But the problem with these is that they are depth-aligned. Tiles are all on the same “z-depth”, as no tiles ever overlap. Props on the other hand can overlap quite a bit. So drawing visible props before desaturated invisible ones may cause invisible props behind (in the game) visible props to appear drawn above the visible ones.
Now, there is no (efficient) way to desaturate the sprite as it is being drawn, because XNA can only tint the color of the tile (probably with shaders and some weird logic, which I don’t want to even get into right now). So I’ll just leave building/props darkened whilst invisible.
Now, the player doesn’t know what’s behind unexplored area, so neither should A*. Let’s return the tile as passable for every unexplored tile:
What happens is the unit attempts to move along the path, but then finds out the path between current location and the next waypoint (furthest visible tile) is blocked; so it tries to re-calculate a new path and either find one around or fails to find one.
It’s amazing how not knowing the map and exploring it is exactly like other RTSes I played.
Entry 39 or map optimization and lighting shader
Apr 15, 2011
I changed the way rendering loop works. What I had is that I I went through all the map each frame, then checked if the tile is visible or not and drew it then. This is highly inefficient. Basically, every tile in the game went through the loop, it’s draw coordinate was calculated (green), but only a small portion of tiles were drawn (orange viewport):
Obviously, this is very easy to do. You specify two loops — for x and for y. The only property of camera is the center coordinate (cross). All drawing routines are simple offset calculations.
Now, a better but a little more complicated way is to keep track of the camera center tile — that is, which tile is currently in the middle of the screen (orange tile). The only iterate through the nearby tiles (green):
Now, map size is no longer the issue, since most invisible tiles are skipped (pale green). But we are in an isometric world, so screen X and Y relate to world X and Y with a “30° angle”. Smooth camera scrolling is achieved by having an additional offset X Y values within the currently selected tile.
Finally, I pre-calculate the actual locations of the tiles and which tiles are to be rendered (green):
This way I keep a single list of tile X Y values, then iterate through the list and add the current camera offset to the coordinates. Without going into much detail, this lets me do a single loop while only rendering the sprites I know will be visible and not checking any others. Additionally, the majority of the math is already done. Very funky math.
This also makes unit/building/prop drawing more efficient, as I also iterated through all of them each frame. Now I only need to look at the ones that are visible, since I am already keeping an object tile-based map for path-finding/collisions and such.
Additionally, this also iterated the off-world tiles (with invalid coordinates outside bounds), which is actually a good thing. I can render these tiles black of to whatever other color, and solve a nasty lighting “bug” I had.
Incidentally, I half-broke the lighting algorithm, I may just need to make a better one. That and the tile-based light is a bit silly, with borders still visible. Time for shaders.. oh boy. The problem is not really it being complex or hard, but the absolute lack of proper tutorials on it.
So here’s a shader that takes a 2 element array of real numbers (float) and then simply draws magenta pixels past their XY value on screen:
That silliness took a lot longer than was necessary if there had been a good explanation somewhere easily found, rather than throwing and extracting some bits from 10 different problems on forums.
But anyway, here’s three float values passed to draw a certain color:
But apparently these are passed as constants and stored in registers, so I am at a 32 limit? *sigh* I don’t know what I’m talking about half the time. As far as I gather, the best way is to use a custom texture that stores the needed data. Not that I know how to set the pixel data or access it from shader code. But that attempt failed with reaching arithmetic instruction limit right away… The thing is, I want to do circle code in the shader so it’s faster. It is pixel-based and would be very slow on CPU for every pixel for every light source. I guess I need to do multiple full-screen renders for each light.
Anyway, let’s render a circle (in relative, normalized terms):
Now let’s use a separate render target for our light shader, where a certain area around a given x/y is “lit up” (more transparent than the rest):
Here is a bunch or random circles drawn independently with a shader-based distance/circle calculation:
Here is the same method, with blurred edges (alpha depends on distance from center):
The brightness values aren’t right though. The whole eye color sensitivity and brightness perception thing. *sigh*
Anyway, here’s a couple of units “glowing”:
I’m not even sure how variable light would work together with fog of war and unexplored area. It has to be very obvious to the player where fog of war starts and ends. I guess obvious solution is to not use any light effects on the fog of war:
..which makes it look O.K.
Entry 40 with building face-lifts
Apr 16, 2011
Entry 40, wow! It’s actually been 4 months since I started this devdiary/project. I really need to come up with a name for the game/my “company” and buy/register a proper domain name. I am not really going to call this “Land of Magic”, contrary to Entry #1’s assertion.
Here is the lightpost model/graphic I upgraded:
These use the same static base bottom sprite and 32 rotary top sprites:
It takes about half an hour to make these, if I don’t start nitpicking things.
In the image above, I moved the sprites closer together, since my original is HUGE. I really ought to pack the spritesheet’s individual graphics closer. I might even trim 75+% of whitespace this way. But that means I need pixel-precise sizes for all objects, programmatic look-up of location and a software to automatically do that. And I think I might be better off writing one myself.
I keep calling these “placeholders”, but I have a feeling that, except for some little touch-ups, I will end up using these in the end unless I find a 3D modeler who wants to work for free. I mean they don’t look that bad (I hope)!
Anyway, here’s a face-lift for turrets and a little zombie attack scene:
Here’s the sprites:
What a moment of sudden inspiration! Now I only wish I would get these for the tedious, boring code parts.