So then I got distracted by other projects. Well, kind of. See, the old phantomnation code was very... awkward. It wasn't timed, at all (the little animation present was based totally on frame-counting, so if it ran on a computer ten times as fast it would react ten times as fast— like those old DOS games), and there wasn't really any way to do non-trivial interaction (hence why after two years the only 'interface' was still just panning & rotation)... etc.
I started work on some timing loops and then moved on to drawing UI elements (something else i hadn't figured out yet) and then to getting a working graphs library (you can see notes re: the early phantomnation graphs code in the previous gallery; it really wasn't good) and then to getting text drawn on the screen... and most of that was on projects totally unrelated to phantomnation, so when i hit a stopping point in one of the other programs i was working on, i went back to good old phantomnation.c and did a double-take. ("But... where's the program state structure? where's the timing loop? how was i planning to do interaction?" and so on. user interaction was actually what stalled my progress back in march & why I started working on timing loops to begin with.)
But I only got the very rudiments of user interface started when I switched back to working on phantomnation, so the "how do i get this working?" screenshots are applicable for this gallery. And this was such a big change (and there was such a large gap from the last update) i figured i should start a new page!
AND THERE IS THE STORY OF WHAT I HAVE BEEN DOING THE PAST FEW MONTHS. also i moved and quit my job. BUT NO ONE CARES ABOUT THAT: ON TO THE SCREENSHOTS!
I managed to get text drawn and showing up on top of the 'ui panels' (currently just a coloured box with no texture; i'll work on that once i get more important things done) but there was the issue of transparency— the font is loaded from a png, and i'm using the glpng library, so I can stencil out the hot pink background, but then it just gets replaced by a black background...?
So i thought, hey, maybe it's not a black background to the polygons themselves, but the polygons being blended with the black background? (first time I tried it I got black text on black background, which was very confusing) ...Even though a more reasonable target to blend with would be the tan UI box, but...
hence the shaded backdrop. and hey, i was right. but then i had the blue backdrop cutting through instead of the tan and that did not look any better. No one but another OpenGL programmer will care, but I had been drawing the UI boxes backwards with depth testing ON because i'm dumb, and then i switched it to draw forwards with depth testing off, which made the blending work right. Except now that i was drawing it forwards i had new problems, because the height of the UI box depends on how many lines the title is and now the UI box was being drawn before any text. So it was always a line ot two too short. With very confusing results, esp. because the boxes are all tan and you can't tell when they overlap (hence the overlapping text in this shot— the box ends but you can't tell, and then the pink text blends with itself and becomes unreadable).
So i kludged it so it by drawing an invisible title text first, getting the line count from the function, and then drawing the box followed by the real title. Overly-complex and a bad design choice, but it works okay. (I'll write the line count code into the menu function itself later.) BUT THEN, i have the problem, introduced by the same depth-test reversal that fixed my blending issues, of UI elements being placed under battlefield elements (in this shot, represented by a single hex because i haven't rewritten the generator function to not suck yet). My life, so hard.
So THEN i moved the ui-drawing code to after the battlefield renderer, only to realize that caused issues with modelvideo matrix camera transforms. so the ui panel rendered all squished. One judicious application of glPushMatrix(); LoadIdentity();
later, and the menus all work fine! Aside from being clunky and unfinished, that is. I'm sure when i go back to rewrite them in a few months (or years, knowing my coding speed) i'll be just as vexed by the terrible quality as i was when i looked at my old map code for phantomnation.
Here is how it is: i've got working, albeit unwieldy, menus; a timing loop; and most of the old battlefield code. I'm working on actually drawing unit sprites & animations only what, two years into the project? If this productivity continues, i hope to have something playable (by which i mean having the full menu input→battle action→state change→unit time charge→menu input loop working. minimally playable) in a week. ...we'll see how that goes.
Oh yeah, and I changed the aspect ratio. The new windowing code is from my other project, which involves a first-person view, and I hate using 3:4 aspect on a first-person view SO MUCH (it is like suddenly having absolutely no peripheral vision!) so I use something like... I think 9:16? much wider. Not sure if I'll keep it for phantomnation.
THAT'S NOT RIGHT. (also, after i fixed this bug i created one where the sprite displays would rotate against the rotation direction, which lead to extreme confusion regarding what direction the unit is 'really' facing. but, ha ha, i can't screenshot animation errors!)
In which my perpetual confusion regarding which functions take arguments in pixels and which take them in coordinates comes to a head.
I always go 'oh well it's okay if this code isn't the most sensible code out there; it is finished and it works okay' and then end up spending way too much time breaking it when i have to rewrite the code for some reason or another. I should stop doing that. I also keep forgetting that a supposedly 'normal' coordinate graph has the y axis pointed up. what is with that? At this point, i'd flip it, but that would mean i'd have to rewrite so much code. sigh.
(in case you're wondering, the more detailed menu texturing in the oversized screenshot was removed because i only wanted to store one border-edge texture, for various reasons [if i wanted to store border textures for each edge, i'd have to make and load four different png files— you can't easily repeat the edges (your options are either to draw a separate quad [totally separate— no GL_QUAD_STRIP allowed] for each 16x16 square or to make a pattern that reflects well, which my design did not [although of all the options that is actually probably the best one]) unless they're each their own texture. lame.] and that meant i'd have to make whatever pattern on the menu have twofold symmetry, and the only twofold-symmetrical patterns i know are not exactly menu-background material [by which i mean not abstract enough— curse you, history of videogame spriting!])
I will admit, i did not start that paragraph with the intent of adding so many paranthetical notes, but once it started happening i was glad to continue.
Man, i aint got no clue what is up with this. as usual, region generating is being a terror. Something to do with my new stack code, i think. which is ironic, because the whole point of the stack is to keep the region path contigious.
also i had some amusing, odd, and/or vexing errors when i was trying to get heaps and pathfinding working, but they were all boring text output. I wanted to make sure they worked right (or at least weren't obviously broken) before unleashing them on the visual side. then i figured i should finish rewriting the region generator before adding pathfinding. AND THAT LEAD TO THIS. aaargh. I suspect another gutting of the function is in order. But on the plus side: hey, i finally wrote a working version of Dijkstra's! I assume. on account of not having tested it because of all this ineptitude.
I should really avoid writing the gallery comments right after giving up on coding for the evening; i am always so full of bitterness at that point.
my life, so hard. It wasn't very hard to fix the region generation this morning (as mentioned in yesterday's note, i keep forgetting how my new stack code works vs. the old code, and because of that i kept coding really dumb errors) but after i got that working i set out to get tile sloping working.
I keep getting deja vu when i run into the exact same problems recoding region stuff. sigh. Anyway, the problem here was that i totally forgot how the tile direction enum worked, only i was SO SURE i knew how to do it right and hey, why was it not working? MAYBE IT IS COSMIC RAYS, BECAUSE I KNOW I AM RIGHT.
in my defense, the proper edge alignment of 0 to 4 and 1 to 3 seems pretty counterintuitive to me. in fact, there's a condescending entry in this log where i make the exact same mistake, back in sept. 2007 (and then there is me going on about how i am so dumb two days later when i catch that bug). hence the edge ripping errors in the two screenshots to the left. The first was actually because i had accidently flipped signs (and thus was adding when i should have been subtracting and vice versa). and i forget what the error was in the second. Something to do with part of the edge code flipping signs. I didn't actually take any screenshots of the usual edge ripping bugs, on account of there are like thirty in the first & second gallery.
VICTORY
and now to snatch defeat from the jaws of victory, i am going to try to get tile joins working properly, finally, before testing the pathfinding & moving code. I AM SURE THIS WILL END WELL AND WITHOUT ANY FRUSTRATION AT ALL.
paaaathfinding!
The 'error' here is kind of subtle. By which i mean not visual. So, now that i have pathfinding working... i have yet to code any picking code, so there's no way to tell the game what tile you want to move to. sigh. I was all excited, too.
(also note the incredibly primitive 'highlighted tile' code, in which i just draw a purple tile right on top of the normal one. I... should work on that)
but hey, once i have movement down i only have to code one final thing (ATTACKS) before the game is theoretically playable. also, uh, AI. but, you know.
fig. a, in which is displayed the purple-polygon mass of movable tiles as well as the red-polygon mass where the pickable polygons are rendered. If the pickables were rendering correctly, the red cluster would perfectly shadow the purple cluster. As you can see, that is not the case.
fig b., in which i realize that the unit-drawing code has very significant errors in it. which is what i get for only testing drawing sprites at the origin.
In which my first attempt to fix the unit-drawing bug goes terribly awry.
For the record: evidently, when you want to billboard things the proper way to do it is via changing the position of the drawn quad, e.g. by using sin() and cos() functions, not by messing with the view matrix. The specific error in this case was just that i rotated the view matrix around the wrong axis.
I hate tile joins so much.
(there was one bug that i did not take screenshots of which ended up to be because i forgot to add the tile offset to a direction check, so every tile checked the tiles surrounding the origin tile [0, 0] instead of their real neighbors.)
arrrrgh
I am pretty sure there is a sloping bug here, too.
In which i got frustrated with minute tweaks of sloping values and decided to try a larger value. uh. yes, that particular line of code was being reached.
So, first I noticed a few weird errors in tile joins. Then i fix them. Then i noticed some weird errors in sloping. Long story short, randomly reordering the tile direction enum does create bugs! I was surprised. Then i just felt stupid. But then i fixed the problem. (in short, the sloping code expected directions to correspond to the edges enum, but the join code expected directions to correspond to the inverse of the edges enum. so i ended up with two bits of code that would never work right at the same time.)
So now, hooray, i have both sloping and inner joins working properly.
At least, until i decide to recode the overlap code, at which point i fully expect everything to break again. Now that i think about it, this is probably the reason the FFT engine allows for overlaps but they are only used in like, two battles. THEY ARE VERY HARD TO GET WORKING PROPERLY.
Back to getting pickables working properly. The problem i am having here is that the renderPickables() function doesn't draw the tiles in the proper location, due to... something i don't understand yet. But while testing out the function, i noticed that the red tiles weren't blended with the unit sprite, because they were getting drawn after the unit was. So i made them draw before the sprite, not really getting that calling renderPickables() would make significant matrix alterations. And so, we have this.
(the other huge problem here is that the visual renderPickables() and the actual picking code no longer agree where the picking tiles are drawn. oh dear.)
(fixed a remaining sloping bug, too— my ad-hoc float abs() code didn't work right, so in every situation where a sloping tile had a neighbor taller than it, it would slope up to it, no matter the height difference. which made for some absurd slopes if, for example, there was a 14-unit height difference. then i discovered fabs().)
I got sidetracked for a long while because of the vagarities of rotation. I was having incredible issues with billboarding (the technical term for 'making a polygon always face the camera') because if you only have to billboard around one axis, the code is easy. (It's sin(angle); cos(angle)
for two of the axes, where the untouched one is the axis you're rotating around and which is sin and which is cos determines if it's clockwise or counterclockwise rotation) Apparently there's a way to do the same rotation in algebraic terms, but i don't know how.
The problem i ran into was that i had to billboard around two axes— the first during a normal board rotation event (around the z axis) and the second when the board is tilted up (around the x axis). there were... difficulties, and i'm sad i didn't screenshot the errors while they were happening. Lots of stretched out and skewed character sprites, etc.
So that delayed my progress for quite some time; i have this incredibly bad habit of not being able to say OKAY I CAN'T DO X RIGHT NOW SO I WILL WORK ON Y. I just have to finish X. Which is why i neither worked on animation nor on multiple-unit boards during the past two weeks. Man, i suck. But billboarding is working now, since the proper math for doing the rotation came to me in a revelation while i was taking a shower. Having a sudden revelation about a vexing problem is a wonderful feeling.
Sadly, this has not fixed one of the most annoying dispay issues— where sprites will randomly cut out a line of pixels as you pan around the map. For the sprite shown, this usually manifests as his chest caving in or his face being transformed into an eyeless horror. If you full-view the recent screenshot, you can sometimes see the problem. There are little guide lines along the borders of the image— yellow lines on the left and right and green lines at the top and bottom. and they should be roughly symmetrical when drawn on screen. But, alas, they are not.
(initially, i thought i had fixed that bug halfway through writing that paragraph, but i kept on writing and discovered that no, i hadn't, and that it was much worse than i had guessed.)
Normal billboarding sprite, after getting billboarding working 'right'.
Normal billboarding sprite, after i realize hey, the render() function calls glRotate with x rotation of -54.736 + rx, which isn't matched in the billboarding code. For the first time ever, i compare the in-game sprites with the spritesheet sprites. And, uh. The ingame sprites are like, 20 px shorter than they should be, instead of the one or two i was anticipating. Not good, for the rotation situation or for my observation skills. So i add -54.736 to the billboard code and marvel as that causes the sprites to not be drawn at all. So i naively flip that sign and add 54.736. Which makes things better, but the sprites are still drawn a few pixels short. (that's this screenshot, which i specifically panned around until i got the 'no eyes' shot)
So i think about things and then realize hey, the proper number to add here is 35.264, isn't it? (figure that one out for yourself; it's not exceptionally hard) and bam, finally, i have working billboarding. All my sprites seem way too tall now, though. Maybe i should draw them shorter.
Whoops. Since the sprites are now being vertically billboarded, they're no longer guaranteed to be parallel to the tile joins. So, we have some depth issues. I don't know if there's an easy fix for this; turning off depth checking would mean sprites get drawn on top of all tiles, which is no less wrong.
Hoom. It has been a while! And, okay, part of that is that my tinkering with the code did not at first generate a lot of hilarious bug screenshots. (i changed the way rotation was handled to be actually timed w/ interpolation, drew a new font, etc,) but now i have gotten to the point where i am FINISHING THE BATTLE LOOP, mainly things like fixing the event/actor/target system (and by 'fixing' i mean 'coding a terrible implementation of') and making it so that battles can hold MORE THAN ONE PARTICIPANT (gasp).
Which, as you can see here, still needs a lot of work.
The most visually obvious problem here is the blending issue. scroll up to the top of this page & notice me blathering on about how menu text and borders must be drawn in the proper order for them to blend together. Well, the units are also blended and also must be drawn back-to-front. And this problem is significantly more complex, because the camera can rotate around them so there's no one 'correct' order; it is dependant on the camera angle. Here, if i rotate the camera by 180 degrees they are both blended correctly. I am filing this problem under 'crazy trigonometric/algebraic problems i have no clue how to solve right now', along with the picking & centering issues.
But the more sinister problem (in that i actually have to fix this one in the near future) is that menu box up there. Purple polygons mean i'm in the 'pick which tile to move to' mode (denoted by the 'BATTLE_SCROLL' text there), and in that mode the unit's action box isn't drawn. Only there is an action box! That menu box is actually the other unit's box (they are differentiated cleverly by me making them face opposite directions, but the action menus are still dummies that all look alike).
See, if two units each get a turn on the same tick, both "this unit can take an action" events are placed onto the event stack. And then they're both popped off the stack on sucessive physics ticks. And so one of the unit's turns is forever lost behind the active unit. Not that this prevents that unit from getting more turns later.
Soooo i need a better way to do the entire battle system. Well. This is one of those situations where i need to just sit down and think about how this will work for an hour or so, then code it all up, because there's no way i'll be able to do this kind of thing while sitting staring at the code itself.
Also, two units can stand on the same tile. I need to tether the graph system & Dijkstra's path function to the real gameboard, instead of it being a generic graph network. Both because of this overlap issue and because of things like jumping & tile heights as well as things like zones of control, if that does actually make it in the game.
So. It is yet again time for me to totally rewrite the program from the ground up. This time addressing things like PLAYABILITY. almost. kind of. One of the things that started to bother me about phantomnation was that is was so slow— every possible interaction with the game was sluggish. I figured most of this was because of the terrible rendering setup i had— as often as computationally possible, it would try to redraw the scene, and i had no way to tell if such a refresh was even needed. So now one of the improvements is that it only redraws the scene 1) when something happens (animation frame changes, player scrolls around, etc) or 2) when it hasn't drawn anything for three seconds. Already, the improvement is vast. It responds a lot more rapidly to input (although part of that is probably the lack of any textures or shading right now) and no longer hogs all the processor time, even when I'm not doing anything with it. The improvement cannot be seen in a screenshot, but trust me when i say the controls are so very much improved.
The other thing i'm doing is making a keyboard interface for picking, both because 1) i want to be able to play this without a mouse (and with a joystick of some sort) and because i need to be able to resolve screen location coordinates so i can eventually do things like draw damage counts or hp bars. And right now, the cursor is in the secondary stages of 'work right with tile heights', although there is a persistant bug (shown left) from the first stage.
Man, until you try to code up a 'which hexagon is this point under?' function, you have no clue how annoying it is. It took forever to get it working, although most of that was because of my ineptitude. But the problem here is that even though the blue cross marker is always over the center of the hex the cursor is over, the blue 'this is the tile the cursor is over' is not always drawn on that hex. As far as i can tell, it's because of some kind of crazy floating-point error. Not entirely sure how to fix that, although i'm sure it'll be a one-line change once i figure out how.
(i figure someone watching me program this would get vexed; every time i start to get a nice-looking program together, i redo it all to get rid of some underlying structural flaws. however, i think [hope] that this version is the one that'll finally get to playability. once i work out the rest of the cursor stuff i'll be able to map 2d coordinates to 3d (...i think) and so i'll be able to draw battle decorations & soforth. ...also, then, i'd need to rewrite the battle and paths code. my life, so hard.)
(later: the cursor fix was a one line fix; i had to jiggle the number up past its threshhold at 1.999999998214 or whatever by adding 0.0001 [or down past with -0.0001, etc])
What? how did this get here? I am not good with computer!
I totally forgot how to do antialiasing properly. As you can see in the screenshot there. I had confused antialiasing/blending with texture smoothing & proceeded to maul my GL settings to try it out. Which... didn't end well. But then I turned off GL_POLYGON_SMOOTH & changed my texture settings from GL_NEAREST to GL_LINEAR and it's all good now.
I'm working out the final bits of the cursor code. Right now, the two problems are firstly, that the cursor doesn't map right when it's on a sloping tile (the tile selector looks fine, just the orange cursor crosshairs themselves)— right now the cursor sits at the height of the center of the tile. It offends my aethetics, even though it's not any sort of important problem.
The second problem regards how i'd like the camera to center on the cursor. The cursor only appears at the center point of the camera when it's drawn at 0 z-height. When it's over a tile that has a height, it is shifted either above or below the center point. This i solved (or 'solved') by adding a z offset to drawing tiles— all tiles are drawn offset by the inverse of the cursor's z height.
That's actually a compound fix— it solves a persistant vexing bug involving maps with extreme z-heights & how they'd get drawn altogether outside the camera view, leading to bizzare-looking scenes where the tile hexes would be cut off halfway, leaving behind an uneven trapezoid, as well as the problem of the cursor not being drawn at the center on tiles with height.
Right now, however, the region tiles are being drawn before the cursor is recalculated, and in certain cases (like the one here; note the few pixels of orange cross at the base of the centered pillar) this leads to the cursor & tile select being drawn under the scene. And because of the frame delay, if you stop moving the cursor at the right (or rather, wrong) time the wrongly-drawn frame will remain on screen for a few seconds.
I suspect the fix for this involves separating the 'calculate cursor location' and 'draw cursor' parts of the cursor code into two chunks, one to run before the region is drawn and the other to run after. Simply making the entire cursor function run before the region drawing code results in the cursor & tile select not blending with the region hex they're supposed to be over.
(later: i separated the code that calculated the cursor location & moved it to the input function, to be run only when the cursor location changes instead of every frame as before.)
One of the problems with the z-offset code is that it was very abrupt— scroll over a tile and instantly the screen would shift the required amount of space up or down to center the cursor. The instant movement was incredibly disorienting. So, i wrote up some code that'd do a timed interpolation of the cursor height, and so smoothly & rapidly slide the camera to the right place.
However, as a result of me messing up the interpolation variable, the cursor instead slowly ascended (or descended) forever, like it was a little orange crosshair angel. Or something. (this screenshot is actually a reinactment of the bug with perhaps even more amusing results— at first i used linear interpolation, hence the constant increase in one direction, but i soon switched that out for a sin()
call, and when that starts looping forever you get a cursor that rapidly bobs up and down twice the length of the height difference)
(details: the code remembers the time at the start of the height shift and calculates the time it will take to slide to the new height based on the height difference, then interpolates based on the current time vs. elapsed time. If the cursor moves on past the tile, the timer & start/end heights are reset and the jump continues until the cursor reaches the height of whatever tile it's over currently.)
I spent the past few days working on map scrolling & soforth— centering the map on a certain tile, automated smooth scrolling, etc. I finish all that up and go back to messing around with the map I'm working on, trying to make it more interesting (not that it matters 'cause you can't play on it yet, but still) only to run into a very odd stumbling block.
I turn off the threefold symmetry and the map is blank. cursor is still drawn, but everything else has vanished. using sixfold or threefold symmetry, the map looks fine. twofold or no symmetry at all, and the map vanishes. I am confused.
Then I remember I still have the two centering functions (instant and smooth scrolling) active elsewhere in the code, called right after the region is established. I try commenting those out; the map loads fine.
Long story short, the instant centering function set the cursor (and thus camera) z-level at NaN
if it centered on a tile that didn't exist. And since the cursor z-level factors into all of the tile drawing code except for the cursor.... You'd never actually want to center the map on a tile that doesn't exist, but I fixed it so it'd work right even in that case.
But writing the centering function has really just destroyed the possibility of overlapping tiles for the time being. Which is unfortunate, because I really like them as a concept, but in practice they made everything incredibly complex. So, oh well, maybe I will see if I can add them in much later down the road when I actually know what I'm doing.
Coming up next: graph code for the maps that doesn't suck! Followed, hopefully, by 1) drawing units (since I can just copy the old code for that) 2) a battle event system that actually works and 3) ATTACKS.
Yet again, annoying bugs. Getting to the point where i am testing out animations. But not quite there yet, because i keep running into unit-drawing bugs. First there were some simple issues regarding translating the code from the older version to the new version (updating the texture coordinates, adding a zOffset to the unit-drawing code so units don't float, etc) but eventually i ran into the vexacious bug that has been lurking since i started attempting to draw sprites.
The new sprites are 41 px wide by 63 px tall. The texture coordinates map an area of the texture that is, in fact, 41x63 px. If i alter them to be one pixel less wide, the texture map starts stretching out to cover the extra pixel. However, during certain movements of the camera (sometimes rotation, sometimes translation) the texture map will just... shift one pixel over.
I have no clue why this happens. My only guess is that it has something to do with rounding error due to the openGL space coordinates not being exactly 41 rendered pixels wide (or 63 rendered pixels tall, whatever) at some points. But it's really annoying. And i have no clue how to fix it! Aside from totally rewriting all the rendering code to establish a openGL frame the same number of units large as it is pixels large (which is apparently what you're supposed to do to begin with if you want pixel-perfect sprites like i do) but i refuse to believe there isn't a lazier way to do things. Like, i could ignore it by making the spaces between sprites on the sheet transparent and hope no one notices the sprites jumping right by one pixel every so often. But i'd rather fix the problem. Provided i don't have to rewrite everything.
Moving on to menus, so that i can actually control the battle loop when i get around to adding that. However, since i wrote the menu code for the last version (you know, all of three months ago) i have totally forgotten how it works. The code reads like a magical incantation, and it's not helped by my prior habit of naming variables things like p16H (short for 'the user-space height of 16 pixels') or tx (short for 'the number of times the menu border texture repeats along its width').
First problem was that the textures were drawing upside-down. Second problem was that each menu was drawn 32 pixels too long (and that y-offset was 16 pixels off). These problems were related; the real problem was that i had been drawing the top and bottom borders (including corners) upside-down. (specifically, with the wrong offsets— to get a 16x16 square to draw the menu texture on, you take the previously-calculated left edge and add p16W (or the right edge and subtract p16W) for one edge, then take the top edge and subtract p16H (or the bottom edge and add p16H) for the other, and I perpetually think the proper way is to add to top and subtract from bottom, which leads to a menu that is 32 pixels too high, off from the proper y-offset by 16 pixels, and has textures flipped upside-down.)
But now the basic drawing issues have been resolved, so i once again must tackle the issue of how to properly draw text on top of the menus. Which, keep in mind, i never actually did figure out before.
You know, the usual. Messing up offsets. Not capping cursor distace to the actual number of menu items. You can see there are remaining issues regarding automatic menu sizing.
(i actually feel really good about programming this bit, maybe just because not programming it in to start made me feel very uneasy, because without the menu system there is no way to do anything of import with the game. So input system, hooray!)
So once again, I am about as far as I have even been in programming this thing. Moving units haven't been added yet, but that's because they were so badly done in the previous version. And then, as usual, the goal now is to get the battle system working. This is more complex than it seems at first.
Firstly, since the unit turns are individually timed (as opposed to 'player team' vs. 'enemy team') and secondly because there are (...will be) skills that require a certain amount of time to use, I am thinking a 'in what order will future events execute' sidebar is required. But I'm not sure how to code that yet. It could go out of date very rapidly (you kill the unit who will act after you) so i need some way to easily take out the actions of one unit and recalculate given new data. This will be esp. hard if I include predictive speed code (as in, 'in 5 ticks player A's hasten spell will go off onto player B, propelling its turn forward') because then one player getting killed would affect other player's slots in the list. Also, since i'd rather not have two timers, the sidebar list has to be the objective measure of who will act, as opposed to a prediction of the 'real' timing system. None of this is aided by the event system I have set up, where events are pulled from the queue as fast as possible with no posibility for meaningful delay, so I couldn't just queue up eight player turns and trust them to execute properly, even if that was a good idea to begin with (it's not).
So yeah, complexity. As usual, i suspect the solution here involves me sitting down with a pen and notepad and writing out everything the system needs to be able to do.
Oh yeah, and here's a screenshot of how the battle system looks right now:
Still working on the proper battle system. Dropped the new turn calculation code (with which i have spent the past four days designing) into the code just a few minutes ago and it worked fine. I had it set to precalculate 30 ticks in advance and it did everything perfectly but spat out a long string of documentary text, so I decided to cut it down to 20 ticks to slow the flood of text. And then it crashes! In fact, (as i found out) it crashed if it calculated by less than 23 ticks per function call.
See, I had set it up so that it absolutely positively had to call the calculation function if there were less than 10 filled slots in the timeline (because that's how many are going to be shown on the sidebar, maybe), but the code didn't re-call the function if it didn't calculate up to 10 events. And the first event happens on the 23rd tick. So, it calculated 22 ticks, exited with nothing in the timeline, then the battle code tried to dequeue the timeline and promptly dereferenced a null pointer. 23 and up was fine because then the queue always had at least one event to dequeue.
It's fixed now.
The nice delayed smooth-scrolling doesn't work quite right now, though, something about the new system not setting the animation delay, probably. But I am feeling pretty good about development right now. Always more problems, but getting more and more trivial to fix. (it was the use of an 'else if' instead of an 'if'; the time delay didn't properly prevent events from happening.)
Displaying the queue works right! Only colored boxes right now, since I'm not quite sure what i'm going to display there yet. And i didn't screenshot the few routine issues with drawing the boxes backwards or shifted in the wrong direction &c &c. I guess next i'll be working on making a real status screen, a real quit confirm box, an animated timeline display, and unit movement & animation. Sheesh. Always more things to do. I seem to recall writing a few months ago that the battle system would be ready in 'a week'. yeah. um, about that.
In which i attempt to write auto-wrapping print code. It works now, but it still chops words in two if they happen to fall at the margin line. Which is unfortunate. In this example, i accidently wrote it so the right margin was to the left of the left margin. On the plus side, i can now check 'make a real quit confirm box' off my to-do list. Only SO MUCH MORE to go. I also fixed some ridiculous bugs about not ignoring user input during the automated scrolling (and thus being able to do things like open a status screen on an enemy unit while scrolling, or open two copies of yr action menu. both invariably lead to crashing when the state stack got confused). Since i have no unit status to display & the controls work fine for the dummy status screen, i guess the next thing is movement. again. with animations this time, i hope!
In which a) the move highlight tiles are hideous, b) the 'hide current menu' code doesn't prevent the menu index from being drawn, and c) the move highlight tiles block view of the cursor. gg me.
When drawing highlighted tiles (now a slightly less terrible purple) there was sometimes this weird jiggling, like they didn't quite match up with the tiles they were over. I kept changing the offset value they were given (remember, all tiles are offset by the inverse of the camera position?), at one point generating the wonderful scene to yr right, to try and figure out why. They seemed seemed especially bad at handling sloped tiles, because then they'd usually get drawn under the tiles and not hightlight anything.
It ended up being because i was casting the cursor Z value from a float to an int. I felt really dumb.
Well, movement works. No animations yet, so they still teleport to their destination, but they teleport tile-by-tile, with proper facing. Also, there are no height checks (I have no clue how I'm going to do jump animations vs. walk animations) and the menu doesn't properly forbid using the 'move' option when you have 0 available move.
Nevertheless, progress!
Also fixed another unamusing bug regarding move centering and physics delay. OKAY, SO. if you select 'move' and scroll around, all "la dee dah i'm going to move" but then decide to not move and hit cancel, the cursor re-centers on the acting unit. However, the first version also stopped the battle system (on purpose, i should specify) so you couldn't input other commands while the map was centering, mostly on the assumption that it would be a fairly short anim & everything would be fine.
However, I forgot that about half of the battle system code is mediated through the more basic 'input' system (it's kind of complex and i'll spare you the details), and the battle delay doesn't affect the input stuff. so the player could do things, like scroll up and down the action menu. And also hit enter to queue events. And since they weren't taking place since the battle system was stopped, you could stack up events you normally can't. Events like 'end this unit's turn'. Sooo, as usual, it messed up the stack and it ended up popping state until there was no active state, at which point things usually crashed in one of several alarming ways.
It's fixed for now, simply by not stopping battle event processing, but i think it implies there's a... race condition-y bug in here, in that it might be possible to trigger the same problem by hammering on the enter key on a slow computer. Sigh. Maybe this version won't be the one to make it to full playability; i might have to rework the event system from the ground up (...again). And fix that annoying timing bug. (see, pausing the game doesn't stop the base timer from running, so if you pause for five seconds then unpause, all the animations jump forward abruptly by five seconds. Including scrolling animations. and there's not an easy way to fix things because there's no overarching animation system & each specific animation keeps a list of times at which it will charge or be finished.)
...but I'm going to at least get movement working properly with full animations before rewriting, if only so i'll have an almost-working commit to the repository. Also I'm really itching to start working on the map generator again, this time with added topography and symmetry action!
I lied again! Why do you believe anything I say?
Working on the 'wander around maps post-battle' code. Also, redrew the font (it is a 14th century blackletter imitation, because i got tired of having a terrible font). Still need to fix animation system. Still need to draw actual sprites. Still have not rewritten map generator. What i have done is... rewrite the starting code so it's even possible to code a title + new/load game screen, separated the 'map' code from the 'battle' code so i can write aforementioned 'wander around maps post-battle' scenes, and made some slight alterations to the movement code so if I ever get around to adding joystick support the cursor will be able to deal with analog stick input.
// FIXME: this doesn't work right. there are times the cursor blocks when it shouldn't and times when the cursor /doesn't/ block when it should. So you can sometimes walk a short way (roughly half a tile) off the edge of the map, and sometimes invisible walls block progress if you're walking around the border. This is alarming because calcCursorTile is (obv.) the same function used to calculate the tile the cursor's over, and it appears to work perfectly /there/.
Also a problem: trying to navigate around hexagons when you can only move in the cardinal directions is indescribably annoying. todo: add 'slide' when you hit a wall. (also: no walk anim, no facing change when walking. this is very bad.)
I realized i have no clue how to calculate the difference in degree between two points, which i'll need in order to program in proper facing when freewalking. Thankfully, I do, at least, remember how to calculate the distance between two points, so I can program in some basic blocking (so no more walking right through other units).
or at least, i thought i remembered how to calculate distance. there seems to be weird distortion-- some shape is blocked, possibly a proper circle, but it doesn't start at the center of the tile...? Then I remember that the unit drawing code has a facing offset so units are always drawn on the nearest face of the tile.
But clearly, i do not remember how to remove the facing properly.
That's even worse!
But anyway, eventually i figure it out and... it doesn't seem to help. blocking still happens only on half a tile. And without the drawing offset, issues with vertical billboarding are much more noticible.
That 'half a tile' turns out to be important. As, of course, i am a forgetful person, i have in fact forgotten the rules regarding calculating distance. so after adding a few abs
inside the sqrt
, i try again. and hooray, it works correctly!
So the moral today is that when you start doing stuff involving geometry and trigonometry, it helps to have basic geometry and trigonometry skills. or access to the internet.
Remarkably, or perhaps not so, i wrote the proper facing code on the first try right after getting access to the proper algorithm— this isn't very shocking, as the proper algorithm is simply calling atan2()
with the movement sine/cosine pair i had already calculated.
However, in yet another un-screenshotable animation problem, things don't work quite as one might expect— going in a cardinal direction (up, left, right, down, etc— importantly, movement caused by pressing a single directional key) works just was you would expect, if you expected the everpresent issues with mapping hexagonal directions with the more traditional quarterly directional keys present on a keyboard. However, issues crop up when pressing two directional keys— moving along a diagonal doesn't set the proper facing, for the simple reason that there isn't a special 'diagonal' move event— it is simply running the (for example) up and right movement code, and both calculate their respective facings for 0° and 90° and one overwrites the other, instead of calculating the facing for 45°.
This is because, mainly, I haven't fully set up the theoretical analog stick input system. So despite the modified code, input is still only parsed as a d-pad command with a strict (0, 90, 180, 270) angle and preset magnitude. The good fix to this problem would involve checking how SDL handles joystick input and adding to the input structure in such a way to accomodate whatever information required by aforementioned SDL joystick input, then rewriting the free movement commands to fake analog direction when dealing with keyboard input in certain cases.
Since i am far too lazy for that (at least for the time being), my plan is to add angle/magnitude values to the input structure and use that. Hopefully, that'll be all SDL requires for analog input… but i somehow suspect i'll be cursing this entry a few months ahead.
bugs tofix:
features todo:
(from my bugs&features file— screenshot is one of the mentioned 'depth issues'. after these things are all done, the walking code will be done [excepting things which are totally uncoded like dialog] and the battle code will be… less unfinished. at which point i hope i can move back to map generation and actually implement moving between maps. also, i should really get around to drawing some sprites and textures so i can stop controlling a coloured box around an unshaded white land)
So then i dropped the project for a few days, then came back and rewrote the texture system. Previously, i was just storing OpenGL texture IDs in various structures that required texture data. This is a bad idea for many reasons, but most notably for me it was because there is a lot of texture reuse (menu backings, sprite sheets, tile textures, etc) in phantomnation, and using bare texture IDs means you either have to load a new texture object for each time you want to use the same image or to share one texture object and have no clue when you're no longer using it. The first take up an absurd amount of memory (...but then again, phantomnation in general uses way too much memory for a program of its complexity, so...), the second leads to memory leaks and/or accidently freeing textures before you're done with them.
So i rewrote the texture code (or at least, parts of it— not all the code has been rewritten as of the time i am writing this) and speaking of memory leaks, guess what the new code had! a bunch of them. ultimately it was a stupid problem with linked lists, but i spent a good ten minutes checking the texture/menu code and recompiling because there was one last unfreed chunk of memory i couldn't account for. And then i remembered that this particular chunk of memory had always been there; it was the state display text shown in the top-right corner, which for reasons i won't do into here is a lazy hack and can't be freed without making it un-hackish. So.
So that story wasn't amusing or interesting, and i made you read about it because i hate you. Presumably i am off to finish the texture code, then work on some of the above bugs.