It's been quite a while since my last post. I am making progress, if slowly. Here is some of that progress.
Day/night cycles. The game keeps track of time of day and, when outdoors, the ambient lighting adjusts to appropriate levels. Walking into a bed triggers sleep which will pass time. Sleep will reset spell cooldowns and recharge energy and health, but the characters' hunger continues to increase while asleep.
Animated tiles and room fade. The engine now supports animated static tiles, which should make the world feel a bit more alive. Also, when indoors, the walls get in the way. In searching for a solution I decided it was best to simply fade out the entire exterior area when entering a building or room within a building.
Serialization. The engine can now serialize entities, saving state of dungeons and outdoor areas when moving between, and making it possible to save/load games. To avoid "save scumming", however, the game will only have 1 save slot per game, and saving will occur automatically when certain events occur.
Compiler bugs? I don't lightly accuse my tools of being the problem, but I don't know what other conclusion to draw in this case. The problem first exhibited as some sort of heap corruption; the Marmalade system would get arbitrary read or write violations when flushing the GL buffer. I thoroughly examined every piece of code that touched the heap. I commented out large swaths of code but was having trouble correlating the absence or presence of code to the absence or presence of the bug. I searched the marmalade forums, I upgrade marmalade and uninstalled Visual Studio patches. Nothing worked. Finally, while commenting/uncommenting code trying to manually narrow down the source once again, it dawned on me that maybe it wasn't the procedural code per se but the variable declarations -- I located a rather large structure that was allocated on the stack in the top-level rendering function and moved its declaration outside the function. Boom, worked perfectly every time, the problem was gone. I never bothered to root cause the true source of the bug, but I'm pretty sure it's an issue with the VS compiler. Somehow, it was allowing the stack to collide with the heap undetected. This only happened in debug mode. The problem never occurred in release and did not occur in ARM builds (which are built with gcc). Anyways this was a huge waste of time.
Ranged attacks. Unsatisfied with the idea of the game automatically choosing targets of all ranged attacks/spells/skills, I bit the bullet and implemented ranged target selection. The system allows a selection of a varying radius and maximum range.
AOE Target Selection
Particle effects. I really didn't want to have to draw death animations for every sprite, and I did want to implement more effects to make combat more satisfying. I realized that a particle effect engine could solve both problems very nicely.
And boom goes the dynamite.
Food. As the game is played, the characters become hungry. I want the gameplay focus to be on survival, as many roguelikes are. Actions have consequences, and once of those consequences is increasing hunger and the need to procure sustenance. I've implemented hunger and a (perhaps too complex) food item system. Food decays over time. Cooking can decrease decay rates and increase flavor (characters' willingness to actually eat the food). Prepared foods have different ingredient components: e.g., meat, plant, minerals. This may (eventually) affect different characters differently. Prepared foods may also have additional effects aside from just sustenance.
Details of Fried Bacon item. Also note the exterior area around the room has faded out, giving a much clearer and cleaner view of the contents of the room.
Misc. - I redid the font. I can't figure out where the old one came from and I think it's just a Windows font anyways. - Combat mechanics are partially implemented. Details to come in a future post. - Title screen and menu is implemented. I'm trying to come up with a good title. - My focus right now is on getting an actual game playable. It won't have a ton of content immediately, but that can be added as time goes on. - I'm going to try to make updates more frequent. Minor feature implemented? Screenshot+update. As is I was having trouble remembering everything I had done.
I haven't made a lot of visible progress recently -- I've been trying to nail down combat mechanics and item/equipment UI, as well as experimenting with some random dungeon generation.
I should have a substantive update ready within the next two weeks. However, since it has been a while, I thought I should post a couple of screens.
I added some skeleton enemies. Not much else to say about that. They can hold weapons, but they aren't.
I really want to have a huge variety of cool loot, both randomly generated and pre-fabricated, so the item structure is fairly complex and versatile. This screen is part mock-up: the purple-ish computed damage values are fake (hence them both being the same for different base damages). The item value is also fake because I forgot to put it into the item structure. The rest come from the item definition. Items can be picked up off the ground (presumably after being dropped by enemies). Items can also sit on top of tables and other static items, and be picked up from there as well. The party shares one inventory rather than micro-manage who carries what. Items can be equipped from inventory into item slots. This screen is the result of attempting to equip the unique sword while the common sword is equipped.
Once the equipment UI is nailed down, and the combat mechanics fully implemented, I'll have another update showing the full equipment UI and explaining the combat mechanics in detail.
I finally got around to allowing the player to manually activate skills/spells. There are up to two rows of buttons across the bottom 5/6 of the screen that show the current selected character's skills. The appearance is not yet finalized, but the basic information is there: if the skill is available for use (enough mana/cooldown/reagants), the buttons are outlined. Otherwise, a pie animation (and numbers) show the number of frames remaining for the cooldown to expire. I took special care that dragging (swiping) across the buttons does nothing; the player has to specifically tap a button to use the skill. This prevents accidental use while trying to move the character.
Spell buttons with cooldown remaining. Also, some frozen snakes.
I added a new spell: freeze. As you can probably guess from the picture, this freezes the target in a block of ice, paralyzing it for a certain number of frames. The target is still vulnerable to damage, and in fact, has a small chance to be shattered from melee damage while frozen.
Special attack effects. Had to get this from a video due to my poor reflexes.
It is also possible for the snakes to poison the player's characters. The poison does a small amount of damage randomly over time, until it wears off (randomly). I plan to make a lot of these currently random or arbitrary numbers (poison damage, duration, ability to be frozen, shatter chance, etc.) dependent on stats and resists, when those are implemented. I do promise there will be no boss monsters that are simply "Immune!" to spells for no logical in-game reason, because that's dumb.
NPC conversation UI.
I started working out the UI and mechanics for NPC conversations. Like the rest of the game, nothing revolutionary here. Standard dialog tree/state machine based conversations. Since it's just me working on the project, I'm not going to waste any time writing a scripting system or anything. Everything will be done in C with macros and simply compiled into the executable. This will also make it easier to wire (hack) in special cases for conversation choices triggering other things happening in the game.
Preliminary UI for NPC conversations.
Right now, NPCs just stand around, but I eventually plan to add schedules.
I've also been busy working on a lot of new tiles; I really want a lot of varied environments to explore. Here's one that's turning out pretty well, I think.
Guess the game that inspired this one for 10 points.
Thanks for reading (or just looking at the pictures)!
Progress has been slow but steady. A lot of work has gone to streamline the asset production process, and I think it's paying off.
I bit the bullet and just animated the three additional character classes plus a snake-like monster. I'm getting faster at it, it helps that I can use existing sprites to build new ones from with just alterations.
Meet the classes. You've probably met them before.
So we have a rogue (which will be the primary PC) plus a tank, mage, and healer class. There may be others (I would like to make a ranger class, for example, with pets), but for now those will do to fill out the party of 4.
I have created the foundation for the skills system, and implemented two basic activated skills so far: the tank has a pbaoe "shout" to attract aggro, and the healer has a targeted "minor heal" that heals up to 5 points of health on a targeted ally.
Tank about to take one for the team. Or eight.
The AI will automatically use these skills when in "speed" mode, where the player controls only one character and the AI decides the other characters' moves. (I really have to figure out a better name for this). They cannot yet be manually activated; I'm still trying to decide on the best way to implement the UI to do this.
The engine now supports multiple map files, and there is preliminary support for "zoning" to different maps. Originally, I was planning on one large, seamless map with dungeons integrated. However, having multiple maps allows greater flexibility to add on content after release and possibly tack on multiplayer features in the far, far future. I am also incapable of pre-planning the topography of the world to accomodate for the size of dungeons. It is much easier [lazier] from a design perspective to make the world up out of a bunch of smaller maps that can be connected in arbitrary ways (stairs, portals, or simply "east of that other map").
So, here is the first simple dungeon, with lighting based on light sources.
Thanks to the sacrifice of the tank, they made it out. Also note the torches are light sources.
I hate snakes.
Boring performance issues
- The light maps are generated when the level loads. Apparently, just because something happens instantaneously on a Core i7 does not mean it doesn't take 30+ seconds on an Apple A4 or whatever the iPod touch uses. So these need to be precalculated. No big deal, they should compress well. And since I can take my sweet time computing them, I can occlude based on obstacles or do other effects. I do plan to implement dynamic lighting (for carrying torches, light spells, etc), my plan is to index into a small static lightmap offset by the coordinates of the PC with the light source, that should be fast enough.
- The font rendering is a serious performance hit when the text starts flowing. It doesn't help that each character is rendered (I think) 10 times.. 9 times for the black outline and once for the center. So the first step is to have the bitmap font already have a black outline. I imagine this will yield a 10x speedup. As well as fix the text fading to grey instead of just purely becoming transparent. If that doesn't help enough I can cache the rendered text as its own bitmap, it doesn't change every frame.
- If you run really far away from enemies that are chasing you, the performance will begin to seriously suffer as A* degrades. I need to cap the map search distance and enemies should give up once you've gotten far enough. They should give up anyways once aggro degrades enough, I need to look into that as well. I could also "leash" the enemies to a spawn point like in an MMO.
Thank you for taking the time to read my rambling, posting these journals helps keep me motivated. It is also nice to look back and see how much crappier this used to be, and wonder how much less crappy it can become.
After a long break from working on the game and a longer break from posting about it, I have some preliminary gameplay footage to show.
[/media] (Please excuse the graphical glitches, I'm sure everyone here understands!)
Some of the additions since the last post:
I've successfully integrated the code from the original ncurses prototype for combat, which includes an aggro system for monsters.
The party and monsters use A* to find each other for melee combat, and for the party following behind the selected character.
Support for attack animations, including weapons that are interchangable (not tied to the individual entity sprites).
Basic sound effects (thanks to http://www.bfxr.net/) and music (thanks to http://incompetech.c...c/royalty-free/).
The strictly turn-based original approach does not work as well in a graphical system. The game was very tedious, so I am adopting a more action-oriented approach, while trying to preserve the tactical nature of the engine for more interesting combat mechanics and to make the game better suited to mobile devices. Right now, the monsters do not move unless the player moves. In 'speed' mode, all the other PCs will have moves dictated by AI. In tactical mode, once a characters action frames have elapsed, the player must manually choose an action. This will need a lot more refinement as I add more combat features. One planned feature is the ability to set a PC to "hold". In action (speed) mode, the rest of the party will still move and fight, but that PC will stay in one place. This enables some interesting emergent behavior: namely, to split the party. Now, for example, a stealth character could sneak through an open but guarded front door, while the rest of the party waits at the unguarded but locked back door.
Newer marmalade version seriously improves performance. I think they must have had a bug before. In SDK version 4 I was getting around 10fps on the device, now I get about 50 (and have chosen to cap it and allow animation/gameplay frames to be tied to graphics frames, simplifying things a bit). In additon to running on iOS, I have it running on a kindle fire (android). It runs great there, too. I plan on having large-display support for tablet devices that permanently displays the character stats, inventory, etc., and separates the log area from the world view area.
I'm seriously considering hiring someone to do the sprite work. It's incredibly tedious and time consuming, and I'm terrible at it. I have put in who knows how many hours drawing that 1 sprite. I'll need at least 3 more for PCs, a few generic NPCs I can recolor for variations, and probably about 20 total of monsters and unique NPCs. I'm just concerned that even for someone who can make them not terrible, it will still be tedious and time consuming, meaning $$$.
[subheading]Graphics fixes.[/subheading] Since the last update, I've fixed the visual artifacts appearing on the device/emulator. I originally thought it might be an alpha issue but after checking over everything that was not it. I went a little crazy thinking it was something I was doing (e.g., off by one on rect size or position) but it turned out that my spritesheet needed to be a power of two size. That fixed everything.
I also greatly increased performance by increasing the maximum GL buffer size used by the Airplay SDK. Previously I had been getting memory errors, so I just threw in a Iw2DFinishDrawing() call after every single entity until I had time to figure out the real problem. Adding the following to the app.icf file fixed it: [GX] DataCacheSize=1000000 VertCacheSize=10000
[subheading]Fonts.[/subheading] Airplay SDK has what appears to be a very nice bitmap fonts API. However, I was afraid of relying on something opaque that has given me a few headaches already for something so simple. Plus, in a game, I felt I might want more control over rendering than the API offered. My implementation is very simple: a spritesheet of characters plus a text file of the character size and each character laid out as it appears in the bitmap. Right now I brute-force search each character to find its position on the spritesheet; it's a simple enough optimization to index coordinates by character on loading. I do require a fixed-pitch font, as opposed to the Airplay SDK's built in fonts library, but really that just simplifies things all around. A wrapper function to render a string outlines the text by rendering it at +1/-1 offsets in black before rendering in the chosen color.
[subheading]Tiles.[/subheading] I spent quite a while working on tiles as well. It is exponentially more work to generate semi-detailed pixelart versus throwing down some cubes with outlines. The art style was actually somewhat inspired by "Game Dev Story". After playing it I thought, "I can make this type of artwork." After researching pixel art I had some cube looking stuff, which would have been functional, but I still wanted something better. I'm still learning to do isometric pixel art, and frequently browse sites like pixeljoint and Google images for inspiration and techniques. Recently I came across the TomeTik library which has some cool roguelike pixel art. Since it's free to use, I might be tempted, but everything is wrong-sized and I'm having a lot of fun learning to do the art myself anyways.
[subheading]Orientation.[/subheading] I would really prefer to play the game holding the device upright. It is very easy to hold the vertical device with one hand while essentially using your finger as the mouse. Horizontally, it is much more difficult to do. Most people cannot securely hold the device with one hand because their thumb and fingers cannot easily reach both sides of the device. Holding on one side alone is possible but the moment about the axis of the center of force of the fingers is great because of the length of the device, compounded by the force when poking the device with the other hand. This just makes it uncomfortable and fatiguing.
However, my tiles are 34x17. With a device resolution of 320x480, there is a significant bias towards showing vertical area while horizontal area is very narrow. In a roguelike, you generally want a square view of the map. In a horizontal orientation, this is achieved. On an iPhone/iPod 4 the resolution increases to 640x960. In this case, I could render in a smaller (harder to see and point) vertical mode with an additional information display in the extra vertical space. On tablets it doesn't much matter since they are too big to hold with one hand anyways. So, the big problem is, I'm not sure how someone would actually play the game in a horizontal orientation. Perhaps some thumb-friendly controls in the corners, though I personally hate it. I would much, much rather pretend my finger is a mouse. Some games let you switch controls (Dungeon Hunter). I guess I just need to do some experiments on the device.
[subheading]Gameplay.[/subheading] Sort of. I refined the (mouse-like) controls a bit more for navigating about the map by touching the corners. The next step is to add movable entities into the map rendering and introduce an avatar. It would be really easy to just move around a static figurine but I think most people would prefer something animated since this greatly increases immersion. So, I have to figure out how to draw animated characters.
I've spent the past week improving the Map Editor. It's usability has improved greatly, but there is still a lot of room for more features to improve productivity with the tool further.
The map editor now exports the map and tile meta-information to a binary format. Tile meta-data is read into the map editor as a hand-written XML file.
I've gotten code written using the Airplay SDK in C++ to load the exported binary map information, display and scroll around the map on an iOS device. I had some difficulties with the SDK emulator getting OpenGL errors after I upgraded to 4.4. I previously had similar issues with 4.2, but after upgrading my graphics drivers they went away. I tried upgrading my graphics drivers again this time, but no such luck. It's possible I may need a new graphics card to use the emulator, the 9800 GT is a bit old but I would think it would have all the features necessary to emulate a mobile chipset. Maybe I underestimate the progress being made on hardware.
Anyways, falling back to 4.2 resolved the issues, but I'm concerned there may be other issues in 4.2 that are fixed in 4.4+. I'd also like to use Game Center, which I do not believe is supported in 4.2. We'll see I guess. I would rather avoid getting (paying for) a Mac, learning Objective C and having non-portable code. Supposedly it's possible to just have an Objective-C wrapper around C++ though.
But regardless, it is running in the emulator!
Clearly there are some graphical glitches to address -- drawing off the screen and some alpha issues possibly caused by GIMP anti-aliasing. But, it works.
It runs on the device too. I spent at least a couple hours trying to figure out how to provision the device, sign the app, and get it installed on the device. I hear that's par for the course though, and eventually I did get it running.
Next week -- I plan on cleaning up the graphical issues, measuring FPS (somewhat moot for a turn-based game, but it would like it responsive), supporting different resolutions, improving the map editor, and, time-allowing, creating more/better artwork.
Inspired by the creativity of and deep gameplay behind many roguelike games, and the small population of tactical rpg's on mobile platforms, I've decided to start on roguelike-rpg for mobile platforms in my spare time.
I feel that turn-based is especially appropriate because, for me at least, it can be incredibly frustrating trying to play real-time games on a small touchscreen, where a mis[interpreted]-tap can be instantly fatal. A turn-based game that allows the user to correct inputs also allows more time for decision making. Therefore, difficulty and complexity of the game can be increased without making it frustrating.
Unlike most true roguelikes, the game will be party-based. I know that some consider it offensive to borrow the "holy trinity" approach (tank, healer, dps) necessitated and popularized by MMORPGs for a single-player game. However, for the same reasons an MMO uses this approach -- to ensure that everyone has a role and provide variety to the classes -- I plan on employing this mechanism.
Here are a couple screens, because that is what everyone likes to see.
This is the gameplay testbed that I am using to test gameplay concepts with ASCII representations before integrating into the graphical game engine.
This is the current state of the isometric tile engine/map editor. There is some very early test artwork (top) along with the more refined tileset I am currently working on (bottom). I plan to have a large, pre-made overworld with shops, castles, etc. as well as randomly generated dungeons.
Development tools: the ASCII roguelike engine is in C, as will the final game. The map editor is written in Free Pascal/Lazarus to minimize development time. The tile engine will have to be ported to C, but this is not a big deal. The game itself will be compiled using Airplay SDK which is built on top of gcc ARM and Visual Studio for the IDE. After some initial frustration (mostly Apple's doing) I have some sample code running on the iPod.
As I said before, this is in my spare time, and this initial post represents about 3 months of work (!) so this will likely take quite a while to complete. Staying motivated on such a long-term project with sparse work periods will be challenging. I've started this journal in an attempt to keep motivated. Famous last words, I know. I'll post an update next week...