Refactoring code to make it not just a bunch of gigantic static classes with a million static functions. Breaking apart code into smaller chunks for clarity. I realized with how asynchronous this game is it will quickly get out of hand if I can't keep everything organized. So-far, so-good. I think I'm on the right track.

More submissions by funkyjive for Daily Gamedev

Cleaned some code, added a second character, added a second camera for split screen.

I still have yet to decide the most important question if the players are working with or against each other...along with what it is they are doing.

Just a demo to play with ideas. What if the world were inverted and we lived on the inside of the planet instead of the outside surface...

What if it were a world big enough for 100 people to hide, hunt, build, and kill?

A few lines of code and now the troops actually get moved to their respective tile. This is prior to the commitment of the turn to the server for validation and the real movement taking place. So this is just the local visualization of planning out your turn.

There are a few bugs I need to deal with and I need to add a way to "undo" a move by clicking a unit (remove the simulated move from the list of moves this phase of the turn). I'd also like a way to indicate which tile a troop came from. Maybe a line back to where they started the turn?

Another small task finished, I completed the configuration of the invasion zones on the west coast. Meaning the tiles have the right properties, links to their neighbors, troop positions, etc. This is a tedious and boring task but the way I am developing this is one phase of a turn at a time till they are all implemented. Well, in order to make the reinforcements work 100% correct I needed to tackle that now.

I had no motivation to do any gamedev tonight but I saw that we were about to go 3 days in a row with no posts from anybody and that seemed unacceptable. So I did some boring but easy work. I finished tracing the rest of the board tiles to complete the map for the whole country. There is probably about 20 more minutes of work to do in another session to rename the vector outlines so that the game will pull out the appropriate shapes at runtime but this will be an exercise for another day. Once they are in game I also need to do the neighbor mappings for every tile. That will take some time.

Anyways here is what all the tiles look like. Note that the colors are temporary for me to see the region the tiles belong too. The will likely all be the same color in game (with a big fat line showing the different regions).

Continued to develop the show valid moves function by adding in more of the game rules. So things like taking into account that you can't jump across a tile that the enemy has at least 1 unit in...unless you are a bomber or chopper unit type. Also added in the logical check for eliminating tiles that already have the limit of 5 units in them...unless the movement is part of an attack towards an enemy territory in which case you can throw as many units as you want at it. The 5 unit limit logic seems to be working as I started placing a bunch of units into one zone. On the sixth, that tile did not show up in the ugly green indicating that I can't move there.

I also fixed Ohio. I had a theory that polygon winding was the issue and wanted to test it. It seems to have corrected the problem. I still need to finish outlining the rest of the tiles in the center of the board but I figure I'll save that for a day when I have little motivation to write code and just want a mindless task.

One final thing I'd like to do before I continue onto more of the core game logic and the next turns. When a unit is moved but the turn is not finalized yet, I need to indicate this somehow. So if troop A is moving from tile 1 to 2, I'd ideally like him to be placed in tile 2 with a line or something back to the spot he came from in tile 1. It would stay like this until the player hits the complete turn action. This allows him to undo a move he doesn't like and at least see things before committing the turn. For each tile in the unity editor I have manually placed 5 transformations for unit placements in a tile (since the tiles can be wacky shapes and sizes I don't want the units overlapping). This is fine for up to the limit of 5 units at the end of the turn but there is one edge case that can't be supported. A player can attack an enemy with as many units as he likes. So let's say the defender has 4 units in a tile and the attacker is moving troops to declare battle with 8 units. Like before, I'd like to have these units "staged" at the tile they would be attacking as the player is constructing the turn but this would mean I have to have 12 locations for units in a single tile (until the battle is resolved). I thought about a single position per tile for "attacking" units but then the player can't pick a specific unit in the pile if he decides he doesn't actually want to engage a particular unit. It is also quite a painful and tedious process to even place 5 positional transformations for each tile. I can't imagine having to place 20 or 30 per tile. I haven't solved this problem yet and can't think of a solution I like. Ideally there would be a procedural way I could place them but unfortunately the tiles are all shapes and sizes. I wonder if given a set of points that represent a concave polygon there is an algorithm to pick random points within said polygon that are X distance apart from each other???

In the picture below I have moved 5 units into the lowest western invasion zone. The units aren't actually shown in there because...well did you read the last paragraph? I haven't implemented it yet. I have clicked a sixth unit and I see that the full invasion zone is no longer a valid move.

