Sunday, March 28, 2021

RPG: Map Pins / Packaged Build / Sounds

Map Pins

This month had many improvements in the game. First off are Map Pins. I don't like the modern ARPG mechanic of "here's a quest you don't need to read, here's an arrow on your mini map pointing directly to the quest location, break everything there, and after that you'll get a new arrow with where to go next". Players don't read the quest text because there isn't any need to. On the other hand, modern players aren't going to get out the graph paper and take copious amounts of notes (nor should they have to).

I liked how Dragon Warrior on the NES did quests. You had to talk to the NPCs to get clues on where to go and what to do. But if you wanted to have any sort of break from the game, you were going to have to jot down a few notes to remember how everything came together for the next time you played. Just a few words and a marker on the map would suffice.

My game's presentation is of a giant map you're walking around on. What better way for a user to write down notes on quest items than as pins on a map. In the bottom right section under Notes, you can select to "Add Map Pin".


A dialog box will then appear where the map is centered asking for a name. (You can pan the map using the middle mouse button, so the map pins can be placed anywhere; not just where your player is.)


Give it a name, and the pin is placed! Multiple pins on the map...


Adding pins for areas I've never even been to but someone told me to go there...


You can toggle the visibility of the pins with the "Show Pins on Map" checkbox. Now someone can play the game, get a clue of a quest item, mark it on the map, and even if they don't play for weeks they'll have their notes loaded and ready to go. But at the same time it's not the modern complete hand-holding of a "go here arrow".  


Packaged Build

Something very important in software development (or anything really) is fast iteration and minimizing steps to deployment. When just debugging on my local computer it wasn't a big deal, but I commonly test this multiplayer with other computers. I've added a Post-Build event when compiling in Release to execute a batch file that packages the game up in a ready to deploy zip file.


One click in Visual Studio and I have a build ready for release...


It's not uploading anywhere (I'm not at that point yet), but that will be the natural addition to the script when the time comes.

Sounds

A while ago I had added random sounds that game characters could play (birds chirping from trees). Last month I added sounds when you got hurt. I had considered sounds to be a minor part of the game, but the more I played with them the more ideas I had.

All the code handling loading sounds and what sounds to use has now been externalized. Terrain tiles can now play sounds (waves on the beach), different sounds play depending on what you're moving on (walking on gravel vs walking on dirt vs walking on stone), and attack sounds play when using weapons. All volumes are adjusted based on your distance from them source of the sound.


