Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

The Wayfarer (Tentative Title)

A topic by JEJoll created Aug 22, 2017 Views: 1,494 Replies: 11
Viewing posts 1 to 11

I've been working on my current project for about six months now, and have been blogging about it over on GameDev.net since the beginning. Given that itch.io is a potential market, I thought it might be smart to start blogging over here as well. 

These first few posts will be duplicates of the blogs I've already written, just to keep everyone in the loop, but there will be a lot more content coming as the project continues to progress. 

ALL OVER THE PLACE

In my last post I discussed an Action/RPG/Platformer/Diabloesque/JRPG game that I had started working on, and showed a short prototype video. As if the genre of this game wasn’t already all over the place enough, I’ve since dropped the project (for now at least), and started work on something else.

The main reason for this was simply the lack of assets available to me for the game I wanted to make. I wanted to have fully modular armor for my character, but I simply couldn’t find the assets that I needed, even paid assets, and I can’t afford to hire an artist to create the level of sophistication for the armor that I wanted. This aspect of the game was really important to me, and without it, it just wouldn’t have felt complete. However, I happened upon a large number of highly reusable, customizable, affordable and high quality assets during my search which inspired me to go a slightly different route. Thanks to the prepaid Visa cards I got for Christmas, I was even able to buy a decent number of them ;).

Ever since I was a kid, I’ve been a huge fan of First Person Dungeon Crawlers. The first that comes to mind is SSI’s 1991 game Eye of The Beholder which was awesome (somehow I thought that flipping through a book to find the copyright protection phrase actually added to the fun). Even writing this I get nostalgic thinking about similar games like Catacomb 3DArcanaUltima Underworld, and of course, Daggerfall. This is a genre I’m always returning to. Even with AAA titles like Skyrim and Far Cry sitting on my computer, I’ll find myself putting them down in favor of playing old Dungeon Crawlers that I’d never heard of (like Anvil of Dawn).

In the last few years, I’ve been delighted whenever I’ve found a new title in the same vein as these classics, and to see how well they’ve been received.

Legend Of Grimrock did an amazing job of remaining true to these old classics while providing the added bonus of beautiful modern graphics, and has done incredibly well in terms of reception and sales.

Star Crawlers (even though it’s still in Early Access) manages to hang on to the meat of the genre while spicing it up with Sci-Fi flavors and innovative new features.

The Quest HD , a lesser known 2016 re-release of an older game is a full fledged first person dungeon crawler in beautiful 2D with open world environments and a great story. I might even argue that it outclasses many of the above titles in many ways. Really worth a look if you’re into this kind of thing.

I digress.

The point is: I really love these kinds of games. I don’t know if it’s something about the atmosphere, the storytelling, looting and killing or just the nostalgia of it all, but I think they stand out as my favorite genre.

So I’ve decided to make one!

NAILING THINGS DOWN

Like all of the games I come up with and want to make (very few of which even see as much as a keystroke of development), I’ve been thinking about this game pretty much non-stop for a couple of weeks. I’ve got a ton of ideas for the game–some to do with how to ‘stay true’ to the genre, some to do with how to deviate to add something original and worthwhile.

A few things I know for sure:

  1. I’m doing this one right. No half-assed hacking just to get shit done. I’m going to need a proper outline and game design doc, and I’m going to have to establish a normal routine so the project doesn’t rust and atrophy. Regular refactoring as well. I can’t have the tangled messes I’ve let happen in other projects.
  2. Grid-Based movement with some kind of turn-based play (this could be either semi-turn-based or full-out ‘wait for player action’).
  3. Nice 3D graphics. I really want to take full advantage of Unity’s new PBR and Lighting to make something that really looks great, and as I’ve said, I just got my hands on some really top-notch assets.

I’m tempted to add more in the above list, but, to stay on the safe side, I’ll make a second list of potential features currently under consideration:

  1. Multiple Levels/Areas–I think it would be more fun to have the player have the opportunity to spelunk in a cave system, bushwhack in a jungle, pillage in a crypt as well as crawl in the good ol’ dungeon.
  2. Open-world–I know what you’re thinking. How is this possible in a Dungeon Crawler? Seriously, have a look at The Quest. It integrates dungeon crawling and open-worldedness perfectly. A part of this is having towns that can be visited where quests can be undertaken and loot can be bought and sold (a feature missing from many dungeon crawlers).
  3. Complex character development–If any of you have read my earlier journals and are familiar with the last game I completed, Pixel Zombie Shooter, then you’ll know I’m keen on upgrades. I’d like to have a nice multi-branched skill tree for my players to fill up as they adventure.
  4. Questing–I briefly touched on this in number 2, but I’d really like to have some non-linear questing in this one as well. I think it would offer a lot of opportunity to develop lore and give me a chance to do some good storytelling.
  5. Procedural Generation–Yeah, I know. Buzz word. But seriously, I really want to get into this. I’ve already got some ideas for randomized weapon implementations like those found in Diablo, as well as for infinite guild quests and random dungeon areas. On that note, I’m not sure if I’d be interested in all hostile areas (dungeons, forests, etc.) being procedural, or just special ‘grinding/looting’ areas.

FINDING MY WAY

Ok. You’ve listened to me rant about this new game idea I’m obsessed about, but talk is cheap. Here come a few things to look at as a reward for sticking through this post so far.

I’ve only had two development sessions on this game so far, and I think they both went well. In both cases, I spent a full day prior to my night-time dev session thinking on and off about how best to implement a feature, and in each session, I’ve been able to successfully implement at least a basically functional version of said feature in only a small amount of time.

The first of these is a simple movement controller.

The Code:

