My Spending Tracker App: SigmaSpend

Comments

Today I published my spending tracker app for Windows 10 on the Microsoft Store. It's called SigmaSpend. I first started working on it almost 6 years ago. I've only worked on it in spurts during that time, but still, I've spent quite a bit of time on it.

I never really intended it to be such a large project. My original intention was just to make something simple to replace the document I had started using for tracking my own spending. I figured it wouldn't take very long to get the basic functionality, and then I could just add whatever features I cared about if I felt like it. And that was true — I had the ability to enter transactions within about the first month of working just in my free time. And ever since then, I've been using it for my own spending data. But it was another couple months before I had basic reporting on the data. And even though it's still a very basic app, I've continued adding features on and off over the years. But I had never put in the effort to polish it sufficiently to where I felt comfortable publishing it until now. The fact that it was working great for me personally, even in its unpolished state, meant that I was less motivated to improve it.

One of the features I added that I spent the most time on was synchronization of the data between devices. Initially, I just used UWP's built-in roaming data feature. That worked well and made implementation easy. But I eventually discovered that the data is limited to 100 KB when my own data grew larger than that. So I switched to using OneDrive, which was a lot more difficult.

Part of the reason I wanted the synchronization between devices was so I could also use the app on my phone. I mostly enter data on my desktop PC at the end of the month when reviewing my bank statements. But it's nice to have a phone version in case I have to pay cash for something so I can enter that right away and not have to worry about forgetting to enter it later. I've been working on this long enough that my phone at the time was a Windows Phone, which meant that I could run the exact same app on my PC and phone, which was awesome. When Windows Phone stopped being supported, I started working on an Android version of the app. Although I do have a version of that that kinda works, it's unfortunately nowhere near being shippable. Maybe I'll finish that version someday. But adding that cross-platform support is another thing I've spent a lot of time on, even though it's not done.

There are a lot more features I'd like to add in the future: graphs, importing and exporting data from other formats, automatic backups, and better overall organization of the UI. But even without those features, I find the app quite useful personally. So I figured it was time to share and get some feedback. If you try the app, leave a comment or send me an email and let me know what you think.

Updating to ASP.NET Core

Comments

Over the weekend, I updated this blog from ASP.NET to ASP.NET Core. I thought I would go over some of the issues I ran into in the process.

Porting the code

The actual porting of the code was reasonably straightforward, since there really isn't much code at all running this site. Since the project format is different, I started fresh with the ASP.NET Core MVC template. I removed what I didn't want and then copied in my existing code, making sure to preserve my Git history, of course. Then, there were just a few things that needed to be fixed in order to get it building and running correctly again:

  • Removing usage of RouteValueDictionary for calls to Html.ActionLink in my Razor files. I replaced those with anonymous types.
  • Replacing calls to HttpNotFound with NotFound in my controller.
  • Removing usage of HttpContext.Server.MapPath. There's no direct replacement, but I used IHostingEnvironment.ContentRootPath to build the paths I needed. You just have to let the framework inject IHostingEnvironment into the constructor of your controller. This is a change that I was happy to make because removing the dependency on HttpContext should make it a lot easier to unit test that controller, which I had avoided for that reason up to this point.

Porting the unit tests

The small number of unit tests that I have actually built without modification. However, they no longer passed. The issue was that apparently the DeploymentItem attribute isn't implemented for .NET Core (yet?). I was using that to deploy some input files for my tests. My workaround for now is to add a test initialization method that sets the current directory to where those files are located in the build output and then a test cleanup method that sets it back to where it was originally.

Recreating the CI/CD build

I have a continuous deployment build ("pipeline") on Azure DevOps that deploys the site automatically whenever I push changes to the repository. With the new project format and build system, I pretty much had to re-do that completely to use the dotnet CLI tool for all the main steps (dotnet restore, dotnet build, dotnet test, dotnet publish). I was surprised that my unit test workaround didn't give me problems here, but it seems to work fine on the build agent.

Fixing the publishing/deployment

This is the only part that really caused me problems. Everything was working fine locally, but I was having some strange issues when I deployed it to the Azure App Service. Most of the pages worked, but the main page appeared as a 404. Apparently the 404 was actually just hiding some exceptions, which I saw when I temporarily set the ASPNETCORE_ENVIRONMENT to Development for debugging purposes. The more straightforward problem was that some of my data files were missing from the published directory. I was able to fix that by adding this to my .csproj file:

<None Include="folder_name\**">
    <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>

The other problem was that I was getting exceptions about missing types and assemblies. I debugged this by creating a brand new app service instance and seeing that it worked fine there. I eventually figured out that it had to do with extra files that were still on the server from my previous ASP.NET (non-Core) deployment. I fixed that by doing a manual publish with a publish profile (.pubxml file) containing a line like this:

<SkipExtraFilesOnServer>False</SkipExtraFilesOnServer>

That line tells the deployment to delete any extra files on the server. I'm not sure there's a way to set the deployment build step in Azure DevOps Pipelines to do that every time, but for me, doing it once manually worked.

Conclusion

