ill
   

A Timelord's Travel In Thedas | Alazander's Blog | Baldur's Gate II Redux | Community Contest | Creations of AmstradHero | Dark Sun Glare Blog | Ossian Studios | The Sanctum | RP Singh

2016 : Aug | Sep | Nov | Dec
2014 : Jan | Feb | Mar | Apr | May | June | July | Aug | Sep | Oct
2013 :
Jan | Feb | Mar | Apr | May | June | July | Aug | Sep | Oct | Nov | Dec
2012 :
Jan | Feb | Mar | Apr | May | June | July | Aug | Sep | Oct | Nov | Dec
2011 :
Jan | Feb | Mar | Apr | May | June | July | Aug | Sep | Oct | Nov | Dec
2010 :
Jan | Feb | Mar | Apr | May | June | July | Aug | Sep | Oct | Nov | Dec
2007 :
Jan | Feb | Mar | Apr | May | June
2006 :
Jan | Feb | Mar | Apr | May | June | Oct | Nov | Dec
2005 : Aug | Sep | Oct | Nov | Dec

 

!!! IMPORTANT NEWS !!!

All of your Rose of Eternity needs moving forward can be found at my new blog, http://www.theroseofeternity.com. I hope to see you there!

12/26/16 -Monday: YOU CAN NOW FIGHT IT OUT WITH THE CPU FROM BEGINNING TO END...

Once I was finished with the Kamikaze & Zone AI implementations, I already knew there was only one thing left to do: Get some basic (and I mean basic!) combat logic in so that this new AI and I could actually fight against each other. Turns out, I was able to get more than I expected in. Either way, the end result is that you can now fight it out with the CPU from beginning to end.

HEALTH BARS

As I sat down to start planning out the combat system, I immediately started to think about displaying health bars, and how difficult it would be. I didn't originally plan to include them, but the more I thought about it, from a usability standpoint, it's better to be able to get a quick idea of the HP of your allies/enemies, versus having to highlight them to see it in their character sheet.

I gotta say, of all of the things I have done with Unity so far, this was... really easy...

Below each unit (which I may switch to above them at some point), I just added a UI canvas, and under that, an image. What does this image consist of? Just a damn background color. Green for allies, red for enemies.

The most intriguing part of creating this was how I would end up being able to show the health bar going down, as you can see in today's GIF. Turns out, each UI element has a scale that goes from 0 to 1 for each coordinate (x, y, x). If I modify the x coordinate to something less than 1, the image gets shorter in length. If I left align the image to the canvas it sits in, when I lower the scale, it looks like the health has decreased from the right to the left.

So I just had to hook this into existing systems to check the current HP of the unit, get the % of their total HP, and then apply that value to the scale, and voila, I have prototyped health bars that decrease in length as the unit takes more damage.

Implemented in like an hour, which is how I wish all things would go :)

COMBAT DAMAGE AND DEATH

Nothing too special going on here. It's pretty hardcoded, as of now, the damage a unit can apply is equal to their level times 2. Yep, that's it. I'll worry about weapons, armor stats, etc. later.

Death was pretty easy as well. Whenever current HP <= 0, destroy the unit, and also remove references to it from everywhere else, like the Turn Order GUI, tile data, etc.

ANIMATION

I was definitely going for something quick and dirty. Some sort of way of showing people that the attack happened, but nothing I wanted to spend too much time on. I ended up move the unit toward the target half a tile, then half a tile back. Like I said, quick and dirty.

USED ABILITY

I added this more so because I was on a roll, so I figured, why the hell not? This is really something that would be used for abilities, but decided to show the used "weapon" in each attack. Yes, those weapons are hardcoded. And when I say hardcoded, I mean, it's just a string set on each unit via their inspector. As with everything else in this prototype, I can just hook in the real logic later.

------------------------------------------------------------------

So yeah, with all of the above done, I was able to get the game in a great working state. I didn't talk about the selection menu, because I'd like to leave that for its own blog entry. But just know that it was a *shock* quick and dirty implementation.

Next, I'll be working on... Well, for once, I actually need to keep this a secret!

Till tomorrow...

 

12/22/16 -Thursday: THAT SWEET ZONE DEFENSE...ERR, ZONE AI....

After I implemented my Kamikaze A.I., I knew the fun was over for a bit, because the code was disgusting as all hell, and I had to bring some sort of decency to it, lest I lose my mind. So that's what I did during the earlier part of the day. And damn, it was boring as shit.

