Official development blog

Adventures in Map Zooming, Part 3: Implementation

Time to get serious! Last time I told you about my engine upgrade and the new “quads,” now it’s to put them to use.

If you recall, for my initial Cogmind map zoom demo upon adding Quad support to REX, all I did was change one thing in the game: the map font size.

The game doesn’t care about the engine side of things so it simply worked, or at least didn’t crash and we could easily see how it’d appear, despite of course numerous input and secondary display issues in some other windows. By just tweaking a few more variables it would be easy to solve all those problems in order to purely have a consistently larger map view. Things get a lot more complex if we want to support both the regular map font and quads, not to mention the ability to swap them dynamically while the game is running.

But with the engine fundamentals solid and behind us, we’re ready to tackle those challenges.

Normally with UI feature implementation I’ll start by writing out a comprehensive list of everything that needs to be done, and any other elements I can think of which might be affected and therefore need testing and confirmation. While I drew up at least part of such a list like a good dev, this is one of those rarer cases where attempting to write a complete list ahead of time is probably not all that feasible or helpful, as it’s basically… the entire interface :P

With a change like this I would need to test pretty much everything, so instead of trying to be complete about it, I just noted areas of the code to be adjusted as I thought about them while working on fixing high-priority features, trying my best to finish off entire groups of related interface elements to speed up the process.

I started in the most important place, restoring the basic functionality required to speed up the rest of the implementation, like fixing map panning and cursor-map interactions. And realtime zoom toggling in order to easily compare and confirm that everything functions properly in both states.

And it was shortly after getting those bits operational that I discovered I wasn’t quite done with the engine xD

When examining the details of what still needed to be done in the map area itself, I realized that while zoomed in we’d probably also want to increase the font size of many types of text that appear over the map, especially object labels which are already integrated pretty tightly into the map coordinate and orientation systems.

cogmind_map_zoom_wip_map labels_small

Yeah these labels are not great like this, using the regular text size (ignore the fact that they’re not even pointing at the right objects here :P).

To maintain the proportionality of map-related text when zoomed in, we’d need… zoomed text. Oh no.

Back to REX

Last time I introduced the engine’s base cell size that fits individual text characters, wide glyphs for square map tiles, and the new “quad,” or four map tiles in order to enable a zoomed effect. To zoom text we’d need yet another type of glyph size, one that like the doubling of map tiles for quads (2×1 to 4×2) instead doubles text/base cell size (1×1 to 2×2!).

For me one of the first annoyances was what to call this new type, and I decided they’re probably best named after the number of base cells they occupy, meaning I had to go in and retroactively rename all the quad stuff to oct. Now our zoomed text glyphs can assume the name “quad.”

rex_terminal_grid_demo_quad_and_oct

A new member joins the REX glyph type family!

Because I had built a generalized system to simplify handling of both wide glyphs and octs (previously quads), inserting this new type was actually fairly easy (whew!).

rex_testing_console_quads_and_octs

REX again displaying operation of the newly renamed octs, and the new quads (the main new area of interest being the large olive-colored box).

Well, the initial implementation was fast, but on returning to Cogmind to apply it to map labels I found an issue…

cogmind_map_zoom_wip_label_text_shearing_bug

The text quads worked nicely in most places, but sometimes this happened. Perhaps we’ll just say this Recalibrator is corrupted and leave it at that? :P

It took a while to figure this one out, since I couldn’t quite tell if it was a Cogmind problem or a REX problem. This was particularly tricky to track down because it looked like an engine bug but also had a property that suggested it couldn’t be an engine bug, yet its other behavior pointed to it to being impossible to be a bug caused by the game itself… Anyway, a really weird confluence of situations managed to hide the real reason for a good hour. It had to do with a specific type of partial transparency of the new quads/octs, and of course it was caused by just one line of code in the engine.

Zoom Text Applications

Yay now we can have some large text on the map, too!

cogmind_map_zoom_wip_map labels_large

Revisiting the scene from earlier, this time with larger labels.

Beyond labels, I also enabled the on-map mode indicators to make use of quad text. To facilitate this (and by necessity for architectural reasons), I also refactored that part of the UI--they used to be drawn directly to the map at the end of its rendering process, but now they are a real window.

cogmind_map_zoom_item_large_text_label_category_mode_indicator

Cycling through item label categories, with the mode indicator visible at the top of the map view.

On-map popup alerts like low matter/core/etc. also got the zoomed text treatment, for one because they otherwise looks fairly small compared to everything else and would be even more likely to go unnoticed.