Overall, updating wasn't too hard. Although there were a few annoying problems, I was able to figure them out in a weekend. There's no immediate benefit in this for me, but I always like to have my projects on the latest technology, if possible, in order to make future maintenance easier. Plus, it's just good learning experience. And if I ever want to try running this on Linux or inside of a container, that should be easy to do now.

Building a Racing Game in Unity

Comments

Since I've been learning Unity, I decided it would be a good idea to try to do a simple game project from start to finish. I wanted to have some concrete, achievable goals and a definite schedule to hold myself to. I decided to do a racing game. I figured the actual game itself wasn't as important as just finishing something, so I just picked a racing game because it seemed like it would be pretty easy. I gave myself one month to complete the project, and I set four one-week milestones to keep myself on track.

Week 1: The Basics

My goal for the first week was just to have a single vehicle racing around a single simple track. I decided on a computer theme for the game, so I made the vehicles be hovering computer mice. I tried to create a mouse model in Blender, but that turned out to be a bit harder and more time-consuming than I thought it would be, so I ended up with just the half-finished basic shape.

I spent some time making the vehicle float with a springy motion. I also played with the movement controls a bit to try to find good values for the rate of acceleration and turning. But I'm not happy with the way it feels. I can imagine that getting the controls to feel crisp would require a lot of tweaking.

I created the simplest possible course I could imagine. The ground is just a plane with a texture that I drew. I added some walls to the inside of the course so that you can't ignore the road entirely.

I also implemented the system for counting laps. I did that by placing invisible trigger collision volumes at locations around the course as waypoints. Then I just count the number of times a vehicle hits all the waypoints in the correct order.

Week 2: Multiplayer

The goal for the second week was to add splitscreen multiplayer. Doing splitscreen turned out to be easier than I thought it would be. I didn't even have to bother going to look for a tutorial. Nonetheless, I'm thinking that I might make a tutorial for how to do that, just in case it might be helpful. I spent most of the time for this week on the UI and configuration work needed for multiplayer:

  • Adding a menu for choosing the number of players
  • Controller and keyboard configuration for two players
  • Making the basic game logic work for a variable number of players (e.g. different internal lap counters for each)
  • Allowing each player to have a separate heads-up display

Another interesting item from this week was calculating the place/ranking of each player while the race is in progress.

Week 3: AI

The third week goal was to add AI players. When I started the project, I hadn't really given any thought to how I'd accomplish that. But at some point, I happened to stumble across Unity's navigation system, so I decided to give that a try.

It was pretty easy to get the NavMeshAgent to navigate around the course. However, with the AI vehicles being controlled that way, their motion is very mechanical — as if they're on a rail. I wanted the AI players to follow the same movement rules as human players. So rather than letting the NavMeshAgent control the motion, I just used its steeringTarget property to get the coordinates of the next point to drive to and wrote a simple steering algorithm. The algorithm first rotates the vehicle to point it in the right direction, without moving forward. When its orientation is close enough, it simply moves forward at full speed, while continuing to make smaller steering corrections. This algorithm isn't great, but it's sufficient to allow the AI to complete the course in a reasonable amount of time without getting stuck.

Week 4: Items

My goal for the final week was to add some basic items/power-ups to the course. I wanted to add boost pads and also a single collectible item. Getting the boost pads working was easy. I placed them just slightly above the ground and then used a downward raycast to determine whether the center of the vehicle was directly above the pad. If so, I just increased the vehicle's thrust.

The usable item I added is something I'm calling the "overload bolt". You pick it up and then you can fire it at the other player. If it hits them, it causes them to lose all power (thrust, steering, and floating) for a couple seconds.

I used the leftover time for the week to play with the lighting in the scene. I made everything darker, added a light beneath each vehicle, and made the overload bolt and boost pads glow a bit. Those lighting changes just made things a bit more visible and allowed me to use those lights to provide some visual feedback to the player.

Release

I'm releasing the game on itch.io. It's a distribution platform targeted at allowing developers to easily share their projects with each other, without the expectation that those projects are necessarily finished or polished. This game is certainly not polished, and not really even fun to play. But I'm releasing it anyway just for the experience of doing it and to give the project some closure so I can move on to the next one.

What I Learned

The whole point of building this game, of course, was for me to learn more about game development. And I've definitely learned a lot over the past month.

At the beginning of the month, I barely knew anything about Unity's UI system. I knew how to display text, but that was about it. Now I've learned enough to create buttons, menus, and more sophisticated dynamic layouts. I spent a fair bit of time just on creating the UI for this game, but hopefully I'll be able to do that much faster next time. I think having some basic UI like a main menu and a pause menu really makes a project feel more finished, even if that UI isn't very pretty.

Another important lesson for me was the degree to which multiplayer complicates things. The fact that it makes things more difficult is obvious, of course, but it was still instructive to see firsthand just how much it complicated things. If you count creating the AI players, I probably spent about half of my time for the whole project on multiplayer.

I think possibly the most important thing I've learned this week is that I can successfully set schedules for myself. And, crucially, that I can stick to those schedules and get quite a bit done. I look forward to doing another project and seeing how far I can get with that, now that I have a bit more experience.

Learning Blender