When working on this game, the best parts are when I have a very clear goal, and it's all about just implementing it. It's a whole other story if I have a vague goal of what I want to do (i.e. refactor shitty A.I. code), and then spend 80% of the time trying to figure out the best way to do it.

When this happens during the day, for whatever reason, I start to nod off. I'm definitely a night person. I can be up from like 7pm-2am no problem, but 2 in the afternoon? If I'm not working on some pretty cool stuff, it's curtains for me.

After taking a few breaks, and after the wife and my daughter came home, I got a little re-energized, and was able to pin down exactly what I needed to do, and dammit, just do it. Of course, this will definitely change later. But you know, prototypes.

Once I was done refactoring the main code, it was pretty easy for me to extend my base AI class with ZoneAI, and implement a function that makes sure that if an enemy is not within their zone, do nothing.

It's funny, because this is one of those things you don't really think of (well, I don't anyway) until you have to implement it. We've all seen this type of enemy, and for me, mostly in the Fire Emblem series. You're happily klling enemies left and right, but there are some enemies that don't approach. Then you finally get in range of them (usually the range is a combination of thier move + attack), and they come barreling towards you.

See below for an example of my implementation:

The first enemy unit attacks because you're within their zone, but the other 3 do nothing, which is, well... you know, zone A.I. So yeah, it works :)

Of course, what is the point of all this A.I. stuff without enemies or the player being able to attack? Yep, that's next on my plate for things to prototype.

Till tomorrow...

 

12/20/16 -Tuesday: LET'S DO THIS!!!

Okay, I've procrasinated enough. I've been trying to handle all of these other things (which are important), but at the end of the day, it's all lead up to this. The first implementation of artificial intelligence in this game.

And god damn, what a start to it all.

I knew I wanted to start out with the most basic A.I., and move on from there. When I mean basic, I'm talking about just having the enemy units move towards the ally units, kamikaze style. There's no regard for what will happen to them, they just find the nearest opposing faction unit, and move towards them. Nice and easy. Or, so I think everything is when I sit down to start implementing it :)

Forgetting about the actual code structure, which I'll come back to at another point, I just wanted a quick and dirty implementation of having the enemy make their way towards the player. Well, I did create an AIManager class, but it's just a spider web of a bunch of functions at the moment.

First thing I had to create was a function that would find the nearest enemy unit. That was easy enough, and I was able to code that function within minutes. Next came my first sort of stumbling block. The idea was, once the target was found, an appropriate tile next to them had to be found. My first solution was to build a collection of all the tiles that the unit could move to. From there, I would calculate the distance between each tile in that collection and the tile that the nearest enemy was standing on. Once I found the lowest, that would be my target tile to move to.

From there, I would make use of existing code to actually find a path to the target, then move them there.

See results below:

I immediately realized there were issues. If you look closely:

  • The 1st enemy is making their way to the nearest target (the teal character), but then pulls up. Why?! 

  • The 2nd enemy starts moving south, but then starts cutting south-west, instead of proceeding over the desert bridge.

  • The 3rd enemy is confused as shit and does nothing.

  • The 4th enemy seems to know what is going on.

After a bit of debugging, it was pretty clear that the issue was that while I have built in the logic to not highlight un-walkable tiles, or have the pathfinding ignore said un-walkable tiles, this same logic was not used when finding the right target tile before a move. For instance, with the 2nd enemy, they're clearly not thinking about the water, so they think that the fastest way to the target is by heading south-west, instead of realizing that it's not worth the time, and that a better path needs to be found.

Then I had an epiphany!

Why in the hell was I trying to write logic to find a target tile, when I sort of already had that done in my Pathfinder class?! Sure, there were some minor differences, the biggest one being that the Pathfinder class requires the source/final target tiles, and if the target tile cannot be reached, it returns nothing. In this case, the enemy won't be able to reach the target in one move, which is why I'm going through this work to determine the best tile to move them to, a tile that's closest to the target.

Then I realized that I could just pass in the final target's tile to the Pathfinder class, then once the path was generated, I could remove all tiles from it that the enemy actually couldn't reach. That would give the shorter path I needed, while maintaining the core logic of the path generation.

See results below:

Now all the enemy units are moving in the right direction! Woo hoo!

Tomorrow, I'll need to take this spaghetti code, and refactor the shit out of it. From there, I'll start working on some other basic AI templates. Maybe a unit that won't move towards you until you're within range. Or maybe a defender unit that follows around a leader. The options are limitless!

Till tomorrow...