When you click a unit to move them, the valid tiles that can be moved to are now highlighted. This took a little bit of clever logic but seems to work quite well and was relatively easy to implement. A while back when I defined the properties of tiles I was thinking ahead of this issue (finding and validating unit movement against game rules). So each tile needs to know it's neighbors and has a reference to them. Thus if you have a starting tile and a max distance in number of tiles then it becomes easy to use a few for loops to "walk" from neighbor to neighbor and find all tiles within X number of jumps.

But wait! There's more! This system allows me to do something even more clever with reinforcements coming in from off board. For normal tiles on the map two adjacent tiles both have references to the other in their neighbors list. Since you may be moving in either direction. I have reinforcement staging tiles for each army. These staging tiles have their neighbor references set to the valid places that reinforcements can be placed but more importantly, those neighbors DO NOT have a reference back to the staging tile. This will essentially create a directional graph and make it so troops can come onto the map but not back off.

Anyways. The image below I have selected a US unit for reinforcement. The valid places the unit can be placed (cities) are changed to be highlighted in the ugliest green you've ever seen. Ignore Ohio for the moment. Not sure why that mesh isn't showing but I've got bigger fish to fry than worry about that dumpster of a state.

Right now it is only finding the valid tiles within a number of jumps from the starting tile. I need to also apply more game rule constraints like territory occupation.

