Dev Update #8: Terrain Controls are In!

Dev Update #8: Terrain Controls are In!

Woo! Great progress this weekend.

Finished with the basic implementation of the terrain raising/lowering controllers.

You can now edit the level at the vertex and the tile level. (which raises all surrounding vertices). Simply select the desired tool (per vertex/per tile), click and drag the desired tile; up increases height, down decreases height. Simple as can be:


Though that’s less a valid course as it is a trip through hell.

Now I gotta work on the stepping levels so that the course building is less insane. Though you’ll still be able to reach insane levels if you so desire. I also want to implement a controller for edges, and one for raising up the selected tile only, similar to what you can find in the Rollercoaster Tycoon of yore.

Next perhaps a flattening tool, and even the possibility of affecting multiple vertices/tiles at once. All should be straightforward to implement with the current system. But will be in the wishlist for now.

Til next time!

Dev Update #7: Auto Tiling FTW!

Dev Update #7: Auto Tiling FTW!


Finished implementing a basic 4-bit auto tiling system using bitmasking. Works like a treat!


(You can find some helpful resource on using bitmasks for auto tiling here and here.)

It has been implemented so far for the fairway, for the bunker, and for the green. Going to draw up the tiles for the trees next, and integrate the hole with the green. Next is height controllers!

Dev Update #6: No more seams!

Dev Update #6: No more seams!

Good news!

Contrary to what I was speculating, the issue with the seams turned out to be simply the bleeding from the textures. It always ended up sampling at least one pixel from the adjacent texture too.

So, the fix turned out to be an easy one: rearrange the tiles inside the texture so that they are always bordered by affinity. And seams are gone!


I’ve also increased the tile size to 32×32, so I can add in more detail later if so desired. Now two things to finish off the basic implementation of the new terrain:

-Make it so the tile chooses the correct texture to display based on its neighbours

-Add controls for changing the height of the vertices

After tackling those two, I’ll need to take a new look at the shot creation system, since before it was relying on raycasts for some things still. Either change the system from raycasts to simply analyzing the grid, which could be cheaper, or turn the flat tiles into cubes so that it has a proper volume. That’s for later!

Dev Update #5: Implemented the new Terrain

Dev Update #5: Implemented the new Terrain


After wrestling with it, was able to replace the current tile system with the height-enabled terrain system. I still need to do some adjustments so that trees and other objects are also automatically placed, but I’m glad to get the thing working as it is:


You can see from the wireframe map that the shared vertices are also taken note of and raised together to avoid some bad geometry. Working on improving adding controls for manipulating the height of the map too!

However, one issued appeared:

Every square is it’s own separate mesh. Did it that way to have easier control/prototyping of the UV maps since each quad has it’s own easily accessible UV array. (If they were in a single mesh, it would be trickier to handle them, but not impossible).

So for some reason, there is a seam in between the each mesh, as you can see circled in red:


The cause of this is, I’m guessing, some imprecision regarding placement of the vertices and the processing of the graphics going bad at some point. Tomorrow I’ll experiment with using a single mesh and keeping track of UVs with structs or something, and see if this issue goes away.

Dev Update #4: Reaching Higher Grounds

Dev Update #4: Reaching Higher Grounds


On the suggestion of a friend, I decided to take the time to experiment with procedurally generating terrain so that height can be added and give you more diversity on the golf course.

As such, I created a simple TerrainMesh class that generates a single polygon, and maps its UV coordinate according to the type of tile I want. Also implemented methods to allow me to change the Y component of the vertices, so that we can add height. So we can go from this:


To this:


Textures are now 16px*16px inside a larger 512px texture. Can easily increase the size to make it better looking if I so desire, and the system will adjust easily.

Next I’ll implement vertice control, so that the vertices can be selected and raised, and then replace the current system with this. Will also give me more control over creating other meshes to populate the tiles.

Til next time!

Quirk #1: Greed isn’t good

Quirk #1: Greed isn’t good

Inaugurating the Quirk category, is an interesting problem that appeared when trying to program the base shot function to avoid tiles where the next stroke would be blocked.

As it is now, the algorithm can be considered greedy; that is, it tends to find the local maximum instead of the global maximum. What does that mean?

The function to find the next best stroke focuses on mainly one factor: Distance covered by the stroke. So the function will always try to travel as far as possible with each stroke in order to minimize the Par score. However, in taking obstacles into account, sometimes the stroke with the furthest reach is not the best stroke! As we can see below:


There’s at least two or three tiles before the chosen one that could be used for a perfectly fine stroke, which would eliminate the danger of hitting either of the two trees in the middle. But since the algorithm is currently greedy, it’ll maximize locally, completely ignoring the global maximum. If we tweak the course further, like below, we can safely get rid of this issue:

But this is not good. Users would look at the course and go “What! There’s a perfectly fine play to be done over there! Dumb game!”. And we can’t have that!

So it’s time to smooth out the stroke calculation to look into the future for at least one or two moves, so that it can more accurately get rid of local maximums, and aim for the global.

Dev Update #3: Automation and Refactoring

Dev Update #3: Automation and Refactoring