“ALERT” announcements are also larger now, almost too large when they include longer strings, but again having them remain at normal text size doesn’t seem ideal for getting noticed among the larger map cells. I might tweak those later when the UI undergoes more changes down the line, but for now they’re large.

I also decided to convert the program shutdown animation to the zoomed text, and unlike its other uses described above, this is the only instance in which it is used regardless of map zoom state.

cogmind_close_animation_new_strip_size_2

Cogmind’s program shutdown animation with larger central bar.

The MegaTODO

The UI is way more than just a handful of temporary popups though! Back to that growing list of challenges… well, technically most are not especially challenging, it was just a case of putting in all the necessary hours to scour the source for anything affected by the advent of new glyph types.

There were lots and lots (and lots) of alignment issues due to years of relative coordinate assumptions behind the fact that map spaces were always twice as wide as text, and both text and map spaces had the same height. Now map cells could be four times as wide as text, and twice as tall!

Most popup windows relative to something on the map needed to have their dynamic coordinates take into account additional calculations.

cogmind_cursor_hover_detection_debug_visualization

The old REX debugging visualization for examining UI z-depth and cursor hover focus came in quite handy for solving some of the more mysterious issues.

cogmind_debugging_console_index_structure_output

I also finally built an exporter for Cogmind’s window index structure to help track down some issues related to cursor input. In fact it also helped me find and resolve an unreported and difficult-to-notice bug in Cogmind’s UI that’s been in there since the very first version!

A chunk of the adaptation work actually required larger architectural rewrites, like the project of splitting the map interface into a trio of classes.

The first new class was purely to hold interface data that must be preserved during zoom events. Whenever a zoom occurs, the entire map interface is actually destroyed and recreated from scratch (far simpler than trying to convert everything over), but doing so would also lose some important info needed to facilitate various QoL features such as targeting history and resource alarm records. So data of that nature was moved to an external class to preserve it regardless of any zooming.

The second class is more interesting, a kind of container for other windows, those that are positioned over the map itself.

A number of windows such as on-map dialogue lines, combat logs, and achievement popups may need to be placed on any UI row within the map area, and these being organized under that window itself was never an issue before. But what happens when the map is zoomed such that a single “oct” occupies two rows? The map window’s grid coordinate system now no longer has any values corresponding to every odd row of the main interface, meaning its child windows cannot be placed on those rows.

So all of those map-related windows in which vertical alignment is important down the sub-row level needed a new parent window, kind of a fake alternate map window that always has a finer coordinate system regardless of the viewable map’s zoom state.

None of these informational windows are interactive, either, so this “finer map” window doesn’t need to capture mouse input and only has to occupy a 1×1 spot in the top-left corner of the map. It is a good example of an “unhidden yet transparent and therefore invisible” control window, allowing it to update normally and its children can both appear visible and use their parent as a coordinate reference (placing subwindows outside of a parent is fine).

The reason it must have an unhidden state is because that’s a prerequisite for actually updating itself and updating children, but is at the same time transparent because the window doesn’t actually want to display anything of its own.

cogmind_debugging_window_zlayer_data

Another useful debugging feature, the ability to show all windows that exist under a given cursor location and their z-depth. With the cursor in the top-left corner of the map there, it shows that there are two map classes overlapping at that location, the single-cell window container CMapFine, and the regular CMap class. The other values can show things like coordinates, indices, current colors, tile values, and any active animations at that point.

So yeah, long story short, this process wasn’t just about changing font settings and recalculating coordinates.

At this point all the heaviest lifting was done, but there was still an awful lot of residual work before map zooming could be called feature complete. I’ll share more on that next time.

This is the third in a five-part adventure through the process of putting all this together:

Posted in Dev Series: Map Zooming | Tagged , , , , | Leave a comment

Adventures in Map Zooming, Part 2: Engine-level Architecture

Taking a different tack from last time, I decided that it would be worth getting really dirty with low-level engine work for the next attempt at map zooming. One of the main reasons we’d need to go this route if there’s ever to be hope of reasonable performance in software mode: Dirty rects. If we play by the engine rules we get to keep that functionality in its existing simple package, which generally means massive savings on CPU cycles.

REX

It had been a while since I’d done any serious tinkering in “Rogue Engine X” (REX), Cogmind’s underlying game engine. The acronym you might recognize from REXPaint, the engine’s ASCII painting software I built with it for my own use and later released (dang that’s been out for over 10 years now, too, with many of its own users).