Comments

One thing I've always felt was a bit limiting for me as a programmer wanting to create games is a lack of artistic assets. Most games require some kind of art work: images, drawings, music, etc. And I have pretty much no experience creating art. I never even took a single drawing or sculpting class in school. I figured that if I were ever going to create a full game by myself, it would probably need to be something like Geometry Wars so I wouldn't need much art. I do love Geometry Wars, but there are lots of other types of games out there.

Fortunately, I recently realized how fun and useful 3D modeling tools can be. I guess it started when I was learning SketchUp for a woodworking project I was doing. Maybe I'll talk about that project or about SketchUp some other time, but today I want to talk about how I've started learning Blender. When I started learning Unity, it really became clear how critical it is to have 3D models (or 2D images) to work with, even if they're just placeholders that might be replaced by better ones later.

I wanted a lovebird model for the bird game I was working on, so I went looking on the Unity asset store and managed to find one that I liked. But it was $20 and I wasn't sure I was that serious about the project yet to spend that much on a single model. I decided to try to make a placeholder myself. Then if the game did become a serious project, I could buy a good model and replace it later.

I started learning Blender just from just from the tutorials on Blender's website, until I started hitting the ones that required a Blender Cloud subscription. At that point, I started watching tutorials on YouTube, including this basic one and this one about creating low-poly animals. Those actually got me pretty far, and I was able to create something that did resemble a lovebird. But they also showed me how much there was to learn.

After watching those videos I kept seeing ads for online courses. I eventually clicked on this Blender course on Udemy. I'd never used Udemy before or bought an online course before anywhere else. But I decided to buy this one after watching the free sections. It was only $10 for new users when I bought it and it has 48 hours of content, which seemed like a pretty good deal to me. I'm a little less than half way through the course and, so far, it's pretty good. I've made a bowling ball, bowling pins, chess board, and all the chess pieces.

I've already learned a lot and I'm excited to continue learning more. Even if I'm never able to create anything better than placeholder-quality models, I think this is a skill that will serve me well in the future. Plus, the fewer excuses I have for not creating games the better. I've already started using some of the models I've been creating. I'll talk more about that later.

Learning Unity 3D

Comments

As I mentioned in my last post, video games are why I started programming and I'd like to get back into game development. So I recently installed the Unity game engine and started going through some of the tutorials.

I started at the beginning with the Roll-a-ball tutorial. Although what you end up with after completing that tutorial may seem simple, I was pretty impressed. Having done game stuff without the benefit of an engine before, it's pretty amazing what a complete beginner can do in an hour with Unity.

I had an idea for a simple game prototype that's not too different from that tutorial. I have a pet parrot and he has a game — I use that term loosely here — he likes to play where you put his toys on top of his cage and he runs around on top of the cage and pushes the toys off onto the floor. He then stares down at the toys on the floor and demands that you pick them up for him. My idea was basically just to create this game with the player in control of the bird.

So I started by just adding a plane and a sphere as in the Roll-a-ball tutorial. The plane represented the top of the cage and the sphere represented a ball toy. Then I added a roughly bird-sized green cuboid to represent the bird (our bird is green). At first, I tried to control the cuboid the same way the ball is controlled in the tutorial. But that was just tipping it over instead of pushing it. So I switched to using a CharacterController instead of a Rigidbody and that worked well. Once I had the cuboid moving around, I just needed to be able to push the sphere. I was able to get that working with code based on the answers in this Unity Answers post.

Again, what I ended up with was very simple. But I was able to make something in two or three hours that I believe could've easily taken weeks if I were writing it completely from scratch. The main reason I think it would've taken so long from scratch is the physics. Even for simple shapes, the math for collision detection and response can be pretty complicated, depending on how correct/accurate you want to be. My hope with learning Unity is that I'll eventually be able to create something closer to a full game (that's actually fun to play), rather than the tech-demo-type things I've created in the past. And while this is still just a tech demo, the fact that it took so little time to create is a good sign. I'm just getting started with this bird game, so I hope to talk to about it more in the future.

Continuing with my Unity education, I also completed the space shooter tutorial. That one is more in-depth and leaves you with something closer to a full game at the end. It took me a couple days to complete. Again, I was impressed with how much can be accomplished so quickly. In high school, I built a game from scratch that was very similar and it took me months. Of course, I was inexperienced at the time, but it would still take me a while to do that from scratch today.

I've noticed that programmers often have a tendency to want to build everything from scratch. We like being able to understand and have complete control of all the details in our programs. And, of course, it's good to understand how things work at a fundamental level. But if you insist on doing everything yourself from scratch, you'll be severely limited in the scope of your projects. I have to remind myself of that occasionally and let myself embrace higher-level tools. And that's exactly why I'm learning Unity.

But Unity isn't the only tool I'm currently learning. One point that the Unity space shooter tutorial really drove home for me is how important it is to have artistic assets available to use. It's only because the tutorial provides those assets that you can create the game so quickly. I can imagine that creating the assets might take as long as the game itself. Because of that, I've decided that I need to learn how to create some simple assets for myself. I've started learning Blender, which I'll talk about in my next post.