CharacterMovementController.cs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using UnityEngine;
using System.Collections;
public class CharacterMovementController : MonoBehaviour {
    [SerializeField] //How long it should take to rotate or move the camera    
    private float animationTime = 0.35f;
    [SerializeField] //The amount to move the player by. Should be equal to the size of each level 'tile'    
    private float unitSize = 3f;
    [SerializeField]  //How much to rotate on each rotation (1 == 360?). This shouldn't change unless allowing diagonal movement    
    private float rotationAmount = 0.25f;
    [SerializeField] //How high off the ground the player sits.    
    private float playerHeight = 1.75f;
    [SerializeField] //The easeType to use for the iTween animation.    
    private iTween.EaseType easeType = iTween.EaseType.linear;
    [SerializeField] //This is used to determine appropriate positioning when climbing/descending uneven terrain.    
    private HeightProbe heightProbePrefab;
    private Hashtable iTweenArgs;
    private bool canMove = true;    //Initialize itween args    
    void Start() {
        iTweenArgs = new Hashtable();
        iTweenArgs["time"] = animationTime;
        iTweenArgs["oncompletetarget"] = this.gameObject;
        iTweenArgs["oncompleteparams"] = true;
        iTweenArgs["oncomplete"] = "ToggleMovement";
        iTweenArgs["easetype"] = easeType;
    }
    void Update() {
        /* Uncomment to allow these values to be manipulated via the inspector at runtime for testing        
         * iTweenArgs["time"] = animationTime;
         * iTweenArgs["easetype"] = easeType; 
        */
        //Move or rotate the player based on input.        
        if (canMove) {
            if (Input.GetKey(KeyCode.W)) {
                Move(transform.forward);
            } else if (Input.GetKey(KeyCode.S)) {
                Move(-transform.forward);
            } else if (Input.GetKey(KeyCode.D)) {
                Move(transform.right);
            } else if (Input.GetKey(KeyCode.A)) {
                Move(-transform.right);
            } else if (Input.GetKey(KeyCode.E)) {
                Rotate(Vector3.up);
            } else if (Input.GetKey(KeyCode.Q)) {
                Rotate(Vector3.down);
            }
        }
    }
    /* Move the player in the appropriate direction. First initialize newPosition based on direction, then create 
       a HeightProbe to determine the appropriate y value for newPosition. This allows easy vertical movement along both
       even and uneven terrain. HeightProbe destroys itself after FindFloorHeight() is called.    */
    private void Move(Vector3 directionVector) {
        Vector3 newPosition = transform.position + directionVector * unitSize;
        HeightProbe heightProbe = Instantiate(heightProbePrefab, newPosition, Quaternion.identity) as HeightProbe;
        newPosition.y = heightProbe.FindFloorHeight() + playerHeight;
        iTweenArgs["position"] = newPosition; ToggleMovement(false);
        iTween.MoveTo(this.gameObject, iTweenArgs);
    }
    private void Rotate(Vector3 rotationVector) {
        iTweenArgs["amount"] = rotationVector * rotationAmount;
        ToggleMovement(false);
        iTween.RotateBy(this.gameObject, iTweenArgs);
    }
    private void ToggleMovement(bool allowMovement) {
        canMove = allowMovement;
    }
}

 

HeightProbe.cs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using UnityEngine;
using System.Collections;
public class HeightProbe : MonoBehaviour {
    [SerializeField]
    private float destructionDelay = 0.25f;
    [SerializeField] // This should be set to only detect the floor in the future 
    private LayerMask layerMask;
    public float FindFloorHeight() {
        StartCoroutine(SelfDestruct());
        RaycastHit hit;
        Physics.Raycast(transform.position, -transform.up, out hit, Mathf.Infinity, layerMask);
        if (hit.transform) {
            return hit.point.y;
        } else {
            return Mathf.NegativeInfinity;
        }
    }
    private IEnumerator SelfDestruct() {
        yield return new WaitForSeconds(destructionDelay);
        Destroy(gameObject);
    }
}

 

Both of these scripts are super simple and will need some updating, but they give a nice final effect:

czWdd3z.gif
Basically, when the user gives input, I spawn a HeightProbe in the appropriate neighboring space, which simply finds the height of the floor/ground in that location. The PlayerMovementController will then add playerHeight to this value and use that as the y position to move to. The reason I did it this way, rather than having a set step height was because I wanted the potential to have my player move on uneven terrain while maintaining the grid-based movement. This will be particularly useful for outdoor areas and will give me greater freedom in my level design.

Right now there are no checks to see if the player is trying to move through a wall, and I rely on iTween to do all of the heavy lifting in animating my player’s rotation and translations (who wants to manually code that stuff? Not me). Obviously I’ll have to do some checking for movement through walls. Also, based on what I’ve read, iTween is pretty inefficient (I do love working with it though), so I think I’ll have to rework the code to use DoTween instead (also free, but apparently performs way better).

Also, I might get rid of the HeightProbe class altogether and put the logic right inside the PlayerMovementController.

Lastly, I don’t like having my input hardcoded, so that’ll have to change. I’ll also want a bit of a mouselook functionality so the player can observe the environment more fully.

And yes, that was a baby dragon :wink:.

What I did in my next development session was implement a bit of pathfinding. Like I said, I thought about this all day, and I came up with my own algorithm. I have no idea what you would call it technically, but in demonstrations I’ve seen, it performs similarly to a concurrent Dijkstra implementation. e is an enemy, p is the player:

eLQC2m3.gif

hTHDXyv.gif
I’ve never done any pathfinding before (aside from using Unity’s built in AI stuff), so this is a first for me. And I think I did pretty good coming up with a solution completely by myself. I won’t need a ton of pathfinding in the game (since most enemies will probably only move toward the player if they can see him, or move to a last known location), but I thought this would be fun, and it was.

Not to mention I really like watching my code solve a maze :P. There’s something hypnotizing about these gifs.

The Code:

Pathfinder.cs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Pathfinder : MonoBehaviour {
    [SerializeField]
    private Color color = Color.red;
    [SerializeField]
    PathProbe pathProbePrefab;
    [SerializeField]
    private float unitSize = 3f;
    public float UnitSize {
        get {
            return unitSize;
        }
    }
    [SerializeField]
    private LayerMask layerMask;
    [SerializeField]
    private Vector3[] directions;
    public Vector3[] Directions {
        get {
            return directions;
        }
    }
    private List probedCells = new List();
    public List ProbedCells {
        get {
            return probedCells;
        }
    }
    private List pathToTarget = new List();
    public List PathToTarget {
        get {
            return pathToTarget;
        }
        set {
            pathToTarget = value;
            foreach (PathProbe pathProbe in GameObject.FindObjectsOfType()) {
                if (pathProbe.Master == this) {
                    Destroy(pathProbe.gameObject);
                }
            }
        }
    }
    void Start() {
        InitiatePathFinding();
    }
    private void InitiatePathFinding() {
        probedCells.Clear();
        pathToTarget.Clear();
        probedCells.Add(transform.position);
        foreach (Vector3 direction in directions) {
            CreateProbeAtNeighboringCell(transform.position, direction);
        }
    }
    void Update() {
        if (Input.GetKeyDown(KeyCode.F)) {
            InitiatePathFinding();
        }
    }
    public PathProbe CreateProbeAtNeighboringCell(Vector3 position, Vector3 direction) {
        Vector3 cellPosition = position + (direction * unitSize);
        if (!probedCells.Contains(cellPosition)) {
            RaycastHit hit;
            Physics.Raycast(position, direction, out hit, unitSize/*, layerMask*/);
            Debug.DrawRay(position, direction * unitSize, color);
            if (!hit.transform) {
                PathProbe newPathProbe = Instantiate(pathProbePrefab, cellPosition, Quaternion.identity) as PathProbe;
                newPathProbe.Master = this;
                newPathProbe.Color = color;
                probedCells.Add(cellPosition);
                return newPathProbe;
            }
        }
        return null;
    }
}

 

PathProbe.cs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PathProbe : MonoBehaviour {
    private Pathfinder master;
    public Pathfinder Master {
        get {
            return master;
        }
        set {
            master = value;
            StartCoroutine(PathFind());
        }
    }
    private Color color = Color.red;
    public Color Color {
        set {
            color = value;
        }
    }
    private List pathPoints = new List();
    public List PathPoints {
        set {
            pathPoints = value;
            pathPoints.Add(transform.position);
        }
    }
    private List myProbes = new List();
    private IEnumerator PathFind() {
        if (master) {
            yield return new WaitForFixedUpdate();
            if (master.PathToTarget.Count <= 0) {
                foreach (Vector3 direction in master.Directions) {
                    PathProbe newPathProbe = master.CreateProbeAtNeighboringCell(transform.position, direction);
                    myProbes.Add(newPathProbe); if (newPathProbe) {
                        newPathProbe.PathPoints = this.pathPoints;
                    } else {
                        RaycastHit hit; Physics.Raycast(transform.position, direction, out hit, master.UnitSize);
                        //Debug.DrawRay(transform.position, direction * master.UnitSize, Color.green);                       
                        if (hit.transform && hit.transform.tag == "Player") {
                            master.PathToTarget = pathPoints;
                            Debug.Log("Path to player found in " + Time.time + " seconds!");
                            foreach (PathProbe probe in GameObject.FindObjectsOfType()) {
                                Destroy(probe.gameObject);
                            }
                        }
                    }
                }
            }
            Destroy(this.gameObject);
        }
    }
}

 

Basically, I raycast in all four directions from the enemy’s position, at a distance equal to my grid size. If my rays don’t hit anything at those locations, I spawn a PathProbe at the appropriate place and repeat, adding each cell from which rays were cast to a probedCells list, and omitting those cells from future checks. Because each probe performs iterations at the same time as all of the others, the first path to reach the player is always the shortest, so I didn’t even need to take that into consideration, and as soon as any path is found, I can stop the search.

Currently, my coroutine’s yield is no good and it makes the whole process take a relatively long time (waiting for a new frame before performing another iteration). Essentially, only a single set of cells for each probe can be checked per frame, which can become a problem, particularly in long narrow paths. I need to allow a greater number of checks before yielding to speed up the whole process, but I also have to be careful not to overload it or things tend to crash.

Currently, both of the searches you see above take about 0.75 seconds each. Again, this has nothing to do with complexity, and more to do with how my coroutine operates. In fact, having multiple paths calculated at the same time has had zero impact on frame rate or calculation time so far (though I’ve only tested 3 concurrent paths to date).

However, I really need to rework this as .75 seconds is not acceptable. Presumably, to be safe, I’ll have to recalculate the path each time the enemy moves to a new cell, just in case something has blocked the path or the player has moved. But like I said, I don’t think I’ll need a lot of pathfinding. I think most of it will be linear movement along a line of sight.

Again, I might remove my logic from PathProbe and put it right in Pathfinder to avoid Instantiate calls.

I was also considering using Unity’s NavMeshAgent to calculate a path, and then writing some code to normalize that path to align with my grid (I assume Unity’s pathfinding would be more efficient than anything I’ll write). Another approach I’m considering is generating an array based on my level when it loads, and then traversing the array based on whether the given index is walkable or not. This would save on raycasting at least.

Anyhow, that’s it for now!

Stay tuned for more, including the launch of an official website for Fidelum Games!

(+1)

In my LAST POST, I talked mostly about some of the pathfinding options that I came up with. One of these solutions involved relying on raycasting to determine a path to my player, which was a fun exercise and yielded some really entertaining gifs. However, I decided to scrap that system in favor of using Unity’s built-in pathfinding system via the NavMesh and NavMeshAgent components.