I do very occasionally add a little REX functionality here and there to cater to Cogmind needs (or REXPaint for that matter), but it’s been mature for like 12 years so there’s never been any huge developments in that time.

My plans this time were for a pretty big one: Add a third type of glyph size.

To summarize, in traditional terminal style the display is just a uniform grid of monospace glyphs, each with a foreground and background color. Less traditional, and needed to produce Cogmind’s map with square spaces as opposed to rectangular ones more appropriate for text elements, two adjacent text cells can be occupied by a single “wide” glyph.

rex_terminal_grid_demo_narrow_vs_wide

The concept is simple, though does require that text characters take up about half the width that tiles do, which can be a little restrictive at certain sizes.

So the terminal has a base cell size, though doubling the width of that base size gives another wider type of glyph that can be used as well. (I also shared a larger diagram and some related ideas under the section “mixed fonts” in my Fonts in Roguelikes article.)

cogmind_terminal_grid_demo_narrow_vs_wide

Notice how the tiles in this Cogmind screenshot each occupy two cells, delineated by the partial grid overlay.

In practice it gets a little more complicated than one might imagine from the above description, because glyphs are not drawn directly and immediately to the visible console as shown, but instead first drawn to their own subconsole, and numerous subconsoles can overlap one another at different positions. This is great for organizing an interface, though when it comes time to merge everything to create the final view, partial overlapping means you can have pieces of larger glyphs showing through, etc.

The idea is to now add something even bigger than wide glyphs, but a key point is that whatever the new dimensions are they must still be a multiple of the base cell size. We have the regular base cell size used for text characters, a wide glyph size used for map tiles/characters, and what can we extrapolate comes next for a zoomed map if we want it to retain a square aspect ratio? Enter: the quad.

rex_terminal_grid_demo_quad

Big chonker tile has arrived.

Doubling the map tile size turns 1 wide tile into 4 (2×2), so while a wide cell occupies two base cells, a “quad” glyph would occupy 8 base cells, 4 in the first row and 4 in a second row. This behavior is similar to the wide glyph, just wider, while also expanding in a second dimension as well, so introducing it to the engine logic is, uh, fun :P

I had to rewrite most of the wide glyph support in order to add quads, but having wide support already there to reference was helpful, and merging everything under the same umbrella kept the overall complexity from expanding much.

To design and test quads I loaded up my old REX testing environment, which contains a random assortment of little test consoles and behavior samples to ensure everything is working properly. One of the important things to test beyond basic functionality (which itself took a little while to get down) is quad overlap with other consoles of different types, and screen edge overlaps.

rex_testing_console_quads

Been many years since I used this thing! It was put together as the engine features were coming together back in 2011 (my first post about it).

Some of the environment is animated/dynamic, though with quads it’s more about rendering and alignment issues, and confirming that underlying data values are correct.

I got pretty excited seeing the quads appearing normally each time a new test was devised and (finally) passed.

It’s official: REX has quad support!

Fonts

REX/Cogmind/REXPaint/etc use bitmap fonts, so if we’re adding a new glyph size that means we also need to accommodate that size in the font files.

While I allow quad fonts to be loaded from file, and that’s what I worked with for the initial implementation, it seemed unnecessary for our needs as far as providing this zooming feature in Cogmind, since our main goal is to simply allow the upscaling of map tiles. Therefore another part of this engine rework was to allow quad bitmaps to be generated as needed. Basically quads don’t have to exist until a given font set is actually set to be used, at which time the bitmap will be generated in memory by upscaling a specified source bitmap which has already been loaded.

Cogmind

Then there’s Cogmind over here not having any idea what’s about to hit it. Hm, what will the impact be? My first quick test was to simply switch the map font to a quad and just… see what happens!

Well for the most part it Just Works. Wow. No crashes, just big tiles.

There’s some obvious kinks like the fact that I didn’t even change the map view dimensions, causing the map view to also quadruple in pixel size and extend off behind the HUD and off screen, therefore “centering” Cogmind in the bottom right corner. That’s to be expected, along with other issues like console alignment and any other source code references assuming the map view is using wide-type glyphs.

But the important thing is that IT WORKS.

cogmind_zoom_map_first_sample

Cogmind’s very first use of the new “quad” glyph support added to REX.

That ain’t no mockup. Also because it’s playing by the engine rules there is zero performance hit from this feature. Zero.