12/17/16 -Saturday: FIXING PATHFINDING...

So, I implemented pathfinding a while back. But like everything else I've been working on, I just did a quick and dirty implementation and moved on. Fast forward to today, and now that I'm getting ready to finally embark on that journey that is Unit A.I., I've had to take a small detour to fix up a known bug.

In today's GIF, you can see me selecting a tile across the water for a particular unit. And, you can see them do the right thing, which is go around the water, across the desert bridge (why do I even have that there, lol), and to the destination. But this wasn't what would happen a few days ago. You'd get the following:

As you can see, the unit is going right across the water, which is definitely incorrect. So, how did I get here, and how did I fix it?

When you think about how I've implemented pathfinding, there's 2 main components:

--------------------------------------------------------------------

TILE SELECTION

This is where you, the player get to select which tiles you can move to. I've been discussing things related to this for the past few weeks, most notably, my blog entries about tile highlighting. Long story short, I make sure to block tiles you cannot go to. Water, mountains, etc. You know, the usual stuff. Nothing too crazy here.

TILE MOVEMENT

This is where things got hairy during my initial implementation. You see, while I block the player from selecting a final destination tile, I wasn't blocking the pathfinding logic from said tiles. So, as you can see in the last GIF, you can select the tile across the water, but when the path is generated by my pathfinding class, any and all tiles were up for grabs.

--------------------------------------------------------------------

Turns out, I needed to implement this concept of Tile Cost. This is basically a number that tells the system how much it will cost to enter a tile. Originally, this value was calculated by finding the range between tiles. So if you had a tile at coordinate (0, 0), and at (1, 0), the cost to move to the tile would be 1.

The real way it needs to be calculated is by looking at some properties I have in my TileData class, most important, IsWalkable, and Movement. The former gets a cost of Infinity, while the latter has a value of (abs(tself) + 1). So for grass terrain, the movement modifier is 0, so the cost ends up being 1. Desert terrain has a movement modifier of -2, so its cost ends up being (abs(-2) + 1), which ends up being 3. So what do all these numbers mean?

Simply put, when the pathfinder is trying to figure out the best way forward, let's say it's looking at some water, which is not walkable. It's cost will be infinity, so the next thing the pathfinding is say, "Oh shit, infinity is a lot, is there a better path? Oh, look, there is some grass terrain that has a cost of 1. Yeah, I think I'll take that one." That's why in the main GIF, you see the unit avoiding the water, as it should.

Now that I have this implemented, I just need to write some unit tests to confirm that the unit will always avoid high cost tiles, then I'll be good. Then I can finally start writing some A.I. Oh man, this is gonna be fun. About time to get this game looking like a real game :)

Till tomorrow...

12/15/16 -Thursday: TURN ORDER GUI WORK...

As I discussed at the end of my last journal entry, I have a Trello card, called "Allow Clickable Turn Order GUI". Well, I finally got around to addressing it, and it turned out to be pretty easy.

So what was I attempting to do, you ask? Well, since I want to eventually support larger battlefield, which would result in more units, I figured it would be nice if while looking at the Turn Order GUI if you could click on the portrait of the unit, and have the camera pan to them, while also highlighting the area they can move to. Nothing revolutionary, I know, but something that I really wanted to get done.

It turned out to be pretty easy because I already had built in functions to do the following:

  • Pan the camera to a specific unit

  • Highlight the tiles a unit can move to

The majority of the work was implementing "Mouse Pointer Click" events for the individual portraits, which undernath the hood, or standard Unity UI Image components. I created my own class, TurnOrderImage, and implemented said events, and within a half hour or so, wired everything up.

While I was working on this, other ideas started coming to. The portrait the player is hovering over should be highlighted. Or maybe increase in size by 5% or so, so it's clear it's the one being hovered over. I started going down that rabbit hole, but the end result ended up with the possiblity of creating custom shaders, and other things I just didn't have the time to deal with. So I just left this as is.

What's next? Well, the only card I have left has to do with writing unit tests for 5 classes. It's nothing glamarous, but I am about to start working on some simple enemy unit AI, and all of these classes will play a part in it. So, I might as well get them fully tested, as I'll be making tons of changes, and I don't feel like breaking a bunch of shit, and not knowing until much later.

Till tomorrow...

12/10/16 -Saturday: 3RD TIME WAS THE CHARM!!!

One of the cards I have on my Prototype board in Trello was "Show Attack Tiles". I've already had the logic to highlight the movement tiles for a while, but I always knew that I wanted to come back and incease the range of highlighted tiles to show where the unit can't actually damage other units with its equipped weapon.