However, because my game uses grid-based movement, I wasn’t going to be able to use said system out of the box.

My first solution to making Unity’s pathfinding play nicely with my game was to have the NavMeshAgent generate a path, and then overwrite that path by normalizing each of its points to align with my grid (whose cells are 3x3x4).

This would have been fine, but I soon realized that would have had to account for inserting points along lengthy straight paths, as the NavMeshAgent only calculates the corners, or turning points, along the path.

I could have done this, but after a bit more thought, I realized this would require unnecessarily complex logic, and that I could accomplish the exact same end result with a simpler, but similar solution.

Basically, I just decided that, each time my enemies move, I would have the NavMeshAgent generate a new path. Then, instead of normalizing the entire path, I would just look at the first point in the path and normalize that. Why bother normalizing the whole path if I’m only ever going to be moving to the first point in the path anyway?

After I did this and added a bit of extra logic to account for the locations and movements of other enemies, I was able to successfully have relatively large mobs moving in ways that (more or less) seem to make sense.

Check out this video of some menacing cubes following my player around:


After I got all of that mostly working, I decided that, although the game is still in a super early state, I owed it to myself to add a bit of polish and replace my cubes with one of the assets I acquired.

Check out the difference a couple of textures, 2 models and some animation configuration can make:


So there’s a lot going on in this video, so let me explain.

Firstly, here’s a list of the key features that you can see in the video:

  1. Grid based player movement and turning (thanks to the awesome iTween library for all of my grid movement and rotation animations)
  2. Mouse Look with rotational snapping (this was actually kind of fun to do)
  3. Dissolving enemies (I’m still experimenting with different effects as you can see. Let me know which one you like).

Secondly, here’s an explanation of what you’re seeing in the video:

The game view is on the left. This is what the player sees.

On the right we have a bird’s eye view courtesy of Unity’s Scene View.

Note that the game uses a true turn-based system. Enemies won’t perform an action until the player does. In the video it appears that the enemies sometimes take multiple turns, but I’m actually skipping my turn via keypresses in those cases. I guess I should also mention that if an enemy turns to face a new direction, it ends their turn, but the player can turn as many times as they want for free. I might change this in the future, depending on whether or not this becomes an ‘unfair’ thing to be able to do and tilts the odds too much in the player’s favor.

The blue overlay you see is the walkable area of Unity’s NavMesh. You’ll notice that when an enemy enters an attack state, it will carve out the square that it occupies, making it non-walkable so that other enemies avoid that cell appropriately. I had to do it this way because, although Unity’s NavMeshAgents will avoid one another if they’re in control of movement, they don’t actually take into account other NavMeshAgents when they calculate the path, and since I’m manually moving my enemies, I needed a bit more customization.

You’ll also probably notice that some of the skeleton’s animations are a bit off–the attack in particular. Unfortunately, I couldn’t allow the animations to apply root motion as it interfered with my grid based movement, and as a result, some of the animations are a bit wonky. This was a purchased asset, which I’m still happy with, but if everything goes according to plan, hopefully I’ll be able to spend some money to have the animations updated to align with my grid.

Anyhow–that’s pretty much it for now.

I think my next focus will be on starting my inventory system. Looting, buying and selling are going to be a core gameplay component, so I’m going to have to get it right.

Deleted 6 years ago
(+1)

Thanks :)

Since I made this post, I modified how I handle pathfinding. I still use pretty much the same approach, but, since I'm manually moving my characters along the calculated path, I found that I was having to fight with the NavMeshAgent component attached to each enemy (since they also try to move whatever they're attached to).

Now, I don't even use NavMeshAgents. Instead, I just make a call to  the static function NavMesh.CalculatePath(Vector3 sourcePosition, Vector3 targetPosition, int areaMask, NavMeshPath path);

Deleted 6 years ago

Waaaay too long since my last update.

Since then, I’ve been working (not nearly as much as I should be) on outdoor environments and a skill tree.

I want this game to follow the classic RPG class formula of Mage, Fighter and Thief, but I didn’t want to constrain my players to a single class. Instead, I decided to go with a classless/multiclass concept where players are able to traverse a large skilltree which is implicitly divided into the three aforementioned classes.

Take a look at the prototype:


So this is still an early proof of concept, and all of the visual elements will probably change, but it’s going to function in pretty much the same way as shown here. You’ll also get a (very) small taste of the kind of skills you might see in the game. One more note: the three skill branches never merge in this example, but I think they will in the final version. Also, all parent nodes of a skill must currently be unlocked before unlocking a given child node. I’m not sure if this will persists, or if I’ll remove that constraint to give me freedom of traversal.

Other than that, I’ve been spending a bit of time building some outdoor environments to try to nail down what my worlds will look like.

This first screenshot is, quite honestly, pretty bland and generic, but it will at least give a sense of how villages will be laid out in the world:

2ceo2m6m5o2n039.PNG

After I made this scene, I procured a license for Gaia–a really powerful and full featured terrain generation tool for Unity.

Here’s what 15 minutes of work with Gaia looks like:
4comfmon1dc6735.PNG

9cobmm5on92d8d7.PNG

4c0o5mfmdo2nf70.PNG

1cboem6m9o9n4c0.PNG

Pretty amazing huh?

So in the end, I think I’ll be using Gaia to build my world, and then I’ll refine the terrain manually and tweak the positioning of settlements and other points of interest to best suit the game’s story and gameplay.

That’s it for me.

Stay tuned for an update on NPCs and monsters!

Official Site and 'The Wayfarer' in a Nutshell

I’ve been working on my first large project for quite some time now, and if I have any hopes of having it be successful, I figured I’d need an official site.

You can find it HERE. Just a simple wordpress thing for now. Maybe something fancier as the project matures.