You can see the UI jank--to record that I had to turn off autocentering and use the mouse for directional input, plus the misalignments and weird stuff in various locations (check out the items in the inventory xD). BUT IT WORKS.

There is clearly still a lot to do. Manually test swapping the font is literally all I’ve done so far on the Cogmind side of things--the size can’t yet be toggled dynamically, but before starting this whole adventure I did prove it could work in theory by testing whether the game would explode if I tried to destroy the entire main map interface and recreate it on the fly.

The disparity between the surrounding UI text size and map tile size when zoomed is kind of annoying--it’s not quite the same aesthetic, but if it means some people who otherwise might not be able to play could now do so, I guess that’s a good thing! Also again I find myself wondering what portion of potential players will find this sufficient since it doesn’t address text, but maybe in combination with the Terminus font it will work for most people. We’ll just have to find out.

While doing the latest map zoom experiments I also came up with an initial list of complementary feature ideas, those that could help blunt the negative impacts of having a much shorter view range than usual.

  • Cogmind may not necessarily be centered when zoomed, instead having the view gradually shift so that you can see further and further in your general direction of travel, out to your actual sight range. Cogmind’s unmodified sight range (16) while truly centered in a zoomed view would extend at most about 4 spaces out of view in the worst case scenario--a north/south direction, so Cogmind would generally be within that distance of the center unless sight range is further boosted. (East-West direction is less of an issue since the view is a horizontal rectangle for most people’s screens.) I can see this dynamic view positioning being fairly complicated to implement well, but a good formula and related behaviors there could save the player a lot of time that would otherwise be spent scrolling around.
  • The above feature is likely more appropriate for keyboard users, not mouse users who wouldn’t generally be happy with a map sometimes shifting to a different position under their cursor during successive movements. For that type of input it would be nice to have a way to quickly set your own relative centering position, depending on the direction from Cogmind you wish to see more of while moving or performing other actions.
  • Labels for important things, especially hostiles, that enter FOV but are not currently in view can be shown at the edge of the view in their direction. Or perhaps not the whole label, but more like the floating indicators that appear to denote an offscreen drone or Cogmind location. Cogmind already stops and labels new hostiles, so this would just be an extension of that feature to accommodate zoomed folks who want to have a little more info about the cause. Heck, maybe in temporarily pausing the action it could even shift the view over a bit to directly see the cause?
  • For new players, zooming the map could perhaps assume they would like everything to be larger or more readable, in which case maybe it’d be a good idea to also automatically switch the font to Terminus at the same time? Just a thought though, not a fan of this approach, and I think it won’t be nearly as relevant given the nature of future planned UI updates…
  • This one’s just fluff, but I can see feedback SFX and an optional very fast animation for the transition between zoom and standard view, for people who want to use both and do it in style :)

Lots of optional features out there, it appears, though exactly how many of them are actually useful, and more importantly can actually be implemented in a way that brings out that usefulness, remains to be seen.

Anyway, those are just some general notes for now, and I haven’t done any real playing with this feature active, but later once it’s actually built and not hacked together I’ll definitely be trying out some runs to see what about this setup irks me and if there’s anything I can do about it.

Although a zoomed map this isn’t the kind of feature I want to use, I imagine it could be useful to others, and look forward to seeing where development takes it. I’ve always loved working on UI to begin with :)

This is the second in a five-part adventure through the process of putting all this together:

Posted in Dev Series: Map Zooming | Tagged , , , , | 2 Responses

Adventures in Map Zooming, Part 1: Realtime Image Scaling

A few years back I introduced an experiment to demonstrate a potential “overmap” implementation that still obeys the rules of the terminal interface. What about the opposite--a way to zoom the map itself? Obviously this would be intended for a completely different purpose, addressing one of the more common complaints about Cogmind, that on some displays and play environments everything is rather hard to see.

Prior to this I’ve always framed the zooming discussion as a full-UI thing, where not just the map but everything needs to be larger, which is kind of a show-stopper when there is a minimum number of text elements required to be visible at all times for proper play as designed. But maybe if we only zoomed the map it’d work for some people who otherwise can’t play?

It’s hard to say whether this would satisfy some people since there’s still the text elements, but maybe for example using an alternative font like Terminus is sufficient for those parts, and the map is what we should focus on. Anyway, it could be worth experimenting with, and I’ve moved up the timeline for doing that.

Why now?

I’ve always been interested in experimenting with larger alternative interface layouts, though because I didn’t see much promise in them, and doing so deviates from the core design, the idea was to wait until at least a likely engine update down the road, as well as the completion of most of Cogmind’s content.