These few additions have really made the world more immersive. When standing in the town, a street musician could be playing a song (fairly loud if you're close by). The beach isn't far off so you can hear the waves on the shore but much quieter than the musician. Then occasionally you'll hear birds chirping from the trees. If you walk through town on the path you get a unique sound for it.

Since the birds chirping is random and the volumes are based on your distance, it sounds very natural and immersive. (And if you cut down all the nearby trees, you won't hear birds singing anymore!) Sounds went from a minor part of the game to something that can be really key to the gameplay.







Sunday, February 28, 2021

RPG: Various Updates

Various updates this month to the game:

  • Packet counter to debug network message traffic.

Which was used to dramatically reduce the number of packets sent over the network so it's far more efficient.

  • Fixed bugs with the new collision detection / avoidance and pathfinding.
  • Now playing "hurt" sound effects when the player is hit by a monster.


Saturday, January 30, 2021

RPG: Pathfinding

This month I decided to tackle pathfinding, and it came out really well. The world is a giant grid of tiles - some you can walk through, some you can't, and some you can only walk into from certain directions.

I'm using the A* algorithm to find paths from a character's current position to its destination. The A* algorithm as implemented is smart enough to know which tiles can only be entered by limited directions.

In addition to the A* algorithm to pathfind the static tiles, there are also obstructions of dynamic characters that can be in the way. And those obstructions can be of 2 shapes - circular (tree for example) or rectangle (bed for example).

If the moving character encounters one of these dynamic obstructions, it traverses around the obstruction in the shortest route possible to stay on its A* path.


Enemies are far more deadly now; you can't just hide behind a tree and get them stuck. Also it's now trivial for me to have villagers pathfind across town to accomplish various activities throughout the day.


Saturday, December 26, 2020

RPG: Networked Events and Time of Day

The character states and magical effects were being shared between the server and clients, but interactions were not. The client players couldn't go up to a NPC and talk, heal, buy/sell, or enable tactics. It was a substantial amount of work, but client players can now do all interactions with a NPC that the server itself could do. Even the inventory of a client character is shared to the server so server events that check if a player was carrying an item works.

As the engine improves, I need more content to test its capabilities and have something to "play". I added the concept of time of day and events that can be triggered off that time. As well as actions that can create or remove characters. Now I can have pirates that show up on the coast when it gets late, raid the village, then leave. The time of day also influences how much the player can see. During the night the vision radius reduces substantially.


There is an indication of the current time of day at the top right of the game screen. (In the above screenshot, it's close to midnight with very limited visibility.)

NPCs can now also be scripted to go to specific lat/lon locations on the map. There is no pathfinding yet though so they can get hung up on the corners of buildings pretty easily. That will have to be improved upon.

Another content item is if you chop down larger trees they'll leave behind logs of wood which you can sell at the lumbermill.

On the game play side,  I've added a delay between when a character begins an attack animation and when the weapon does damage. Damage now coincides with the instant the weapon's animation touches the target as opposed to the start of the animation. In addition to just looking better, this adds more options to tactical combat (adds the ability to dodge).

Wednesday, November 25, 2020

Backup Generator Power

We frequently lose power in the fall/winter months, and no power means no lights, no refrigerator, no water, and no heat. We had a portable generator and ran extension cords into the house through a cracked door, but that was far from ideal. (And even though the generator was several feet from the barely cracked front door with foam filling the gap, I can still confirm the Carbon Monoxide detector in the house works.)

A very cheap and relatively simple way to tie a generator directly into the house is via an interlock switch. Add a inlet to the outside of the house wired into a circuit breaker in the main electrical panel. The interlock is a simple strip of metal that slides up or down to prevent both the utility main and the generator inlet from both being engaged simultaneously. (Very very bad things happen if utility main power can get to the generator and very very dangerous situations happen if the generator is back filling power to downed power lines.)

Another option is to use a Transfer Switch, but that requires far more wiring as you have to pick specific circuits to be powered by the portable generator and wire them into a separate electrical panel.

The only 2 upsides I know of for a transfer switch is:

1. With an interlock switch, you have to make sure to not enable power hungry devices such as ovens and electric furnaces. With the transfer switch those aren't even available to turn on.

2. With a transfer switch, you can leave the main power enabled so you can know when the power is restored to the house to those few circuits that aren't on the transfer switch.

However the interlock is cheaper and far simpler overall. Definitely the way for me.

There are far better tutorials than mine online on how to do this; the following is really just notes to myself and ways to share it with others I know that are interested in doing it. Disclaimer: The work was permitted / inspected / approved, but I'm not an electrician and you shouldn't trust anything I say.


I patched up a prior hole in the wall that was an old dryer vent. It's at a perfect place underneath the panel and I want to cover up how ugly it looks anyways. Here's a picture of the patched exterior (paint still drying) with a coupler to guide the wire into the house. (I saw other installers just pushing the wire directly through the wall and caulking around it, but that looked pretty poor to me. I like this much better.)

And on the inside... (That's construction adhesive around the patch.)

Total cost for the mini conduit piece and wire clamp was less than $5.

For the plug itself, I went with the Reliance 30-Amp Generator Power Inlet Box for $49.98. I picked it up at the local Lowers but it's readily available online.


The 4.5 out of 5 stars is no surprise, this is a great inlet box. It takes the typical 240V 30 Amp generator extension cord and can be wired to the house panel.

Mounting the box...

For this inlet I needed 10/3 wire. The 10/3 Romex (NM-B) wire that you get at big box stores will have 2 insulated hot wires (red and black), 1 insulated neutral wire (white), and a bare ground. I only needed to go about 6 feet, so I got the smallest bundle from Lowes (15 feet) for $31.69.

This wire is only for interior applications; if you're connecting to anything outside the house then you'll need the exterior grade wire instead. Apparently even though my inlet box is mounted on the outside wall of the house, it's still ok to use the Romex NM-B as it's considered interior wiring. 

Routing the wire into the panel...



Now comes the most difficult part of the whole thing. You must get the proper interlock kit for the panel, and the descriptions on local hardware stores and Amazon are not clear what they're compatible with. I ended up getting part numbers off my electrical panel and contacting Square D customer support. They replied back with the exact interlock kit I needed: "Square D HOMCGK2C Homeline Cover Generator and QOM2 Frame Size Main Breaker Interlock Kit", and it fits perfect.

The interlock kit includes a clamp down for the breaker (required by code for any breakers that supply power into the panel) and the metal slide that prevents both the generator inlet and main power from both being simultaneously engaged. $42.89

And to wire the inlet into the panel, I got a Square D Homeline 30 Amp 2-Pole standard circuit breaker. The "2-Pole" is how the breaker is 240V - it connects to both hot wires which are out of phase. If your electrical connection is bridging both hots, then 120 + 120 = 240V. Just $9.95

And here is the installed breaker with the clamp supplied by the interlock kit. The inlet breaker must be installed in a specific spot so the interlock switch can slide over it. I ended up having to move my 240V breaker for the water pump from the bottom left breaker (position 2/4) to the top to make space available.


Mounting the slide was actually a piece of cake. It comes with a template that slots into the holes of the panel cover. Drill some pilot holes with a smaller drill bit then go back with the larger bit. Then you just tighten the slide on with the supplied bolts.

The only problem I had in this process was when the wind blew my instructions onto the only fresh pile of chicken feces on the front porch.

Panel cover back on...


So the panel is good to go now, but the generator needs a bit of work.

Main utility power is a pure 60 Hz sine waveform. That's considered clean power and is what AC (Alternating Current) devices such as refrigerator compressors, water pumps, etc. expect. Portable generators can deliver power as a modified sine wave (basically a square wave or close to it) or a pure sine wave. They're both at 60 Hz, but the square wave shape is not the clean waveform the electrical device is expecting. If the generator creates a pure sine wave, then it's called an "Inverter Generator".

Having a modified sine-wave go through AC motors such as compressors and water pumps can generate additional heat and decrease the life of those devices. How much so? Hard to know. But it made me nervous enough to not want to have my devices on modified sine-waves for extended periods of time. Inverter Generators are more expensive than their modified sine-wave counterparts, but the piece of mind of not worrying if I'm damaging my equipment is worth it.

Of Note: I have an older modified sine-wave generator that I originally planned to run into a UPS then on to my electrical devices. However, standard UPSs will completely reject dirty square wave power and will not charge from them or clean up their power. You can buy UPSs that will accept the dirty power and clean it up to a pure sine wave, but they're so expensive you might as well get an Inverter Generator to begin with.

I ended up buying a Champion 6250-Watt DH Series Open Frame Inverter with Quiet Technology for $1032.17.

It is an "Inverter Generator", has a relative highly continuous load rating (5000 watts), delivers 240V via L14-30R outlet, has very nice maintenance accessibility, and solid reviews. I'm not powering an electric car charger or my electric furnace with this, but it has enough continuous power for the house lights, water pump, refrigerator, and wood pellet stove (to keep the house warm).

One gotcha with tying the generator to the house is whether or not it has a bonded neutral. The 240V L14-30R outlet has 4 wires - 2 hots, 1 neutral, and 1 ground. These portable generators are meant for taking out to a job site, starting them up, and plugging the tools in. For that typical use-case, the generator comes delivered with a bonded neutral - the neutral wire is connected to the frame of the generator alongside the ground wire.

In a house electrical panel, the neutral wires are also bonded to the ground wires along the same bus bars. But apparently some squirrely things can happen if the house has the neutral & ground wires bonded AND the generator has the neutral & ground wires bonded. I won't even pretend to understand it well enough to confidently explain it.

There are plenty of warnings out there to not modify your generator and to use a special GFI transfer switch instead to solve this ground loop problem. However, the official Champion website has instructions and a video explaining exactly how to disconnect the neutral wire to get a "floating neutral". The generator would no longer be safe as a portable device on a job site, but it would no longer have the ground loop problem when tied into the house.

Note on the front of the generator: "NEUTRAL BONDED TO FRAME".


If I used a multimeter to check continuity between the neutral and ground of the 240V outlet, there was no resistance.

The steps are super easy; this generator was definitely made with intention of swapping the neutral connection. Remove the front panel.


The corner terminal has a white wire (the neutral) and a couple ground wires (yellow/green) connected to it. All that has to be done is the neutral wire removed from that bolt and wrapped up so it can't connect to anything.


Reattach the front panel and use the multimeter to confirm that I now have a floating neutral; the neutral is no longer bonded to ground.


Last item to buy was a 15' 30 Amp rated extension cord with NEMA L14-30P/L14-30R ends. After the inspector approved of my wiring, we did a successful test! 


Again I'm not a professional; this is what worked for me and I have yet to burn anything down.

Costs:
$5 Electrical Clamps / Conduit
$49.98 Reliance 30-Amp Generator Power Inlet Box
$31.69 10/3 Romex (NM-B)
$9.95 Square D Homeline 30 Amp 2-Pole Circuit Breaker
$42.89 Square D HOMCGK2C and QOM2 Interlock Kit
$86.30 Electrical Permit
$1032.17 Champion 6250-Watt Generator (5000 Watt continuous, Inverter Generator)
$43.69 15' 30 Amp L14-30 Extension Cord
----------
$1301.67 Total


Thursday, October 29, 2020

RPG: Memory Reduction

 Although CPU performance was improved to a solid 60 Hz, memory usage skyrocketed.


Each depth of the map has a ground tile and a canopy (roof) tile. When rendering the scene, the ground tile is drawn followed by characters followed by the canopy tile. That way a building roof can be drawn over characters.

For now we have 5 depths (that will grow) and 4 animations for terrain (that will likely increase as well). So: 5 depths x 2 (ground/canopy) x 4 (animations) = 40 tile maps.

I was generating at startup every one of those tile maps. That actually turned out to be totally unnecessary and very memory wasteful. To update all the tiles in a tile map from one level to another (8 in total) only takes a fraction of a second - barely noticeable. So I've replaced 40 tile maps with just the 8 that are in a single depth and the player has a trivial pause when the view switches between depths..

The difference in memory usage is unbelievable - 93% less:


There were lots of graphical glitches with canopies, walking to the edges of building, and other UI elements not redrawing properly that I've also now fixed. Even though the game still looks awful, the underlying engine drawing it is becoming much more capable.

Also did a network test, 3 players all fighting in the world together!


The network test went great. Found a handful of bugs (including an especially funny one of dead players that weren't resurrected quickly getting transported to the middle of the world based on monster respawn logic) but the game was really fun.













Wednesday, September 30, 2020

RPG: Quest for 60 Hz

As I implemented more and more features, the performance went down and down. It got to the point that if I zoomed out all the way, my frame rate would drop to about 1 Hz. In my last post I detailed how my drawing went from thousands of individual draw calls to just a handful for the map. My performance jumped to the upper 30s but still far from where it should be.

The most CPU intensive operation was still drawing, but it was the user interface this time. Every frame every control item (button, text, bar, graphic) was redrawn; each having its own draw call. I reworked the drawing routine to draw all of those controls onto a single texture generated dynamically. Now instead of recalculating / redrawing all the controls every frame, I'm drawing the single dynamic texture every frame. If a control changes (text, visibility, color, etc.), then just that one control is updated onto the dynamic texture. After that change, I was able to get 60 Hz.... most of the time.

The last bottleneck was a simple bug in the A.I. logic that caused entities to check what to do every frame rather than every other second. Once that issue was fixed, I achieved 60 Hz in all cases in the game. Wohoo!

(Frame rate in the capture shows 58, but it's bouncing around 60.)

The CPU is still working harder than I'd like it to. I want the game to be able to run on relatively low powered computers, and I think lower end processors will fail to reach 60 Hz. So more to do, but at least right now it's buttery smooth for development!