As I continue to add development blogs, I’ll be continuing to post the content over on sites like GameDev.net and IndieDB.com, along with any other locations that I think will help get a bit of exposure. If there are any you’re aware of, feel free to leave a comment and share it!

As for what ‘The Wayfarer’ is, let me give a bit of an overview:

The Wayfarer is the tentative title of my current project.

In a nutshell, it’s an open world quest driven dungeon crawler with a strong focus on storytelling, lore, exploration and looting.

Imagine Legend of Grimrock meets The Elder Scrolls II: Daggerfall.

I’m developing in Unity and deploying primarily on desktop platforms, with plans for mobile as a secondary platform (this will involve a graphical overhaul if it happens).

I’ve got big plans for this one.

Stay tuned for more!

A CLEAN SLATE

Originally posted on FidelumGames.wordpress.com

Since my last post, I let myself get a bit out of hand as far as staying disciplined goes.

I had made some decent progress, and had some cool things to show off, but most of what I was showing was only superficial progress. The things I’m talking about are environments, enemies (actual animated models, not just cubes) and some UI stuff.

The problem with these things is that they were all parts of incomplete systems.

In one of my earlier posts, I wrote:

“…I decided that, although the game is still in a super early state, I owed it to myself to add a bit of polish and replace my cubes with one of the assets I acquired.”

This was a mistake, and led to me falling back into my old habits of sitting down to a development session and asking myself, “what do I want to work on today? What would be cool?”

The result of this workflow was getting a given feature ‘good enough’, making it look cool, and then moving on to something else with the intention of returning to the feature I had just ‘completed’ in order to finalize and polish it.

The problem with this was that I would often go too long before returning to that feature (if I did at all), and forget the mental model required to finish the system properly. I basically wound up with a bunch of fragments that didn’t fit together.

This quickly became overwhelming and really sucked my motivation away.

What I really owe myself is to not add any polish until the game is ready for it.

Luckily, things have been slow at work lately (until today), and so I’ve been left mostly to my own devices. Without any project work to complete, they let me work on pretty much whatever (as long as it’s somewhat related to what we do there), and since Unity is part of the skill set I use on a regular basis at work, I was able to justify working on my own game in order to increase my proficiency with Unity.

God how I wish that was the norm. Working all day long on something I love really makes the time fly.

Some day.

Anyhow, with all of this time to work on The Wayfarer, I decided it was the perfect time to throw away everything I’d done so far and start over, with a new mentality. This might seem like a bit of a waste, but I’ll be able to reuse some of what I’ve done, and consider the original work as a prototype.

The most important thing I’ve been doing is forcing myself to plan everything (except for the smallest tasks) before I even open Unity.

This prevents me from sitting down and asking that awful question “what do I want to work on today? What would be cool?”. Instead, I ask myself, “where did I leave off? What needs to be done today?”

My new workflow goes something like this:

Look at my task list (something I never had before, but to which I adhere strictly to now) and see where I left off. If a task is in progress, pick up where I left of. If not, move on to the next item, adding to the task list as required.

These tasks break down essentially into two categories: planning/design and implementation/development, and both groups take up about the same amount of time.

Before I write a single line of code, I establish my algorithms in my GDD in plain English (which feels strangely similar to coding).

Then, I draw an activity diagram based on the algorithm, identifying any logic flaws along the way and revising the algorithm as required.

Finally, after all of that is done, I move on to actual coding–simply translating the algorithm and diagram to code.

All of this might seem like overkill (and it does feel like a pain in the ass sometimes), but it’s all worth it in the end, and makes writing the code so much easier. Not only that, but my code is cleaner, more robust and more easily expanded upon.

Way fewer headaches now.

For those of you interested, here’s one of the plain English pseudo-code examples taken right from my GDD, and the corresponding activity diagram (these are for enemy AI):

Enemies will have the ability to make the following decisions:


  • Patrol
  • Wander
  • Pursue
  • Retreat
  • Engage
    • Melee
    • Ranged
    • Magic
There are 3 base states which an enemy can be in, which will determine available decisions:


  • Unalerted
  • Alerted
  • Injured
If an enemy has not seen or been attacked by the player, it will be in an unalerted state and will always either Patrol or Wander, unless it has seen or been attacked by the player within x turns.
Patrolling will always occur if patrol points exist for the enemy, otherwise it will wander.
If the enemy has seen or been attacked by the player within x turns, it will be in an alerted state.
In the alerted state, regardless of whether the enemy can currently see the player, it will always ‘know’ the player’s position, unless x turns pass without it seeing the player, in which case it will return to an unalerted state and continue to either patrol or wander.
While in the alerted state, the enemy will first check if its health has dropped below the injury threshold. If it has, it will randomly decide whether to heal (if available), continue engaging, or transition to the injured state.
If the enemy is still engaging, it will check if it is within a certain range of the player (a range it will consider to be dangerously close to the player). If it is and it has any available defensive buff spells whose effects are not currently active, it will perform a random check as to whether it should cast the buff or perform another action.
If it decides to perform another action, it will check if it is facing the player and if it has a clear line of sight within a range of y, where y is the longest attack range of any of its usable (has enough mana) attacks or abilities.
If this case is met, but the distance between the player and enemy is less than y, the enemy will make a random decision to either move backward to increase distance (up to, but not beyond y), or to attack.
If the distance between the player and enemy is equal to y, the enemy will always attack.
If the distance between the player and enemy is greater than y, but the enemy has seen or been attacked by the player within x turns, the enemy will attempt to move closer to the player.
While moving along the calculated path to the player, the enemy will always favor movement over turning, if available. It will do this by first favoring forward movement.
To favor forward movement, the enemy will calculate a new path from the cell in front of it to the player. If this path is shorter, it will move forward. If this path is longer, or the same distance, it will follow the original path.
Enemies may have an option for sidestepping. They will always favor this strafing over turning if it has been enabled for a given enemy.
This process will continue until either x turns have passed without it being attacked or seeing the player, in which case it will return to an unalerted state, or until it is within range of the player again and can attack.
While in the injured state, the enemy will check if it is dangerously close to the player. If so, it will make a random decision to flee, or heal (if available). The enemy will remain in the injured state for at least x turns (unless it has healed itself beyond the injury threshold), but not more than y turns.
If it is not within a dangerously close range, the enemy will always heal if available. Otherwise, it will move away from the player.
When leaving the injured state, if it has seen or been attacked by the player within x turns, it will return to the alerted state—otherwise, it will return to the unalerted state.