Well, this year money issues have had an influence on my near-term direction :P

Revenue has fallen quite a lot, I mean it has been over 10 years of dev at this point, and now that Cogmind is being developed at a bigger loss I need to start worrying about revenue again… (this will also likely lead to some release timeline adjustments in the future, too).

Anyway, to the issue at hand, hopefully with a larger map view Cogmind will be able to appeal to enough additional people who are otherwise okay with the rest of the game--I know there are some out there, and it’ll be better for revenue going forward!

On that note, I must thank all patrons for making the ongoing expansions much more feasible. I’ll admit expansion-level content releases for a niche game without explicitly charging for them isn’t really feasible forever, but I don’t want to split the game world into DLCs--it’d be bad for the design so it’s all or nothing, and there is just so much cool stuff still to add. It must be done. It will be done :)

It’s time to experiment!

Mockups

Any proper UI work is likely to start out with mockups--might as well play around with relatively simple images before investing a greater effort into code…

cogmind_zoom_map_mockup_size18

There you have it, a mockup depicting Cogmind using a size 18 font (Terminus for better readability overall) combined with all map tiles doubled in size (1080p@16:9, the most common Cogmind player resolution). (open for full size)

Okay so each tile actually occupies four times the usual amount of space, but what we mean here is that the cell dimensions are doubled. Something in between 1.0x and 2.0x might be more ideal from a size and visual balance perspective, but doubling is more feasible for retaining the actual aesthetics, both in terms of cell alignment and pixel accuracy, and might also provide us with other benefits later.

The mockup is also missing some components that eventually must be considered, such as what text over the map might look like as far as object labels and other info overlays, but that’s not important right now, more of a detail to consider when the time comes, assuming the fundamental feature even works out at all.

Architecture

It’s time to enter… the zoomiverse!

cogmind_zoom_map_imagebased_wip_blooper1

Okay this is an early blooper, we’ll get to that in a moment ;)

Just how to implement selective zooming in a terminal emulator that is made to do no such thing is a bit of a dilemma.

Terminal-based engines don’t behave like a normal game engine where you have individual windows represented essentially as images layered on top of one another and their contents can therefore be scaled individually. Instead there are many layers of cell data from different subconsoles that feed into a single root console which is then converted to the final image.

Under this kind of architecture it’s not all that reasonable to insert images into the mix, or make modifications to entire subconsole properties of the variety which are easy and obvious to apply to images. We can’t go “oh sure just tell the computer to zoom that window and we’re done with it!”

Sticking to the terminal system’s constraints is great for helping maintain visual consistency, and keeping the overall architecture and interface relatively simple, but if we want to zoom the map things are going to get complicated beyond the scope of what the engine can normally do on its own.

Over time I’ve brainstormed 4 different theoretical approaches to zooming the map, and most recently expanded that to 5~6 (an exact count depends on how different one needs to be in order to be considered unique). Some are more involved than others, and each comes with their own tradeoffs, though having no actual experience with this feature in practice, its true complexity and scope are not immediately apparent. Therefore it makes sense to start with the easiest, least intrusive option regardless of all other factors, just as an experiment to gain a better understanding of what the results feel like, and collect a list of design issues that would need to be tackled to make this a reality.

Realtime Scaling

The first and simplest method is absolute brute force (of course :P). Let’s stretch some pixels.

Sounds easy enough to take the map area and blow it up, yeah? Well, not really xD. Cogmind doesn’t know anything about images, and the engine doesn’t know anything about Cogmind or its UI structure, so we’re going to need a little extra communication between the two on this point.

Basic steps describe the cooperative process:

  1. Cogmind registers a callback function with the engine, letting it know that it wants to zoom an area of the interface every frame.
  2. When the engine is about to render a frame, it first lets this function know about it and expects to be handed an image in return. That image is created by Cogmind itself by forcing the interface to render [mostly] normally in between frames, copying a central portion of the map view directly to an image, then scaling it up to fit the normal view dimensions.
  3. The engine finishes rendering its normal frame, then at the end of that frame takes the zoomed image sent by Cogmind and copies it over to the desired area before displaying the final results on the screen.

If this sounds terrible, that’s because it is :P

The performance of realtime software scaling is no good, with a first iteration tanking my FPS from 240 to 40, and that one wasn’t even working right. Once it got “fixed” the real FPS was more like 24, definitely far below acceptable.

