The Good Small Game Project is still proceeding, in small steps. I have now implemented a step-sequencer in Unity, which uses the AudioClip.PlayScheduled() method, to allow for proper timing of the notes, regardless of the frame timing. The important thing for the game is being able to dynamically change the BPM, and have the sequencer react with as little lag as possible to those changes. And that i could easily swap out the different sequences. So far so good! I have a simple 16 note (4 bars of 4 quarter notes) setup working, with parallel sequences and linear sequences, each containing a number of tracks.
Next step is to experiment with Markov Chains and not L-systems as i had previously considered. I think the Markov Chain approach is better for on-going continuous changes to the output from the previous output. The L-System seemed like you would run it for a couple generations to create a "sequence", and then play that sequence, and then generate a new sequence. Not so much driving what comes next from what has already played. Anyway, we will see, once i get this working.
Also, while looking for something to test the sequencer out on, i found my Funklet book, a kickstarter from 2011. Oi. Amazing, was able to convert the beats into sequences no problem, and was grooving and funking out! Maybe the first practical use of this since i got it! Only took 12 years!
Couple of small things, got a huge flapper on my finger climbing last night. Had to tape it up. Was near the end of the session, so didn't really impact me too bad, other than hurting! Have been working on a game project in my "spare" time. Going well, really reduced the scope down (callback to How To Make Good Small Games), and this has enable me to do more in smaller chunks. Working on the audio now, and am looking at using L-Systems and usfxr for the "sound track". Lots to design and figure out yet, but am enjoying the constrained nature of the problem space. Will talk more about this game when i have a bit more done, at least some placeholder simple audio, and slightly better menus. Am also taking Basic Costal Navigation course, and it is pretty busy, so lots of time on homework and readings! Finally, the longer days are a real boon, as is the warming weather. Spring! Nice! Mental Health + 1!
Whew. I love learning about the history of programming and computer development. So nerdy and fascinating to imagine a time when folks didn't even really understand the use and power of recursion, or even the definition of what it was.
I am sad that so much happened from the 60s to the 80s with programming theory and design, and then it just ... stopped. Got super boring. Still programming with text editors. Still cut and pasting code. Still dealing with dumb syntax errors. Why hasn't J. Edwards or The Future of Coding folks or Chris Granger gotten more support to "make things better"? I want the future now! But i also don't want to learn a bunch of new esoteric stuff to get there!
I started blogging again this year because i wrote my own blog site generator. Or did i write my own blog site generator so i could start blogging again? I am not actually sure which it is...
I had been using Tumblelog, and there were a couple things that were just not quite right. What does a programmer do when things are not quite right? They scratch their own itch.
The major changes, other then rewriting in c# and Unity3d (ahahaha), were tweaks to the input format itself. Each post can now have its own date/time stamps and an optional title. I also changed how tagging works.
I wrote the tool in c# and Unity3d. Yes, when all you have is a game creation tool, every problem is a game. Mostly because using familiar tools would get it done quickly, even if they are not an exact a fit. Whatever, it works. I was surprised by how little code it took, actually. Used Linq, hand written simple recursive decent parser, a Markdown library and Mustache (via the Nustache library) for the templates.
I keep telling myself that once i've cleaned up the code, and finished a "couple last features", i'll put it up on github or some other place. We will see. Not that i am precious about it, more that i'm not sure anyone else would be interested or get anything from it. Other than maybe a laugh.
Couple Last Features
further tweaks and improvements to the input format
adding an "work in progress" marker so that a post is ignored during publishing
adding an explicit "this is a page" token to PAGE types, so there can be explicit error reporting for badly formatted post & page markers
getting all the variables into an ini file, so i don't have to keep recompiling the app
Have been looking for this C# attribute for a while. In Chronicle (our timeline log tool), i've wanted an easy way to ensure that all calls to it can be removed and ensure no GC or CPU is being used, without having to decorate every call with #IF UNITY_EDITOR or some ugly horrible construction like that. And so we get [Conditional("")], which i can just put on top of all the Log() methods. Sweet!
Doing a project where we have a fixed camera, and the "gun" is quite high off the ground. Then we have targets on the ground, that we would like the gun to be able to shoot. But we don't want to worry about bullet intersecting with the gun or anything between the gun and the target on the ground. So what i did was, create a tall collider and "billboard" it such that it always faces towards the camera. This way, you can aim at the target on the ground, the gun rotates and points in the right direction, the bullets travel in the right direction, and they collide with the object! Looks good, and was very easy to implement. Could be an issue for cases where the target is behind cover or other stuff that should block the shots, but i'll cross those bridges when i get to them.
While working on some other research stuff (for Behaviour Trees and Utility AI), i came across this GDC slide deck. It is "just" about the importance of logging data. And while we do that already at work, the key item here is the historic or time-based way of storing and visualizing that data. Being able to scrub through this data, and see it reflected in the scene itself, or via textual outputs. This led to the creation of the Chronicle logging tool. The visualization/output side is very weak right now, but the data-backend and API is pretty great, especially for an alpha/poc. Hopefully something to show soon?
Whew, lots of updates! I had a play test with Tony and Ericka, which gave me a bunch of great feedback. Some interesting ideas for possible experiments! Then today I got the selectable UI in, and a couple actions, kick and stop for the networked balls. I also added a boost ability, with cooldown, for the player. Works great, although i have yet to test it over the network, but i think these should be fine, as they are just like any other physics related interaction. Pickup and Drop are still the biggies, and, maybe, i will tackle those next.
Did a play-test with Adam and Thom yesterday. Discovered an issue when you have more than 2 players connected, the 3rd player's avatar does not sync up with the other 2 players! Luckily it was a pretty easy fix, having to do with initial values for the different authorization sequences. I also was concerned about the jitter i was seeing when playing, but i realized i was playing as a HOST, and the rigidbody sync system is not setup for HOST style play, only SERVER and CLIENT. The SERVER does no smoothing to the objects, which is why it looked so bad for me.
Now i can move forward onto the in-world item selection stuff.
In the past week got the rigidbody controller working across the network. Updated the test scene to include a "soccer stadium". Just an enclosed space which re-positions the ball if it gets out of bounds. The controller is working quite well. The visual representation is still quite basic, with just rotating to point in the direction of travel (or velocity of the rigidbody). Works great in most cases. Not so good when you get on a moving platform! Also, the visrep updates are not propagated across the network, so on other clients your avatar does not rotate.
Next steps are to do a minimum pass on the visrep rotation issues, and to get them updating on other clients. Then on to object selection, and the UI/Display for that. Was talking to Adam about it, and he gave some good examples. The way Sonic Adventures 2 displays the button and action that can be taken is great. What is not great about it is that there is no indication in-world of what object currently is going to be affected by the action. Rim-light or outline will take care of that. Also, the description of the actions available appear in the upper right of the screen, divorced from the object itself. While i like the consistency of location, it takes your eyes away from what you are concentrating on. So, will try something where that info is located beside the currently selected object. While Adam's other reference for how it might look was this:
Aspirational UI Design
I'm not sure i'll be able to get there on version one!
Ok, got some work done on the toy project. Have been experimenting with several different character controller types. Used the Unity Character Controller for a bit, used the Unity supplied 3rd person controller from the asset store. And have ended up back using a rigidbody type, based again on those movement tutorials. I am ignoring all the special gravity stuff that those tutorials do, and have made a much more simple controller, which is good for me, as i totally understand how it works. It has wall jumping, and grounding, and can be moved by other moving platforms, including rotation. I'm excited see how this all works over the network. But probably before that, i will get flying in, and pickup and drop.
Definition. Mindlessness is the vulnerable state of heuristic decision making which leaves users susceptible to unintentional or malicious deception (e.g. fake news, deep fakes) and misdirection (e.g., filter bubbles, dark patterns).
An interesting bug when using Unity Events... You have created a class with a method like public void MyMethod(), and have a unity event which targets that method. You later decide that the method should be private rather than public. The unity event does not care about the access change, and happily continues to call your, now private, method. Also, it can be very difficult to find what unity event is actually calling your method, making tracking down this kind bug very difficult. A "fix" is to change the name of the method, thus breaking the unity event reference. But that is not ideal. I do not have a solution, other than that the unity events should respect the access modifiers on the methods they are calling. With the knowledge that that would likely be run-time costly, and so maybe not worth it.
Got the 3rd person controller "working" in a demo scene, and have continued to think about how selection will work. Also more and more thinking about writing a bespoke controller, just so i know how it works, completely. The tutorials by Jasper Flick are a great resource and starting point. Also, because they use rigidbodys as their underlaying root object, the work on rigidbody sync i've been doing should be able to be directly applicable to the controllers movement.
Oh i found out that the Inter Illusion translation package also has google-translate built in, in that it will take a bit of text and submit it to google for translating. One of the tricks when i did some auto-translating test before was where/how to do it, without having to pay a bunch for it to work. If we just distribute the "raw" or original chat-text to all the clients, and each client then uses its own bandwidth to look it up, that might be better? For some cases of better, anyway :)
Just realized in typing the above that it is my 40th programming "anniversary". Didn't start programming professionally until 1995, or 1996. So 25th year as a professional programmer. I actually find that hard to grok.
Have been trying to get back into "coding for fun". I've been programming since i was ... 11? First on my Vic-20, then the C64 and on to PCs from there. Now working as a programmer I do find that i burn out on programming much more easily, and do not find the fun for post-work relaxation. Especially during these Covid Times. However my down time had turned into hours spend just kind of browsing Reddit or reading Gamedev Mastodon... So, i fired up my kobo, and started borrowing books from the library. It was nice to see that my brain could still read full novels! After reading a couple books, my interest in programming started to perk up again. Not wanting to squash it immediately, i began thinking about how i could program for fun, and keep it fun, or at least stress free. Rather than rushing to my IDE, i began writing, writing about problems that i find interesting, things i'd like to learn. I also realized that i need to keep this project safe from the idea of becoming a game, it needed to be a toy. I don't want to bog my process down with having to make something follow some game-design, or whatever. It is a toy, and a play space for me to experiment. If it is fun, or if you can play a game with it, so much the better. But that isn't the goal. It isn't even a bullet point. Removing the requirements of time, or feeling like i have to work on it, is also important. I am still reading novels, and watching Ted Lasso on TV, and that is fine. Programming is an other activity I can do, when I want to make time for it, not the be all and end all.
So, what is this set of goals i have, for fun personal programming? At least, this is the list at this point in time!
Procedural Generation (of whatever, probably the physical area one plays in)
I have 1 and 2 working in the prototype. The physics stuff is great, using the state synchronization and authority articles by Glen Fiedler as the basis for my stuff. I've done a fair bit of multiplayer networking and this is the best implementation of rigidbody physics, shared across multiple players, that i have ever done. Best both from a "works better" point, but also that it is a very simple implementation.
Also been noodling with how to select objects in the space, and then how to architect the code that makes a thing do a thing. Like, how to select a box then pick it up. Kick a ball. Move items around the world without picking them up. These are questions that i think are fun to think about. There may be something wrong with me!
Still improving the networked rigidbody code, i think the next thing will likely be some experiment with selecting objects, and then activating an action on them. Like, kicking a ball, or moving a block. Depends on how i'm feeling next time i fire up the project.
Adam put me onto this page, Accidentally Turing-Complete. Trying hard to not go down all those rabbit holes of interesting but totally non-relevant articles! I have been prototyping some "program blocks", items that you can physically pickup and move around in a virtual space, and then snap together to create program flows, kind of like Unix command line apps that you pipe data through. The biggest issue is what the input (sensors) and output (effectors) would do in the prototype environment we currently have. The work has sort of stalled, a "solution" in search of a problem.
Oh, it is also the last day of winter, and i'm happy to see it go. It was actually a very mild winter, and i am quite thankful for that, we had enough other stuff going on to have to deal with a bear of a winter too! But still, good to be done with it.
Working on some documentation for the Flow project... Hooked into the EditorApplication.update event loop to allow for updating the names of the Flow components, regardless of their enabled state. This now lets them validate their own flows, and show debug info if they are improperly setup. Also, non-flow components can update the name as well, without having to know anything about flow, other than a magic string field flowName. I tried to avoid magic, but Unity itself uses it, so...
Doing some work on a networked game thing prototype. I really wanted to reduce the difficulty of getting all the things working together, and so am using Mirror and the Noble Whale components for match making, relay/nat traversal and position syncing. It was a surprisingly painless, and quick, process to get them working together correctly, and my basic player controller and visrep working. This might also be due to the fact that i've done a fair bit of networking work before, and have keep up with all these different technologies, but, still, i was surprised. I am quite critical of Unity and how they have been managing their first-party networking solution, or rather, lack of solution. But the community has filled the gap, and as much as i would much rather use a first-party networking solution, this has worked well, so far.
Now moving on to having a couple different types of controller in the game, so next is getting a character controller working. This is going to be a bit more complex due to having animation states to sync, but Mirror does have a Network Animator component, and i'm hopeful that this can be a drop-in-and-work...
A little discussed and poorly understood design goal for code is disposability. Given change, what design patterns can we follow that allow us to quickly expunge incorrect behavior from our codebase? Interestingly it is a much more tractable metric for measuring as opposed to more popular criteria like “elegance”. (a post for another day)
Also this from point 4:
... We often describe this code with the suck-the-will-to-live quality as messy (spaghetti), unmaintainable, or amateurish. Often what we’re describing under the surface is fear and confusion. We don’t understand the code, and when we don’t understand things, as human, we tend to get scared, tired, and angry.
I had a project where this exactly described my experience. Enlightening.
Article about servers and the history of computing, arguing that we have made so little improvement, and been sidetracked down these blind-alleys, into space that has not improved notably since the 70s. I can't help but agree. I have been feeling more and more that computers and computation itself, has been cooped for its own improvement, and not those that would help its users. Us.
Sooooo, holiday time off has kept me from the blog. It has been good for me to be away from the computer for this time. Actually feel refreshed, ready, so ready, for the new year. Family has also been relaxing, enjoying too much food and some respite from this past year. Doing some video calls with the family in lieu of actual visits.
Posted to mastodon about the work i have done to reduce image sizes and got the most feedback ever. Which was enheartening. Next steps are going to be looking at the HTML and CSS and all that, trying to simplify it. Ideally to make it "readable" just as text. I'm not sure that is a realistic goal, considering how many links i use. Even in my markdown "raw" file the links are kind of horrible to read. I could do the reference thing, rather then in-line, which would help, i guess. But only with the raw file, the HTML will still have all those anchor tags and their hrefs in-line.
I do like looking at the server logs, and seeing what all the bots are requesting. Most are, i assume, looking for easy server exploits, of commonly run scripts or packages. Amazing that there is so much action going on that you just never see.
Have been learning, for the uncountable time, that games actually want to be highly integrated. Having things call other things directly is not automatically a bad idea. Using events as weak RPCs is worse then direct calls. Anyway, this all to say that our project is coming along, i've got a bunch of the "meta" gameplay stuff working again, after a big refactor to clean up months of technical debt. Feels good!
One thing that i am proud of is how we have been "upgrading" old save files to whatever the latest format is. This to ensure that it is rock-solid so when we release and need to upgrade save files, we can be sure that it is going to work and not break everything.
Did some work on a 2d car physics project over the weekend. The classic Car Physics for Games (archived it locally) article is the basis for this work. Got the weight transfer stuff working for acceleration and decelerations. Then on to turning, and tire slip and rotational velocity. I think i have most of this working in my head. I am still interested in a model which is expressly not a "realistic" simulation, as we know that, for the non-diving-simulation kinds of games we want to make, players actually want a much more arcade-y feel driving experience. Tuning that feel is the tricky part. And that is what i want this car controller to make "easy". I have a much greater understanding of car physics then i did when we made AutoAge, and also what makes for good car driving feel. So hopefully, i can make a component which allows for easier tuning of those "feel" parameters. It is an ongoing process.
Got the holiday-cheer lights up, tracked down and acquired a tree for the house. Culture has its way, and i do feel better seeing all the lights on the houses in the darkness which comes so early these days.
Also learned about wget and using it to download a copy of a site or url.
wget -r --no-parent http://site.com/songs/
Watching "CRDTs:The Hard Parts" and continuing my interest in Conflict Free Replicated Data Types. I'm not really sure how this works within my interest zone, namely games... But maybe in a MUD-type game? Where the DB itself is changed via CRDTs? I actually looked that up, and there are DBs which are backed or use CRDTs as the sync mechanism. I worry that now i see it as a hammer and want to use it for everything...
Following up on that Unity Scriptable Object issue from yesterday. It appears that SOs have a sort of reference count, and when that reference count reaches 0, the SO is "marked" as removed/unused. If a new script references that same SO, it is reloaded and reset and its Awake() method is called. Now, when all the references are removed and the object is recycled is still unclear to me, but we figured out a code solution, which only kind-of makes my skin crawl. We have a private static hashSet which, when an SO becomes "enabled", it adds itself too. This then holds a reference to that SO for the rest of the life of the application, which prevents it from having its Awake() called again. Fixing the bug, but i still don't really understand what or how or when or why Awake() is called when it is. I am likely to keep poking at this to try to figure it out, but i do not hold out high hopes.
At work I use Unity3D for, well, everything. It has many... quirks? Corner cases? Today we just uncovered a new one, having to do with ScriptableObjects, and their Awake() method. While most other objects in unity have their Awake() method only called once, when the object comes into scope, it seems that Scriptable Objects can have their Awake() method called multiple times. In some cases. And those cases, are, so far, opaque to me. This thread on the forums has some deeper info, but even with doing my own experiments, it isn't clear when Awake() is or is not called. This is frustrating for several reasons, not the least of which is i don't know if this has been happening for ages, and we just have never been caught by how it works, or if this is a new change to how Unity works. So far have spent most of the afternoon delving into this, with no definitive answer.
Got the dang Dijkstra Maps stuff working in the game finally. I had obviously made some dumb programming error when i first coded it up, but i don't know what it was. I threw it all away and started from scratch, which was the key to moving forward.
I now have a "players distance" map, that NPCs can "roll down" towards the players. Will probably split this out into per-player maps, so NPCs can use the player map for the player they are interested in. And still have to figure out the whole multi-maps with desirability coefficients.
Yeah, numbers on the tiles, that is what we needed!
Still trying to workout what i want this to be? Is it "just" a roguelike game, with the multiplayer aspects? Is it some attempt at building a distributed meshed shared world? There are things i can, and want, to try to do, but also don't want to be just another , there should be something new that i can bring to the table. Maybe the multiplayer is enough? For now anyway? I'd like to have a bit more interactivity for the players in the prototype, so something there should be my next focus... And i'm kinda set on environment actions -- digging, making, breaking...
Implemented the auto-translating chat in the game.
Oh yeah, translate that text!
This was the lowest bar, easiest to implement method. I don't even show a name of who typed what! And there is actually no way for a player to set their language preference yet, so there isn't "in game" any translation, but i tested it out with hard-coded player preferences and you can see the results in the gif. So, hopefully, now i can move on from this to something else? Like getting the Dijkstra Maps working? Or maybe mining? Hummmmmmm.
Have been working on the game project a bit, but in a non-exciting-to-show kind of way. And it is actually a side-track, and i am trying to decide if i want to keep doing down this path, or get off and try to find the main route again. It involves in-game chat, and auto-translation. I actually have the auto-translation working, via IBM's Watson service. But the UI for this feature is catching me up, as i have a bunch of specific "looks" that i want to try out, and not the box-with-text-in-it-in-the-lower-left-corner style. However, just in order to put this behind me and move on, i might just do that for now.
Oh and also, because it is text, i've been trying to find a good pixel font that is localizable. This is remarkably hard. I've actually only really found 2 options, LanaPixel and PixelLocale, and only LanaPixel has the Japanese, Korean and Chinese glyphs. Unfortunately it does not work with Unity3d's text mesh pro font rendering... There is this alternative font renderer that works better, but still not 100% great with the LanaPixel font. Anyway, this is another huge side track. I should just drop it for now, and get back to the "main" stuff... But! In my tests with other online players ("tests", ahahah, like 1 time playing with somebody else) i really wanted in-game chat. So here we are.
The end result is that i have to set a reasonable goal to finish up this feature. Which will involve no pixel fonts, no localization, and probably just a box of text in the lower left corner. So it goes.
I worked on AutoAge: Standoff and one of the things i remember really wanting to get into the game were "drunk missiles". You know, those missiles that pop out of a mecha and fly in a crazy swirl towards their target.
"Macross: Do You Remember Love" was huge for me as a kid
I wanted that so badly. It was actually quite tricky to come up with a solution. We used a "guide" that moved in a ballistic way from the shooter towards the target. All the other "real" missiles simply rotated around that guide point. A tricky bit was ensuring that they didn't intersect with the ground while swirling around. In the end i think it looked pretty good, especially animated, but, sadly, i don't have any footage of that, just this still.
Found that image randomly this morning, and made me nostalgic for the game and the work we put into it.
Got some work done on the game, actually have a displaying map and constraining the PCs and NPCs to open spaces. Very unoptimized, but, this is all kind of still just an experiment or prototype, so, i'm trying very hard to be ok with that. Having the map actually makes a huge difference to feel. And it is fun to have a map to run around in. Using Perlin Noise for the "cave" generation, as it was quick and easy. Oh and the NobleWhale Connect and MatchUp assets to make the networking easier, for the players anyway, if not me. Although it is better for me too. Need to reassess what the next steps should be...
Wanted to do some work on tgthnn last night, but just couldn't focus. This had been a problem in the past, but the whole Covid thing has really jacked up the difficulty of getting things done. I don't really like the idea of motivation, and believe that you just have to do a thing, but i couldn't even get my brain to "load in" the code of the project, and start programming. Just too much noise in the neurons.
Soooo, didn't really get the map setup, but did fix some bad code with how the clients were sending their move updates over the wire, and the server/client code to handle them. Also moved the responsibility for asking the NPCs if they are interested in moving to the "game manager" (nee map manager).
And i updated the GFX for the NPCs and PCs to be nicer, and implemented a pixel perfect camera system.
Still working, slowly, on The Game That Has No Name. I have the NPCs working with networked players in a turn-based way. The "time" system is actually an "energy" system, allowing for different actions to have different costs, and so quicker and slower NPCs and Players.
Then next step is a basic map, shared over the network. I am trying to not even worry about display of the map for now, just the ability to have one, and that the Players and NPCs use it. That is my goal for tonight, get the most basic version working. Then worry about a simple rendering layer.
Next steps on the game that has no name, aka tgthnn (this actually sounds, well, reads, like something a dark being would utter while casting a horrible spell on you). I think probably a map, and player movement on the map. It is going to be turn based, and tile based. And multiplayer. And Roguelike. First steps first. A basic map of walkable tiles, and character controllers that obey the map. I already got the network connecting and shit like that, so map and better player controller is next. Have been re-reading some of the Rogue Basin articles. I am still very taken by the Dijkstra Maps stuff, and would like to integrate it into whatever AI thing i'm going to make.
Also time, and how turn based gameplay can work for multiplayer. Ages ago there was an article about Surreal Time for a roguelike, and i have been forever smitten by its ideas. Sadly it is either gone from the interwebs, or my google-fu can not draw it forth from the bowels of google, so i have will just go with what i remember about it. Each player has their own "local time", and NPCs are assigned to a player's "time" based on whatever rules you'd like. To begin with it would likely be distance to player, but also interactions with player, etc etc. This way one player on a level is not stuck waiting for another player to take their turn. I will also be starting with the easiest time system, where everything takes the same about of time, and we just loop through all the entities over and over.
A critical thing to keep in mind for me, is to not over scope any individual bit of this process, if it is to have any chance of success. Super simple steps, one at a time. The simplest thing that will work.
I'm not sure why i bother with these kinds of games. Networking is such a pain in the ass to get working. I was despairing for a bit tonight again, about the state of Unity's networking. But. But. I did get 2 instances talking to each other, which was all i really wanted to accomplish tonight. Sadly, while i am using the Noble Connect asset to allow for direct connections without a relay, i really wanted to use the Mirror package with it, but could not get it to work correctly. So i'm left using a deprecated library just to get this shit working. Gaah.
Ok, trying to move on. What is next? Maybe smooth sync?
Yep, that looks good. NETWORKING. DONE. Bahahahahahaha. Ok, no really, what is next...