Hmm, it turns out I post sufficiently infrequently that I've made barely any mention on this journal of the
Ren'Py TileEngine and UnitEngine that I've been working on since Christmas. It began its journey as just the isometric engine for my planned tactical-combat ren'ai game. Then it turned out that the
Lemmasoft forums were celebrating their 5 year anniversary, and people were being
encouraged to create resources that'd be useful in visual novels and release them for anyone in the community to use. So I volunteered to take my isometric tile engine and make it available to anyone who wants to write a Ren'Py visual novel with some segments taking place on a tile-based map (either isometric or square-grid).
I've been working on this for a few weeks now, and things are in pretty good shape, although there's a lot to do with just one week to the deadline of Feb 25th when I want to release it to the OELVN community.
So, the TileEngine will currently:
- Display a map made up of isometric tiles, at two heights: "terrain" and "obstruction". All "obstruction"-level items appear above all "terrain"-level items.
- Create Sprite objects, which will store a grid x and y coordinate and display the sprite on the grid, by default at the "obstruction" height.
- Display all this inside a scrollable viewport.
- Display a cursor sprite.
And right now, the UnitEngine that sits on top of the TileEngine can:
- Create Unit objects, with a controller, name, position, DirectionFacing, current and maximum Movement Points and Hit Points, and so on. Updating the unit object's position, DirectionFacing etc will redraw it in the new position and orientation.
- Display an overlaid menu indicating the current unit's status, and offering buttons to perform assorted actions.
- When you click "Next unit", automatically cycle through the active units which are controlled by the player, still alive, and can still move or act this turn.
- When you click "Move", automatically calculate which squares on the map are reachable within the current unit's remaining MP, taking into account obstructions, and highlight the reachable squares with a clickable highlight. (Making them clickable shouldn't be a big deal, but it is, since in Ren'Py there's no way to detect clicks on a normal image. I'm having to jump through a couple of hoops to achieve this.)
- Call callback functions when the player selects a unit, moves a unit, performs an action (attack), etc.
Still remaining to do on the TileEngine:
- The option to make it take square-grid tiles instead of isometric tiles. This shouldn't be too much effort, as I've kept things pretty modular: there's only about 3 or 4 functions that know the grid is isometric, the rest all just use them.
- Let the user move the cursor sprite around with arrow keys. This should be pretty straightforward as well, using a Ren'Py ui.keymap.
- The function to centre the scrollable view on a given square hasn't worked since I refactored the code to use ui.viewport. I just need to figure out the correspondence between screen x/y coordinates and the properties of the Ren'Py ui.adjustment object.
And still to do on the UnitEngine:
- The Action / attack system. This is the biggie. I need to specify the format in which the user will supply allowable actions, create a menu from that, hook into the user-supplied "determine legal action targets" criteria (and provide some basic ones myself), and provide support for death animations when units
- I need to support the AP model more explicitly. I think the engine may be slightly MP model-specific at the moment.
- I need to handle leaving the UnitEngine for a VN segment, and re-entering it either into the same combat or a new one.
- Fix the bugs in the movement cost calculation code.
- The overlay displaying the unit's status needs to be more customisable.
- I need to test a whole bunch of features in more contexts than just my one tactical-combat game.
- I'm not promising any AI, but I at least need to provide an interface for the user to supply AI.
Surprisingly, the current issue I'm facing is performance. Scrolling around the map when it's only displaying a few hundred tiles and a handful of sprites is surprisingly sluggish. Ren'Py is normally pretty quick, so I suspect I'm doing some things suboptimally. I know what a few of the basic optimisation mistakes look like, so I'll have a look for such things. I already tried replacing some division that happens in a loop with multiplication by the stored reciprocal, but Python's integer division is good enough that I lost more than I gained in that.
There's an awful lot remaining to do, compared to the seven days left. I'm getting the sinking feeling I'm not going to get it finished by next week, which will be rather vexatious. Principally because I feel like I ought to have been able to achieve it within the month. But, well, there's still seven days to go, and I've pulled out astonishing creative bursts in the final few days
before.