But it did work! Hacky and incomplete though it may be…

cogmind_zoom_map_imagebased

Still image of a zoomed Cogmind map, working in game, based on realtime software scaling.

Here it is in action:

cogmind_zoom_map_imagebased

Them’s some big ASCII--a working realtime software-scaled map view in Cogmind.

I say “in action,” but really only keyboard input would work in this test since the mouse still doesn’t know anything about this image resize weirdness.

Essentially in this form it’s nowhere near complete, and not performant either. While there are plenty of potential optimizations, optimizing this kind of architecture makes little sense since much of the work would become obsolete by an inevitable switch to hardware acceleration, yeah? Scaling and copying a few images would be nothing for a GPU, but for now Cogmind is CPU-bound and that isn’t changing in the near term.

A few other problems I noted:

  • Tons of artifacts created when toggling the zoom (I believe any such zoom feature would need realtime toggling).
  • An image-based approach is not directly compatible with some other interactive visual systems that expect to have cell-specific knowledge at various locations, so there would need to be a layer of translation that tends to complicate things.
  • Not only is an image-based map unable to take advantage of the normal dirty rect system, in fact it requires turning off that system completely, meaning the engine is always rendering every frame in full. That’s pretty slow, compounding with the software scaling work. In my fullscreen tests, forcing a full render every frame in the normal game gives an FPS of 60*, while realtime image scaling drops it to 25. I managed to up it to 30 with one optimization, but it’s still far from ideal, plus you don’t really want to constantly be rendering at max speed in the first place, even as a cost of getting a map zooming feature. *These speeds are in my dev build, which has a lower FPS than released versions, so I’m just looking at it for relative comparison. (Aside: “Dirty rects” are an important concept in gamedev, whereby you keep track of known areas of the screen that have changed since the last frame, for example defined by a list of rectangles, and only update those areas during the render, since any unchanged areas should remain the same and don’t need to be updated. This is also where artifacts may originate in a game’s display, where perhaps an area changed but was never marked “dirty” for updating along with everything else.)
  • The zoomed area would need more nuance, probably in the form of a mask, since it doesn’t distinguish what’s in the target area at all and simply scales everything, so you try to hack a machine and get this…
cogmind_zoom_map_imagebased_hacking

Many different UI elements can appear over parts of the map view, not just the map itself :/

As with any project dealing with rendering work, this one had its fair share of funky bloopers along the way. One of the main issues was a logic error causing the map to repeatedly zoom itself, resulting in a recursive scaling effect.

cogmind_zoom_map_imagebased_wip_blooper2

Had some funky problems with coordinates for zoom centering, too :P

cogmind_zoom_map_imagebased_wip_blooper3

The Next Step

The map zooming implementation as shared here isn’t ideal, or even acceptable, though the good news is I do have that longer list of possible methods, and will be working with one of the better, if more involved, ones that could solve all the issues presented here.

A smarter approach should play by the engine’s rules, but will take a while longer to implement. The important thing is that playing with this idea showed me what it would feel like and gave me an opportunity to formulate concepts for some promising complementary features which might make this more feasible in a UX sense as well.

Before properly testing out those ideas, however, I’ll need to put together an implementation that won’t try to fry my CPU ;)

This is the first in a five-part adventure through the process of putting all this together:

Posted in Dev Series: Map Zooming | Tagged , , , , | Leave a comment

Experimenting with Drone PIP

Early this month I was streaming a Cogmind run on Twitch, at one point once again sending out drones to scout around as I like to do. Drones are generally pretty fast, and I’ll often just make sure I’m in a relatively safe spot and keep an eye on what the drone(s) find while I wait and decide where to go next.

The drone centering and following feature added back in Beta 10 has been quite useful for this purpose. (For years before that you had to actually scroll the map yourself!)

cogmind_drone_cycling_with_fov

Cycling through active drones to see their surroundings, which also allows passing turns while following their view.

But in this particular stream as I sat there waiting to see what they’d uncover, I also kinda felt like it was a situation in which I already knew where I wanted to head, but it would be somewhat tedious to both move and keep an eye on what the distant drones were up to before they splat on some trap or were blasted by a hostile squad.

I blurted out that we need a drone PIP (picture-in-picture) feature to make it easier to operate while scouting drones are active, and of course ever since I mentioned that it stuck in my head, just asking to be explored as a feature. So I found some time to try it out a little while ago!