AlertedInjuredUnalerted

I have to say that with all of the practice I’ve gotten in lately, and my new workflows, I feel like I’ve just come out of a learning plateau, and am reaching a new skill level with programming and game development.

I’VE CREATED A MONSTER

Originally posted on FidelumGames.wordpress.com

I’ve been spending nearly all of my recent development time working on my enemies.

This and the following two sections will deal with the details of that.

The first thing I did was rework my enemy AI, again with my cubes.

I feel like my new system is much more robust, as I’m able to get a wide variety of behaviors just by modifying a few values in Unity’s inspector.

I’m able to make my enemies favor ranged combat or close quarters (or any combination of the two), physical or magical attacks, determine how often they’ll heal themselves, and how likely they are to cast buffs on themselves during or in preparation for battle. I’m also able to dictate how aggressive they are by setting the chance that they’ll become injured and retreat during battle, and for how long they’ll pursue the player. I’m also able to dictate how well they can see. All of this without ever (hopefully) having to touch the AI code again (except for bug fixes).

This system relies on a simple state machine in which the enemy can be Alerted, Unalerted or Injured. In each of these states, the AI will choose how to behave based on their preference for a particular behavior.

You can see more about this system in the pseudo-code and UML shown in the above section.

I’ll show a short video of the AI in action in the next section, but for now, have a look at the variables exposed to the inspector which determine an AI’s behavior:

AI

WORKING MY MAGIC

My goal with my magic system is to allow myself to make everything as generic as possible so that I can easily create new spells without writing additional code, by easily adding status effects to spells, being able to reuse the same visual effects for different spells, setting whether the spell is a projectile or has an immediate effect, or combining/linking any number of spells or visual effects.

The system itself is pretty difficult to explain. Suffice to say I use ScriptableObjects, prefabs and Animation Events, and can just work within the Unity Editor to make new spells. Also, I can just drag spells into an enemy’s spell list to give them the ability to cast them.

The system itself is pretty much done (with the exception of making status effects actually dosomething), but I’ve yet to put any legitimate visual effects in. Just differently colored spheres for now.

Here’s a short video showing how customizable I’ve made spells (I have hopes of letting the player create spells while playing as well):


One thing I would like to point out that I think is kind of cool is the ‘Blood’ Magick type. This type of spell costs health instead of (or in addition to) mana to be able to cast. I see these spells being used heavily by warrior type players who have a lot of health to spare, but maybe don’t have enough mana to be proficient spellcasters.

And, here’s a video of my enemy displaying how it behaves, and how changes in its values modify its behavior.

Note that the different balls are placeholder for different spells, and the green thing is a placeholder for a physical projectile, like an arrow.

Don’t mind the bugs.


PREPARING FOR THE FUTURE

Along with all of this planning and trying to ‘do things right’ (if there is such a thing), I’ve been working on getting all of my stats set up, and having them actually be meaningful.

The need for this came out of creating the status effect portion of my spell system, which needed stats to be defined (or at least a shell of them) in order to work.

I’ve broken my stats down into three categories:

  • Primary/Governing stats: These determine all secondary base stats, and base proficiencies with tertiary stats. Very D&D-ish.
  • Secondary stats: Anything directly tied to primary stats. Health, Mana, Carrying Capacity, etc.
  • Tertiary/Skill Stats
    • Weapons & Armor (Dual wield, Ranged Weapons, Heavy Armor, etc.)
    • Magick (Proficiency in different types of Magick)
    • Other (Things like lockpicking, etc. If I decide to put them in the game)

The Player, enemies and NPCs all have a common set of stats, and then, of course, some that only apply to a certain character type exist only where necessary.

Nothing overly exciting here, except that I created my first custom inspector in order to make modifying stats easier.

Here’s a before and after:

Stats

This inspector lets me modify governing stats and see how it affects everything else. It also allows me to easily modify all stats and quickly restore a character’s health or mana at run time. Hopefully this saves me some time in the future.

That’s it for me. Stay tuned for more!

PS: We’ve got a new team member, but I’ll wait for him to introduce himself!


(3 edits)

GREETINGS FROM THE COMPOSER!

A few months back I was looking for projects that would be in need of a composer. Jake did contact me via GameDev.net and asked if I’d be interested doing musics to his game and since I’ve always been a huge fan of fantasy RPGs decision wasn’t really that hard to make, even though there was quite a lot going on at that time (I was offered six game music projects at that time, I had quite recently started in a new job ect.). Style of the game and the musics just seemed right for my style.

Okay. Then who actually I am?

My name is Mika Pilke. A Finnish hobbyist musician who has been playing around with music for about 20 years now. I’ve been writing music for years, but just lately I’ve felt that my material and quality of the mix have archieved the level where it is possible to actually consider accepting composing projects. I don’t really know how many songs I’ve written totally, but total number is probably somewhere between 150-200. I have also played in several bands too (mostly as a lead guitarist and/or as a singer), but I guess I never truly found comfort in playing live which is a chaotic moment where your senses are dampened and you can barely hear anything, let alone the small details (which I do find important). I’ve always felt that making music all alone, at night, in a dark room is what I actually love the most. It’s intensity, 100% focus and the flow.