Quick update, didn't work too much on it this weekend.

  • Camera can now pan and zoom within a bounds. So now I can make the units a little smaller and fit better on the tiles. This will come in handy for mobile to really get in and select your units and their movements.
  • Camera movement is for mouse in the editor but I think I have it for mobile too (I'll test it down the road and see how far off I am).
  • Finished the refactor. Some of the code is a little cleaner and shorter. There is still some tight coupling between the game logic class and the map but I think that is always going to be the case since doing something to one depends on data or logic from the other.
  • Began implementing a feature that when you click a unit it will show you what it's valid moves are.

The attached photo is a panned and zoomed camera (hard to tell from a still photo)


And for a bonus since we are talking about clever camera things

It's not a camera trick. It's a trick with a camera!

  • Created western invader reinforcement staging area. This includes the troop positioning dummy objects.
  • Instantiated the first wave of western reinforcement troops. During the first turn the type of units is fixed, after that each round is 8 reinforcements of the type you want (assuming you still have that type left in the pool)
  • Fixed bug where I forgot to set the flag on all the city tiles marking them as cities.
  • Fixed unit sprite sizing for western invaders to match the US. I may still need to shrink all units as they are pretty large and don't quite fit.


I'm out of room in the board area for troop reserves and killed units. Thus I need to bring the camera back a bit which I think is going to force me to make camera movement the next priority before any more game logic.

  • Traced the West coast tiles. + Western invasion zones.
  • Renamed the East coast ID's so the tiles show up in game.
  • Created the city icon prefab which is a sprite for a city plus the text. Created all of the instances for the cities.

Didn't have much time so I traced some more tiles. The entire eastern coast is done. I realized afterwards I really should have been working on the West since that's where the next turn will be played out and I need some tiles to move to for testing. So that's what I'll work on next.

I did a little backend work 2 days ago but didn't feel I had enough to show. Tonight I finished up one of the first major breakthroughs for the game!

The U.S. player can make his first move! By selecting the units and then the tile he wants them to go to he can construct his "turn". The first turn of the game for the US player is to simply place his reinforcements in the city tiles. While this is happening, logical rules are preventing the player from...well...breaking the game rules of only placing them in cities, and only 2 units per city.

Once the player has his turn, he hits the complete action button and the commands are sent to the server where they are checked for validity against the rules and if all is well, the moves are executed by the server. At this point the clients receive one of the periodic broadcast messages and realize that they are stale and request the board state from the server and bingo! The clients see the moves made by the U.S. player.

It all seems to be working and this is a major step in the right direction. I think the best way for me to keep developing the game is to continue implementing a single phase of a turn at a time until the game can be fully played. Next up, is the western, southern, and eastern invader reinforcement placements. The good news is this is mostly the same as the US and I can reuse most of the code with a few changes to the logical rules of what is valid.

A few things I don't like. The rats nest of code continues to grow. I'm at a critical juncture of press ahead and hope I can keep it all straight till the end or see what if anything can be done to clean it up before I move on.

Either way, it's great progress and encouraging!

Completed:

  • Infantry game piece art.
  • Hover tank game piece art.
  • Troop transport (mech) game piece art.

Things to figure out:

  • Do I do a different piece for the partisans or just color the infantry piece gray (leaning towards that solution).


Drawing the game pieces has been quite fun. A nice change from the coding. I'm not 100% satisfied but they turned out much better than I anticipated. They will at least work for the initial game. I didn't really have an art style in mind but I do like the flat color and clean lines (the troop kinda breaks this a bit but still feels like it fits in with the others). I honestly don't want too much detail for the pieces as there will already be a lot going on with the board and I don't want a bunch of rendering artifacts when zoomed way out.

Completed:

  • Tiles in-game now have a nice border around them. This is so you can actually tell territories apart.
  • Created some of the game piece artwork. Bomber, chopper, and city icon. These will be rendered to a sprite instead of imported as vector art.

What I don't like:

  • I wasted time upgrading Unity thinking an issue I had was due to an outdated version. Answer is inconclusive but hey, I'm running the most updated version now.

Things I need to think about:

  • Some game pieces look better from the top down like the bomber and chopper. Others are going to look better from the side like a troop or mech vehicle. In real life the 3d plastic pieces work well. I guess I'll just have to live with the different perspectives for the 2d game unless I think of something clever.
  • How to represent a city. This is another one where in the real world the plastic pieces look nice and make it easy to see if a city is on the board or not. I drew the blue icon that is printed on the game board signifying a city territory. I may play around with changing it's color? A top down view of the city plastic piece will look like terrible (just a bunch of rectangles).

Coming next:

  • More code work instead of art. I think I've got enough for placeholders.

Watching Michigan thwamp Florida in football left little time for game-dev but to celebrate Florida's terrible performance I decided to complete the game territories that compose the state. I'm using inkscape to quickly draw the outlines of the territories. In the game I just do some clever parsing of the .svg file and pull out the paths I care about/turn it into a render-able mesh.

One oddity is that vertical and horizontal lines are represented weird in the svg format. Instead of programming a solution with extra special case handling I descoped the problem by simply not drawing any vertical or horizontal lines for the tile outlines. It's an elegant solution.

I haven't tried to draw the outlines in game yet, just a flat shaded tile. Maybe I'll try that soon.

Accomplishments:

  • Selection. Clicking on troops or a tile now get registered. Since a click on an item may do 1 of 30 different things depending on game state and involves other things in the scene (like what tile you may want to move the unit to or another unit to attack), I can't put the game logic in those objects themselves. Instead, when they are clicked, the just throw a message up to the GIANT game logic class saying "hey, I was clicked". The game logic class then needs to decide what to do.
  • Unit movement command. I've got the basic structure representing a units movement. The information needed is the unit in question and the desired tile that he should move to. The tricky bit is that a list of all the DESIRED moves for the turn must be held onto before executing/finalizing command is given and the actions carried out because often the player will move some pieces and decide on a better strategy, or just hit a wrong tile or something.

What I don't Like:

  • My massive game logic class continues to grow large. I've come to the realization that just due to the nature of the game and how tightly pieces, the board, and the rules are tightly coupled there won't be a way to separate the logic. I can try to maybe organize the code a bit better though.
  • The number of cases/permutations I have to handle when a unit or tile is clicked. Things that all determine what we should do about a click include: Is the troop mine, is it my turn, are we on a phase of the game where I should be making moves. That's just the cases to determine what to do. There's another layer of checking for move validity against game rules, does the troop already have a move this turn, etc. etc. Lot's of cases.

What's next:

  • Continue working on making the first move. Getting close. I have a feeling when I am able to make a move and the other clients see it I will get an extra boost of excitement.
Misc:
  • Trying not to burn out this go around so there may not be an update every day. Just going to pace myself and try to average every other day or so.

Rolling on with the new project. Instead of long blog posts I think I'm going to go for shorter lists of things completed. Feels like less of a chore.

What I completed:

  • I think the map state synchronization between client and server is working. Server sends hash every 2 seconds to clients. If a client sees it is out of date it requests the full state from server. Server responds. Client now takes that response and updates the game board accordingly. Right now it's just which force occupies the tile and if the tile has a laser. Troops will be added later. I opted for a simple text human readable format to transmit the game state. Not very optimized but I can do that later or not worry about it since it is such little info anyways.
  • Fixed an issue with the message notifications where once they got larger than the list they would vanish. This notification list is mostly for debugging right now but will be used for game info like "unit x killed in sector y". Still some bugs with the list but not going to worry about it till the finalized version.

What I don't like:

  • There are three giant classes: the map, network manager, and game logic. All three are single instances and pretty tightly intertwined with each other resulting in a boatload of static members and functions. I think this may just be due to the nature of the game and how asynchronous everything is. Not sure the solution here. Seems to be working, just ugly as hell.

What's next:

  • For a player to actually take a turn. The natural start is the first player in the game. The U.S. placing his or her reinforcements.


Nothing visible to show today. Worked on a a bit of UI code which then drove me to the task of font and text rendering. I struck out with getting the freetype2 library to compile so I went on to doing some research reading. Need to sleep on this one and figure out my next move.

After a few days enjoying the weekend and not working on the game it's time to get back in it. I want to start slow and pick up speed to not burn out. Didn't get a whole lot done today but mostly played around with a few tools. Namely, looking at a few 3d modelers (although I'll probably stick with my tried and true 3ds max) and a few online tools for generating noise patters. I want the polygons of the game to have an almost faded, dirty construction paper look to them. Based on some inspiration images I changed the background color to a dark purple as opposed to black. I want to play around with some ideas of doing different gradients but I'm not sure yet how I want to pull that off.

My "game" now has two of those three components with the addition of some camera logic. Meshes now "subscribe" to cameras that render them. This way things like UI graphics will only get rendered by an orthographic camera whereas the world stuff gets rendered by a camera that can zoom and spin. Next up might be a nice star background with a sun. This should give a better reference of rotation of the world in space. A quick demo moving the camera around seems to work just fine.

Today's work was all in the head. Namely solving one of the bigger algorithm challenges for my game. At least for now I want to avoid using any physics engines. I want to keep the game relatively simple. If at some point ragdoll or complex collision detection is needed I'll bring in an engine but for now I think I can pull it off with simple vector math. One of the things that will have to be implemented is a way for me to know what world tile a person, object, or point is over. This will be needed for things like who controls a land tile as well as where to position characters in 3d space so they appear on the surface. These are all derivatives of a common piece of logic. The problem space is this: Given a point in 3d space, what is the tile that is "below" that point (where below means a vector towards the center of the world). In other words there exists a function f(x) that when given a 3d point in space x finds the tile under it and I need to write that function. First I should say that if my world were divided in a simple longitude-latitude fashion the problem would be trivial. But who doesn't like a challenge. The nature of an icosphere is that the triangles that make it up are at weird angles. There may be some O(1) function but I can't come up with it in my head.

Instead I came up with two methods. The first method is actually quite simple. If I calculate the sum of the distance from each face vertex to the target point I can give each tile a "score". The tile with the lowest score should theoretically be the tile under the point. This is pretty fast and pretty easy to implement but there are a few downsides that rule it out as my implementation choice. First, this method only works if all faces have the same shape and size. That is mostly true for an icosphere and I could probably live with the results and tiny errors. The larger problem however is that the vertices that make up the faces must all be equidistant from the center of the sphere. Think of the case where the point is just off the edge of a plateau, the "score" to the flat tile at the top will be small compared to that of the face that has vertices way down low (which raise that faces score super high). In such an edge case the wrong tile will be selected. This is actually a subset case of the all same shape and size requirement.

So here is what I came up with and plan to implement. Given any world face (made up of 3 verts), there exists 3 planes that extend forever. Each plane is made up of three points that lay on the plane. Those 3 points are the center of the world and 2 of the 3 points that make up the face. A point is above a face if and only if it falls within the 3 sided "inverted pyramid" made up by these planes. There are a few technical details. First, I need to be consistent with polygon winding for these 3 imaginary planes. Not hard to do as I am already consistent with the ordering of the vertices that make up the face. I somewhat lied when I said we are going to make a plane...in fact all we really need out of these three planes is each of their normals (I'll explain why position is irrelevant in a minute). Calculating the normal is easy, just the cross product of two vectors constructed from the 3 points of the plane. So now we have 3 normals (1 for each imaginary plane) all pointing inward towards each other. Here is where the clever part comes, each of these constructed planes passes through the center of the world. We simply take the position we are testing and treat its position as a vector. By computing the dot product of this vector against the normal of each plane, we can quickly determine if the point is on the positive or negative side of the plane (and we don't have to worry about position of the plane because the vector to the point we are checking is already relative to a point on the plane (center of the world)) . If it's on the positive side of each of the 3 planes then we've found our tile! This method places no constraints on size or shape of the faces relative to each other. In fact they can even overlap and if a point is "above" more than one tile we can find them all! Although in my case I don't really plan to have any overlap so I'll optimize with an early exit out of the routine. There is also another huge optimization I would like to implement. The naive approach is to just start iterating over every face. Instead, I'm going to take advantage of the fact that the sphere is constructed from subdivided triangles. Essentially I have a tree structure. If I run the above algorithm at the root level I can determine the "hemisphere" to start looking in and repeat the process at each level until I find the face. The base icosphere has 12 traingles and each subsequent subdivision produces 4 traingles per triangle. So take a world that is subdivided 3 times. In a worst case scenario I will only have to do the above algorithm on 12 + 4 + 4 + 4 = 24 faces.

Daily Gamedev

Do something related to your game every day!

joined 3,139 days ago

2024-12
2024-11
2024-10
2024-09
2024-08