The technical premise is pretty simple: Since Cogmind is a monospace terminal interface, when drawing the map we just have to find some space in the view where we can copy over a portion of the cell data from the drone’s surroundings to somewhere the player can see.

Finding this space isn’t too difficult since Cogmind mechanics and UI were designed to fit a 4:3 display anyway, despite most everyone these days using 16:9 or higher, meaning there is usually a decent amount of space available at the left and right sides of the map view which is not as vital to be able to see at all times. Those are the spaces we can cover with other things, and is also why you see non-modal info presented in those four corners for various purposes.

cogmind_map_corner_ui_element_sample_excerpts

Sample info that can overlap map edges: Detailed combat log to the top-left/left, audio log in the top right, special mode menus to the bottom left, and achievement notifications in the bottom-right corner.

Anyway, I wouldn’t be worried about coming up with room for a proper implementation, though I was interested in seeing how it feels when active, since having such an interface feature working even in experimental form has a way of triggering deeper thoughts about potential roadblocks or related features.

Experimental PIP

Lo and behold, a basic drone PIP in action…

cogmind_drone_pip_test

Pretty cool! This didn’t exactly take all that long to implement for testing, but that’s all it is here, just a quick and dirty experiment thrown together in order to watch it, not even 50 lines of code or so.

The process is quite simple: When rendering the map, check if there’s an active drone and pause the rendering to first force another render around the drone’s own location; save the console info from around the drone and return to finish the normal map render, then when that’s complete copy the drone visual back over the map area wherever the PIP should appear. In the sample above that’s the top-left corner.

I’m not planning on adding this feature for now, though building it would require thinking about how the window interacts with other UI content that can appear in locations it might occupy, and the best default location. It might even be interesting outside the map, up in the top-center console, though that comes with its own problems in addition to that area’s relatively limited height.

There’s also questions about whether and how to get the window itself to properly display other UI-related content that can appear in drone-explored areas, for example (and most importantly) item/enemy labels that don’t otherwise show as you can see in the demo above.

Proper PIP

What would it take to turn this into a real feature, besides not being pretty hackish code :P

Well the PIP only needs to activate once the drone is no longer visible on the map view, but okay that’s super low-hanging fruit, let’s try the more complicated stuff…

  • Maybe window dragging to actually put the PIP monitor wherever you want
  • If currently following/locked onto a distant drone in the main UI, the PIP could perhaps switch to show the area around Cogmind’s position instead
  • Multiple simultaneous PIP panels for more than one active distant drone (now I’m imagining having a boatload of combat drones out working for you and Cogmind is like the security guy just watching everything play out on a dozen monitors xD)
  • Setting your own “PIP point”, for example around a Terminal with an active tracking Trojan
  • Of course there’d be customizable PIP size

As you can see, this one UI feature spawns lots of neat ideas…

It’s also a ton of work though, and based on its effort:usefulness ratio I have to assign this one a pretty low priority. Although shelved for now, I might revisit it alongside the next big drone mechanics update I want to do?

Posted in GUI | Tagged , | Leave a comment

Projectile Deflection

Ever since my first design docs from Cogmind pre-alpha, written back in 2013, I always wanted a projectile deflection mechanic. Like it doesn’t get much cooler than that, being able to swat away bullets or even send beams back at an attacker, or redirect them into other targets.

Every few years I think about the concept again, and it finds its way into my ongoing notes in yet another location in some slightly-altered form or alongside some other content idea, begging to be implemented. At the same time, being so cool it’s likely one of those rarer abilities that ends up more suited to unique parts, and even after ten years of development had yet to find a proper home on Tau Ceti IV.

One day several months ago I decided the wait had gone on long enough and this mechanic needed to happen now. Who cares if I didn’t even have a specific use case yet?

This marks the first time in Cogmind history that I implemented a new mechanic before actually having a spot for it in game--I had no idea what item(s) or robot(s) would make use of this feature. But I did know that we’re now in the Era of Cool Expansions outside the core game, so I’d find a place before long, and unfortunately around that time I also need a smaller project to tackle while getting my health back on track after repeated concussions (seriously annoying and a huge drag on development for much of this year). The opportunity was ripe to implement something fun and compartmentalized, as opposed to the grand projects I was supposed to be working on at the time which would take a lot more brain power.

Not Recommended

In gamedev it’s generally a Bad Idea to do this, building mechanics for your game that you aren’t ready to apply anywhere. Having one or more detailed use cases helps you think through your specific needs and acceptable limitations, otherwise when it comes time to use a generically-implemented feature for an unplanned use case, you may either find there are problems or insufficiencies and have to rewrite it, or eventually discover that you did too much work because you’re never going to actually use all those features or options you built in anyway :P