XBLOG01E

Tools

Nowadays (and at this level) the magic happens mostly by using virtual instruments. I use Reaper as a DAW, a midi-keyboard (Axiom61) and various VST/VSTi/VST3/VST3i instruments from various companies (like Native Instruments, Steinberg and Spitfire Audio).
But sometimes it also might add some extra punch to actually record something from the real world too, so I also have Shure Beta 58A, Rode NT1-A and Zoom H1 for recording sound. M-Audio Fast Track Pro serves mostly as an audio interface (and Behringer U-Phoria UM2 as for backup, or for recording sessions that are located elsewhere and you’re too lazy to unconnect M-Audio from the computer). In the end it’s quite a simple, but somewhat capable setup. And still somewhat cost effective too, even though software is not cheap.

XBOLG02

What is the meaning of music?

Music and soundscapes are easily undervalued and even forgotten elements, yet they have (mostly passively) a strong impact to viewers/gamers emotions. I believe music is actually one of the key elements that will define the game’s identity and it has a strong purpose in creating memorable moments and atmospheres. I would even go as far to say that all the visual content is the body but music makes the very soul of the game.
When these two elements are combined, sometimes there is a change to create something truly unforgettable. And of course sometimes a good storyline helps too ect. 
But after all, how many games that have become a legend, has a bad soundtrack (if there are any, that is)?

So there are quite a lot reasons to take music writing seriously. It’s a job that comes with a great responsibility and it’s a matter I wish to handle with a proper care and passion.

One of my creations for The Wayfarer:

BR

BR

Mika Pilke

PS. Check out Mika's YouTube channel!

(1 edit)

TASK LIST, UPCOMING MILESTONE

Originally posted by Jake Jollimore on FidelumGames.WordPress.com on September 11, 2017

I’ve been pretty busy over the last week with life stuff, so not a whole lot to report on at the moment.

However, I watched an Extra Credits video last night that talked about some tips for making your first game. This isn’t my first, but there were still some good tips in there.

The biggest takeaway from this video for me was to make sure that, even if you don’t have the time to work on your game, spend at least 30 minutes a week looking at and reviewing it. The point of this is to keep it all fresh in your mind, and not to let the mental model you’ve created of it to atrophy too far. If you’re a game developer, or even just an avid gamer, I really recommend you check out Extra Credits on YouTube. The videos are always entertaining and educational.

Anyway–this video got me thinking about the task list I mentioned in an earlier post, and I thought it might be kind of cool for some of you to see it.

Note that this list is not static by any means. Items get added, removed and shuffled around all the time.

I’ll start with a high-level task (like Spells), and then break that down into smaller tasks. Often time, I’ll get part way through and realize that, in order to finish the current task, I have to add another to the list and shift my focus to that (eg. I needed a base Stats implementation to implement spells), and then resume with the original task.

I’m really glad I have this list. Juggling all of the interconnected systems and moving back forth between them would be a major headache without it. This lets me keep my mental RAM free for more important tasks.

It’s not formatted as nicely as the Word version, but you should still be able to get an idea of what I’ve finished, what I’m doing, and what I’ll be doing next.