Today’s update is pretty much what I had announced on the previous update, plus some work moving certain methods to better locations in the code.

So now the base shot will be automatically updated as we modify the landscape surrounding the course. This will only work if the hole is closed, so that you can’t modify the hole as players are playing it. (This may be revised later if it proves to be more fun to allow you to grief the AI)

Also optimized the process by making the course cache the nearby tiles once the course is created, and then further process to calculate the base shot become a lot faster and cheaper since we don’t need to do raycasts every time we update. It also allowed me to add more precision by refining the raycasts and adding the neighbours of the tiles to the cache as well. Here’s some pictures explaining the process:

Start off by placing the Tee and the Hole tiles, the base shot is generated. No fairway, so it is happy to find a random grass tile somewhere:


Then I begin adding some fairway to the course. You can see the path change, and become incomplete. That tells you that this course isn’t really eligible for the public since it can’t find a proper Par without having to resort to landing on grass, and that is bad mkay.


On the next patch of fairway, the course becomes doable, as it can finally reach the hole:


Needs more challenge, though, so I add some bunkers here and there, and modify the overall base shot:


That’s more like it. That first stroke is treading dangerously near the bunker, which is great. So on to continuing my edit:


A short Par 5, which could easily be completed in 4 for a nice birdie, or even for an eagle if your chipping game is strong. Still could do with some adjustments here and there, but it’s a nice start. And all done dynamically, so I don’t need that “refresh” button anymore! Progress++!

Next step will be taking hazard into account when making the base shot. Now the function will only seek to land in fairway or green, which is what we want. But if there’s a tree in the way, it won’t care and draw the path right through it. That’s NG, as we say in Japan. This might be a stroke for a better golf player; but the par is calculated based on the handicap 0 player, who likely wouldn’t try such a risky move! So that’s the next issue to tackle on my list!

Hope you enjoyed the break down! Any questions/suggestions, don’t be afraid to comment!

Dev Update #2: Refreshing the Base shot

Dev Update #2: Refreshing the Base shot

Hello folks!

Tonight I’ve finished the first pass at implementing the function to refresh the base shot, for use when you are landscaping your beautiful course. Right now it needs to be triggered manually via a button, but once I refine it a bit it will happen automatically if you place a tile in the “path” of the course. Time for pictures!

Here we have a first pass at refreshing the base shot of the course. The origin point of the red/blue/yellow lines are the end/begin point of every stroke. These lines are the directions we cast a ray when trying to find eligible tiles for the shot. It looks only for green/hole/fairway tiles at the moment, as that’s where the player would be regularly aiming for:


With 441m for a Par 5, this is slightly on the shorter end, so it could theoretically land on the green with 3 shots without a terrible amount of effort.

Next I tweaked the fairway a bit, and refreshed the course again:


The slight change in layout produced a slightly larger course in the same area, rising up to 450m. But this shows one limitation of the current system: If the angle of the yellow/red lines was smaller, we would have been able to hit the green in our third shot, instead of necessitating a fourth shot to be in a better range. Or even, upon finding the hole, exploring the nearby tiles to find the extent of the green, so that we could have a better decision. Maybe I could reduce the angle of the check/tweak number of rays based on distance to the hole. So further away strokes can explore the area better for possibilities, while nearby strokes need to be more specific towards the hole. Or even simply adding the neighbours of the tiles to the list would suffice. I’ll test this tomorrow!

Still, I didn’t really want the course to fall down that side, so I changed it once again:


This produced an even shorter course (potentially), much more straightforward, and easier. A very short Par 5, barely a Par 5 even. Extremely easy, but I like it, as it provides some good base to increase difficulty, specially on the first stroke. It barely lands on the fairway, so less confident golfers might instead burn a stroke on getting to the earlier fairway patch first, to get into a better position. And I could add a bunker at the entrance, like below:


Now this would really discourage less confident golfers, as the position of the bunkers ups the stake in case of a mistake, and would reward confident golfers who were able to land the shot, making them feel great and more willing to pay the price of membership. Capitalism, yo!

That’s it for today! Tomorrow I’ll automate the base shot generation process, to reduce clicking amount, and improve the function further so that it can make better decisions when mapping out the course. Afterwards, I’ll make it detect if there’s hazards on the way, so as to avoid and look for a better alternative. Maybe ace golfers would try the hazard shortcut, but the base shot isn’t for them anyway!

Til next time!

Dev Update #1.1: A* Update

Dev Update #1.1: A* Update

So one last update before calling it a day, just improved the A* pathfinding to take into account undesirable tiles while tracing the basic shot from the Tee, and to sample in all 8 neighbours instead of just the regular four. You can see it in action below:


  • The solid white line represents the direct distance to the hole
  • The blue tiles are the tiles selected by the A* algorithm as the best candidates for strokes
  • The dashed line is the combination of strokes creating the basic shot of this course

The distance to hole also changes based on the strokes created by the basic shot, and of course so does the Par rating. At 282m, this is a rather short Par 4 that can decently be accomplished in 3.

Next step is to make the algorithm take into account if there’s any fairways between the tee and the hole, in order to create more desirable base shots.