I already know I’ve built a system that’s probably more flexible than I’ll make use of, based on a lot of hypotheticals as opposed to real world scenarios, but at least it includes a set of features I do know I want.

The main other aspect to worry about when prematurely constructing any non-simple system is that when it comes time to use it and you find the system doesn’t quite fit your real world needs, you then have to go back to make adjustments, which can easily be more time consuming than it would have been if the initial implementation happened at the same time, given complete familiarity with the system at the time. It’s just potential for extra overhead, really, but dammit I wanted to see projectiles bouncing around!

Aside: This whole section strongly reminds me of those who design, build, and expand game engines without actually using them to make a game, though that’s on a different scale altogether.

Flexible Deflection

So I tried to cover all the bases by building a flexible implementation for projectile deflection, identifying tweakable parameters in order to hopefully support a range of fairly different items, of course all still centered around the idea of making sure projectiles hit something other than their intended target ;)

Among the main features of this system:

  • random deflection within a specified relative arc
  • deflection that always counterattacks the source
  • redirecting projectiles to target nearby hostiles
  • categorization of projectiles for deflection purposes, and the ability to specify a category to deflect, or deflect all of them

Architecturally, deflection of projectiles is somewhat related to the penetration and guided waypoint systems, which served as a good starting point for implementation. The main requirement is to be able to give the projectile a new trajectory at the right time and let it continue on its way.

On that note, it’s nice that there were actually multiple indirect benefits of building a deflection system, improving the game in other areas along the way, including addressing the longstanding issue of guided projectiles always treating weapon ranges from the original source, rather than by measuring the actual path traveled, enabling them to exceed their maximum range in some cases. It wasn’t too much of an issue, hence why I’d left it like that for years, but this also factors into play with deflected projectiles, so it was about time to do something about it--projectiles traveling along a non-straight path now measure cumulative range for accurate distance calculations:

cogmind_projectile_cumulative_range_limiting_guided

Firing a guided projectile to the left here and reversing its direction will not reach the targets on the right, but if firing to the right they are all in range. Before this update, firing to the left and circling back around would still work. Not a useful tactical situation by any definition, just demonstrating the difference in action :)

Shiny Applications

So while I had no spot in Cogmind for deflection just yet, or any plans to even include it in the next release, the soonest I saw it appearing was with the Unchained, a deadly group of hostile unique derelicts working for MAIN.C.

And no doubt beyond that as well, since there are a good number of ways to use this new tech. When we think of deflection, the obvious use case is in defensive shield technology, but most any item is allowed to have deflective properties, meaning we must have an energy sword that can deflect incoming projectiles. Because duh.

Below are some recordings made while I was building the system. Note they’re all just test shots with fake items I was using to make sure everything works as expected, so don’t read anything into that aspect. These are also not usually very realistic scenarios, either, just having a bit of fun :)

projectile deflection demo

The very first system test, deflecting grenades back in the direction they came from within a 90-degree arc.

 

projectile deflection into enemies

Similarly deflecting incoming shots within an arc, but sending them back into an enemy within that arc. Cogmind is not firing a shot here, just passing turns :P

 

projectile shedding deflection

Deflecting kinetic projectiles backwards, like shedding them off to the side.

 

missile deflection into enemies

A 360-degree deflection capability redirecting an incoming missile at a nearby group of Swarmers.

 

projectile bouncing ring

Spectating a dangerous game of hot grenade with the local opposing Demo squads.

 

projectile deflection animation

The system also supports per-item animations and SFX for the deflection, seen here using a random placeholder to confirm that it works. (You can also see there deflection benefiting from the cumulative projectile range limitation feature, unlike the earlier shots before that was implemented.)

 

projectile deflection in combat log

Also yes, deflection is recorded in the all-important revamped combat log coming to the next version.

Well I can finally cross deflection off my list!

Funny enough, back when I first wrote about building this feature on Patreon, there really was no intent to add any deflection-related items to the next release, which is already packed with so much other stuff. Fast forward to a couple months later and there are already no less than three different such items xD

This is the fifth and final post in a series on new item mechanics. I didn’t cover anywhere near everything (or even the coolest mechanics because I don’t like to spoil much :P), but some of these also offer a chance for relevant discussion of the bigger picture:

Posted in Mechanics | Tagged | Leave a comment