TaskStatus
1.       Define and Implement Core Gameplay Mechanics (Alpha)In Progress
1.1.    Movement (Base Mechanics Only—Polish to come later)Complete
1.1.1.Define Movement SchemeComplete
1.1.1.1.              Moving (Translation)Complete
1.1.1.1.1.                    Define RestrictionsComplete
1.1.1.1.1.1.   Non-Walkable AreasComplete
1.1.1.1.1.1.1.         WallsComplete
1.1.1.1.1.1.2.         HolesComplete
1.1.1.1.1.1.3.         Non-Passable Terrain (Water, Marsh, etc.)Complete
1.1.1.1.1.1.4.         Max Climbing AngleComplete
1.1.1.1.1.1.5.         Max Drop AmountComplete
1.1.1.2.              Turning and Looking (Rotation)Complete
1.1.1.2.1.                    Fixed rotation (Key presses)Complete
1.1.1.2.2.                    Free Look (mouse)Complete
1.1.2.Implement Movement SchemeComplete
1.1.2.1.              Player MovementComplete
1.1.2.1.1.                    Develop test level with walls, holes, stairs, dropsComplete
1.1.2.1.2.                    Develop test level with terrainComplete
1.1.2.1.3.                    Turning and Looking (Rotation)Complete
1.1.2.1.4.                    Moving (Translation)Complete
1.2.    Turn-based PlayIn Progress
1.2.1.Wait for player action (Mode 1)Complete
1.2.1.1.              Define how the Speed stat affects turnsComplete
1.2.1.2.              Define TurnManager (Passive vs. Active Mode)Complete
1.2.1.3.              Define Enemy AIComplete
1.2.1.3.1.                    Determining ActionsComplete
1.2.1.3.1.1.   MovementComplete
1.2.1.3.1.2.   AttackingComplete
1.2.1.3.1.2.1.         MeleeComplete
1.2.1.3.1.2.2.         RangedComplete
1.2.1.3.1.2.3.         MagicComplete
1.2.1.3.1.3.   RetreatingComplete
1.2.1.3.1.4.   PursuitComplete
1.2.1.3.1.5.   PatrollingComplete
1.2.1.4.              Implement Enemy AIComplete
1.2.1.4.1.1.   MovementComplete
1.2.1.4.1.1.1.         Avoiding Other NPCsComplete
1.2.1.4.1.1.2.         PursuitComplete
1.2.1.4.1.1.3.         PatrollingComplete
1.2.1.4.1.2.   AttackingComplete
1.2.1.4.1.2.1.         MeleeComplete
1.2.1.4.1.2.2.         RangedComplete
1.2.1.4.1.2.2.1.               Ranged Melee (Spears, etc.)Complete
1.2.1.4.1.2.2.2.               ProjectilesComplete
1.2.1.4.1.2.3.         MagicIn Progress
1.2.1.4.1.2.3.1.               Define Spell SystemComplete
1.2.1.4.1.2.3.1.1.                      Define Stats and Prepare for implementation (equations, helper functions)Complete
1.2.1.4.1.2.3.1.2.                      Implement StatsComplete
1.2.1.4.1.2.3.1.3.                      Custom Stats InspectorsComplete
1.2.1.4.1.2.3.2.               Implement Spell System (Enemy)In Progress
1.2.1.4.1.2.3.2.1.                      Linked SpellsIn Progress
1.2.1.4.1.2.3.2.2.                      Document SpellcastingIn progress
1.2.1.4.1.2.3.2.3.                      Revamp Spell SystemIn Progress
1.2.1.4.1.2.3.2.4.                      A couple of finished sample spellsIn Progress
1.2.1.4.1.2.3.2.5.                      Define potential status effects. Not Started
1.2.1.4.1.2.3.2.6.                      Implement base status effectsNot Started
1.2.1.4.1.3.   RetreatingComplete
1.3.    Combat (Base) Not Started
1.3.1. Attacking (Player) Not Started
1.3.2.Melee Not Started
1.3.2.1.              Create Placeholder Weapon Not Started
1.3.2.1.1.                    Attack Animations Not Started
1.3.2.1.2.                    Damage Enemy Not Started
1.3.2.1.3.                    Ranged Not Started
1.3.3.Ranged Not Started
1.3.3.1.              Create Placeholder Weapon Not Started
1.3.3.1.1.                    Define how moving projectiles affect turns Not Started
1.3.3.1.2.                    Projectile Animation Not Started
1.3.3.1.3.                    Magic Not Started
1.3.3.2.              Casting Animation Not Started
1.3.3.2.1.                    Implement Not Started
1.3.3.2.2.                    Dual Wield?On Hold
1.3.3.3.              Define how the player will use dual wield (Attack both at once, choose which hand, etc.)On Hold
1.3.3.3.1.                    Items Not Started
1.4.    Define item types (Consumable, Weapon, Armor, Quest, etc.) Not Started
1.4.1.Define item script heirarchy Not Started
1.4.2.Determine item commonalites and differences Not Started
1.4.2.1.              Create item heirarchy Not Started
1.4.2.2.              Weapons Not Started
1.4.2.3.              Create Weapon Scriptable Object Not Started
1.4.2.3.1.                    Make Weapons equippable (through editor) Not Started
1.4.2.3.2.                    Share common animation based on type Not Started
1.4.2.3.2.1.   Practice with Infinity Weapons Not Started
1.4.2.3.3.                    Practice with Mesh Effects Not Started
1.4.2.3.4.                    Integrate Infinity Weapons and Mesh Effects Not Started
1.4.2.3.5.                    Procedural Weapons Not Started
1.4.2.3.5.1.   Experiment with Infinity Weapons texture generation and Blend Shapes at Runtime Not Started

Side note: looking at this list now, it’s starting to get pretty long. I might need to make some separate sublists.

As you can see, I’m currently working on implementing the spell system for the enemies.

I’ve been at this task for a while. It was nearly done, but I realized it was needlessly convoluted when I had to keep re-learning how to use it to create new spells. So now I’m reworking it a bit, and so far so good.

Once the spell system task is complete, I’ll be able to move on to what I consider to be a major milestone: making the player do stuff.

Currently, all he can do is move and take damage. After the spells, I’ll work on making him be able to attack back.

Speaking of milestones: I really need to define some formally.

Anyhow, I’m excited to get over this spell-casting hump and to start turning all of this functionality I’ve created into an actual game.

As soon as the player is able to start attacking back, the need for new systems is going to skyrocket. We’re talking weapons, armor, items, inventory and all of the little pieces that make them all up.

I’m realizing now that this next task is going to be a huge one, but I’m suddenly super excited to get to that point. As soon as I finish spellcasting, and before I start working on the player, I’m going to make sure all of my code is painstakingly commented. This will be a turning point in the project, and I have to execute it well.

Cheers!

-Jake

NEW MUSIC AND A TEMPORARY SETBACK

Originally posted by Mika Pilke on FidelumGames.WordPress.com on September 19, 2017

Here is another piece that was done for The Wayfarer!


Last week was a chaotic one. My PC crashed so badly there was really no other option but to reinstall operating system and everything else again. That was a small disaster. Basicly I spent all of my spare time for 8 days to revive my setup.

“Luckily” I did this same operation about an year ago, so I got most of the bigger installing files already there. Still there was quite a lot to do. Not only that you install all the programs, but then you update everything, upload the registeration managers, look for the serials, registerate, find out (again) that you have multiple accounts (at the same site) which cannot be merged (and that there are email addresses that don’t even exist anymore) ect. It takes time to relocate all the passwords for those over 10 different accounts. There was probably over 60-70 different products. Luckily only that much. It could be a lot worse.

After you’ve installed and updated everything, you still need to find folders of all the dll-files so VST instruments and effects start showing and working in you DAW. Then open up the DAW, open up the instruments one at the time and look for the libraries so that instrument have something to play ect. ect. It’s quite a mess.

To be honest I really, really would not care to do this again. It’s really time and nerve consuming. But now it’s done and I’m back in business and nothing crucial is missing. That’s life. Things happen. Then you clean up the mess and move forward. wink

PS. The cause of this was actually drivers of my audio interface (it could be concluded from the file name showing at the blue screen). Fast Track Pro does not support Windows 10, but since it did work after the update from Win7->Win10, I did not quit using it. Now that interface does and will not touch my PC. It is a good interface and I have been using it for years, but I really don’t recommend using it if you use Windows 10.

BR

Mika Pilke