The idea actually came from the Fire Emblem series, in particular, the ones on the 3DS (though I'm sure the GBA ones also did this). Honestly, that's the only turn based RPG series I've played in the past decade. Of course, I came up with Final Fantasy Tactics, Shining Force, etc., but I haven't played those in a damn long time. But as far as I can remember, those games didn't have that. If you wanted to see if you were within range of hitting an enemy after a move, you would have to first move there, then check. This way removes a step, which in itself doesn't seem like much, but if you add that up over hours of playing the game, plus add in the fact that you could potentially see X enemies you're within range with, versus checking each one... You see where I'm going with this.

And this is really at the core of how I'm attempting to design this game. I want to eliminate as many superfluous steps as possible. The player should just be able to get on with the game, and not bothered by pop up confirmation buttons, or the aforementioned issue of finding out if you're within range of attack and enemy.

Here is an example of how it is with Fire Emblem:

Pretty self explanatory. So, as you can see by looking at today's GIF, you'll see the following 4 units and their movement/attack ranges (denoted by the color of the circle that represents the unit):

  • Pink: Movement 2 - Attack Range 1

  • Dark Blue: Movement 2 - Attack Range 2

  • Teal/Light Blue: Movement 4 - Attack Range 2

  • Green: Movement 5 - Attack Range 1

Some things to consider for each of those units:

  • They cannot move to a tile that is occupied by another, and the attack highlighting does not show up for friendly units

  • While a tile may be unwalkable for one unit (mountains, water, etc.), they can still attack other units at those unwalkable units (i.e. flying unit)

  • If the unit has enough movement to technically make it to the other side of a unwalkable tile, but that tile ends up being orphaned (i.e. no connecting tiles), then that tile is inaccessable, and therefore not highlighted. Of course, if that unit can fly/teleport, that's a different story. For now, I'm not even dealing with that. One thing at a time :)

Now, this took me... I guess 3 days to complete? I cannot remember, but I did have my daughter with me Friday night/all day Saturday as my wife was away, and I try not to be a terrible Father, so of course I couldn't do as much as I would normally get done with her here to help. I ended up implementing different solutions, and the 3rd one ended up being the charm.

FIRST ATTEMPT

At first, I was like, "Oh yeah, this will be easy. I already implemented the highlighting of the movement tiles, so adding an additional x tiles to iterate over, and making them red will be easy."

And I did just that. The movement highlighting logic loops over all 8 directions for x number of tiles the unit can move. So I just increased that by 2, and was hoping I would be on my merry way.

Then, it became apparent to me that I had a terrible bug in the system, where I was showing orphaned tiles. I had never really noticed it until I moving towards the water on the map with units that had a movement of >= 5. What I ended up seeing was this orphaned blue tile surrounded by red tiles. No bueno.

SECOND ATTEMPT

For this next attempt, I had to take a step back and think about it. How could I not show these orphaned tiles. I decided to start down a path where I would show all tiles, then run another function that would locate the orphaned the tiles and remove them from the game. This all happens pretty quickly, so the player would never see it, but it's not that efficient. Again, I'm in prototype mode, so I didn't let those details derail me.

I had some logic coded up in between playing with my daughter and putting her to sleep. When I came down to my man cave, I was excited to try it out. It seemed to be working... Most of the time, but there were edge cases where the right attack tile was not highlighted, or a movement tile, for that matter.

THIRD ATTEMPT

At this point, I was getting a terrible feeling I was going to have to leverage my pathfinding code to do something like... Check if every movement tile could actually be reached. Again, not terrible efficient, but again, this is a prototype.

Luckily, before I went down that path, I realized I had a bug in my IsOrphanedTile function, where it was only checking N, E, S, W tiles. All NE, SE, NW, SW tiles were ignored. Sigh... Even more, I realized that I had the same bug in my HighlightAttackTiles function as well. Double sigh... Also, because yay for code re-usability, I had all the logic for both attack and movement highlighting filtered to a single function, which calls IsOrphanedTile. Which of course doens't make sense for attack tiles, since those could legitimately be orphaned. Triple sigh...

Once I realized the error of my ways, I quickly coded up fixes, and voila, the shit worked.

So the way it works is as follows:

  • Clear out all highlighted tiles

  • Highlight all movement tiles (which will now handle kicking out orphaned tiles properly)

  • Taking the existing movement tiles, highlight all attack tiles. This is heavily predicated on the highlighted movement tiles being created properly.

Now, I have some small code changes before checking it in, merge the branch to master ,and moving on to the next card I have.

Speaking of that next card, it's "Allow Clickable Turn Order GUI". This terribly ordered card title simply means that when the user clicks on a portrait on the Turn Order GUI, the camera will focus on that unit on the map. I've never dealt with handling those types of events on UI objects before, so should be fun.

Till tomorrow...

P.S. All this logic I just put in should just work for the CPU. We'll see... 

12/2/16 -Friday: ONE HELL OF A MONTH!!!

STATE OF THE UNION

Well, well, well... I just had one hell of a month! I mean, everything was firing on all cylinders. Most of the free time I had, whether it be on the train, or at home after the family went to sleep, was spent doing some sort of work. And if you look at the number of posts I had last month, you can see how it directly ties into how productive I was.

So what happened, you ask? Simple... Destiny: Rise of Iron.

It came out on September 20th, and I knew that I wanted to put my all into that game. Single player story, exotic quests, a little PVP, and ultimately normal/heroic raids. Going in, I knew what it was. I wasn't going to be able to do much at all, while I put my all into the game that I knew would be my last for a while.

Staying true to my intentions, around the time I finished all activities, leaving me not much of anything else to do, I decided to shelve it. I mean, I would have shelved it until the Spring 2017 update anyway, but I knew what I was going to end up spending my time on.

It's been one hell of a run. I ended up prototyping the following:

  • State Machine

  • Pathfinding for player controlled units

  • Unit Turn Order (including UI)

  • Map Scrolling with WASD keys and mouse

  • Unit Tests

  • Added SFX and dynamic music

I have more than achieved the goals I set in the November State of the Union. I couldn't be happier. However, I want to keep this going. Already for today's updated, I done the following:

Github Integration

The picture of the day is meant for this part of today's update. I have, for far too long, avoided this. Why, I have no idea. I'm a software engineer. This is what I do on the daily basis. I fully understand the importance of source control. And yet, here we are :)

Well, before getting distracted by SFX and music, I had said that this was going to be easy, and easy, it was. Since I'm used to working in Unix environments, I made sure that my GIT client had a bash interface I could use, so I could do all GIT related things in there. No fancy windows explorer plugins or the like for me.

As of now, the repository is public, but empty. I'll push up my prototype branch either later tonight, or tomorrow. I'll most likely make the repo private, which will cost like $7 a month or something. There's nothing too secret about what I'm doing, but better to do it now while I'm already doing everything else...

...Speaking of which...

Trello

...Yep, got started with Trello as well, because, why the hell not. For those not in the know, this is software used to track bugs, issues, featurs, etc. for projects. I've not put too much effort into it, but at the very leasy, it'll be a nice visual guide for me as I try to keep track of all the things I'm working on. I'll continue to iterate on how I use it, and I'm sure at some point, I'll be ready to get a job as a project manager :)

What's On The Agenda This Month

  • Refactor the hell out of the code, and get it out of "prototype" spaghetti mess into somethig I would be proud to show others

  • Integrate some cheap unity assets for units (possibly tiles as well), and try to get some animations with said cheap unity assets for units

  • Implement actions players can take during their turns. Right now, you can just move. That's not so much fun anymore. You need to be able to "Attack", "Defend", use an ability, item, etc.

  • Enemy AI. I'm not going all Skynet or anything, but I need the very basics at first, where they just try to go and attack whatever is closest to them. Then I'll start implementing a priority list system, sort of like the Gambit System from Final Fantasy XII. Imagine if the enemy is a healer. They could have something like the following as an AI list:

    • Resurrect closest ally

    • Cast heal on self if HP < 40%

    • Cast heal on ally if HP < 40%

    • Attack nearest enemy

Exapnding on the AI a bit, it just goes down this list until it hits something it can act on. Pretty simple. Actually, Dragon Age: Origins used a smiliar system. I know it well, because I had to tweak it to make sure that party members would use their custom abilities the base game didn't know about.

Of course, I didn't write the underlying engine, but I know how it should work. So yeah, I think I'll roll with what I know, until told otherwise.

Anyway, If I can get these items done, I'll feel pretty good. I'd like to think December will be like November, but I don't want to get ahead of myself. Although, I will be on staycation starting 12/15 until the rest of the year, but I don't want to get too excited. Here's hoping.

Till tomorrow...

Website contents copyright (c) 2006 by Leonard Bedner
   
thr