Refining player movement

So now that my changes to the background tiles went through, the next thing I want to work on is to add some animation to the player movement.  There are a couple things I need to change in order to make it work. First, I needed to make some more sprites for the animation. I’m still not an artist so am utilizing programmer art once again and the animations are a animated arrows pointing in the direction of movement.

player_animations

Second,I need to smooth out the movement. Right now players basically teleport from one square to another. So I need to change from editing the position to using the translate method.

The reason I did not originally use translate was the code ensuring the sprite stopped at the point I wanted was more complex. But I felt like now was a better time to try and tackle it. So here is my new move function.

 


 protected IEnumerator SmoothMovement(Vector3 destination)
{
while(Vector3.Distance(transform.position, destination) > 0)
{
transform.Translate((destination - transform.position) * Speed * Time.deltaTime);
if (Vector3.Distance(transform.position, destination) < 0.01)
Move(destination - transform.position);
yield return null;
}

EnablePlayerInput = true; // Input was disabled when input was collected
}

As evident by the IEnumerator type, The new movement function is what Unity calls a Coroutine. It works by moving a small distance to each frame and fixes itself to the correct location when the distance is less than 0.01. I don’t know if I really like the last part, but for now it is working well enough.animated

Lastly I added the new sprites and animation clips into. Here is the sprite at rest on the left and a move right animation on the right.

 

Getting fancy with tiles

So far I have drawn the background using sprites that were set as public variables. It was convenient for getting things to work fast. However there are things that I don’t like about it.

Managing the sprites manually in Unity sounds really tedious to me with all the clicking and dragging. Furthermore, I’m not working with final assets right now so I expect my tileset to change. So I feel an incentive to  write code that does the boring part for me.

In fact, I want to minimize the work of adding new tiles as much as possible. Its with that desire in mind that I came up with my new scheme for handling the tilesmaps. It works like this:

  1. I created a new class called TerrainData. This new class only holds 3 bits of data: An identifier, the sprites index on the spritesheet, and if it collides with the player (example being water)
  2. In the Tilemap Manager I added a dictionary of TerrainData and filled the dictionary from a JSON file with all my data on my sprites.
  3. From the dictionary I created another collection of Tiles with all the correct sprites and if any of my tilemaps need a tile they can easily pull a reference to it.

Overall, I got all of that working and I’m pretty satisfied with how its going. I’m fully anticipating some unanticipated problems to crop from it that I need to fix. Also spent a good hour on a bug where everything compiled fine but on closer inspection the problem was hiding in plain sight. It’s in the section below.


public void AddPrototype(string key, TerrainTile tt)
{
if (prototypes.ContainsKey(key) == false)
{
prototypes.Add("key", tt);
}
else
{
Debug.Log("Invalid Prototype");
//throw new ArgumentException();
}
}

 

Working with tiles and managing players

So with basic collision detection added, I started looking at a couple things that involved much more C# scripting than anything I did on the project previously. Anyways here is the latest.

2018-07-12_2048

So what’s different? Well 3 things.

I wanted more tiles on the screen, so I zoomed out. It was fairly simple, just one setting on the camera.

Next, while I found being able to paint tiles onto the screen directly in Unity to be convenient; I wanted to have a little more control over the tiles on the screen. For that I spent time figuring out how to add tiles through scripts. Or, more accurately, straining my eyes on the documentation and banging my head against my desk while missing the completely obvious answers to questions I had. Questions like, “how does one create a tile on the tilemap, if a tile is a necessary parameter?” The answer is, of course, you just create the tile separately and then fix it to the location you want in the tilemap.

So with that figured out, I replaced the old terrain with a 32 by 16 square of grass. All the terrain was created by a script. The code wasn’t pretty and I’ll be revisiting it later to make it better, but instead moved onto the third task.

Previously, my keyboard input directed the object on the screen called player to move it around. However I’m not going to only be controlling that one single player. Like any good rpg game, I want to give keyboard input to other characters. So I added a new class that had a list for all potential characters where I can get references of whichever of them is currently getting user input. To test it, I promoted the npc to Player2 and added a switch player button on the top left to toggle change the active player. It ended up being good practice working with Unity game objects.

Generalizing movement

While the lack of collision detection is bugging me, I need to tackle one other matter first. My code for moving the player currently looks like this:


public class PlayerController : MonoBehaviour {

void Update () {
if (Input.GetKeyDown("right"))
transform.position += new Vector3(1, 0, 0);
else if (Input.GetKeyDown("left"))
transform.position += new Vector3(-1, 0, 0);
else if (Input.GetKeyDown("up"))
transform.position += new Vector3(0, 1, 0);
else if(Input.GetKeyDown("down"))
transform.position += new Vector3(0, -1, 0);
}
}

Depending on whichever arrow key is pressed, my player will move one unit in that direction. The problem is, instructions how to move is all written directly into the player’s script. It isn’t a big deal right now because its just a transform.position statement(one line of code), but I’m going to be adding stuff to check for collisions before movement and there is nothing really unique about how the player moves compared to anything else. At best its pointless to have the same bits of code in multiple spots and at worst it will become confusing and tedious to make any change to movement because I would need to make the change in more places than one.

So I’d rather have one function for movement to use for multiple different things.  In that case, how will I know that it works?

2018-07-10_1012

I redid the scenario from last time. I added an npc to the bottom right. I’m going to have him move around once every hundred or so frames. Then I’ll have the player move with the keyboard. If both move as expected, then the code does what I want it to do.

In my Java prototype I did that by making a parent class called Entity where the move function existed and was available for anything that needed to move. The solution here is essentially the same.


public abstract class Entity : MonoBehaviour {
protected void Move(Vector3 movement)
{
transform.position += movement;
}
}

Having the Entity class as an abstract class was advantageous in my Java prototype, so even though the one here doesn’t need to be abstract to work, I still went ahead and made it one. The code is not going to know (or care) that the movement is originally from keyboard inputs, so I’m just asking for the direction of movement.

Then all I need to do is change the class for Player to inherit from Entity, and make it use the new Move function. I decided to go one step farther and move all the Keyboard stuff onto a separate function which is called from update.

<blockquote>void KeyboardInput()
{
if (Input.GetKeyDown("up"))
Move(new Vector3(0, 1, 0));
else if (Input.GetKeyDown("down"))
Move(new Vector3(0, -1, 0));
else if (Input.GetKeyDown("left"))
Move(new Vector3(-1, 0, 0));
else if (Input.GetKeyDown("right"))
Move(new Vector3(1, 0, 0));
}</blockquote>

Lastly, I saved everything and hit the play button. The npc is running around in circles as expected, and my player moves around according to my commands.

Somewhere to get started

So after procrastinating for just under weeks, I finally started the process reconstructing my java game using Unity. My basic goal was to place some ground level terrain and add an object representing a person to move around the background. Here is what I came up with: A basic scenario with a person, a rock and some varying terrain. (Note: as with the Java one, these are without a doubt placeholder graphics.)

2018-07-09_2032

Early on, I came across tile maps and palettes so the ground layout was easier than I expected. I ended up wasting more time trying to get collisions to work before I realized that two kinematic objects don’t really collide with one another. Good lesson to learn.

My time as a hobbyist game dev… so far

The main difficulty I’ve had when learning programming is after a point, it’s hard to find projects to practice programming skills. After a while, coming up with simple application ideas like coin sorting programs becomes boring and unchallenging even when you add fancy GUI components.

I’m a fan of RPG style games. In particular turn based JRPG games like the ones I played in my younger days on the snes. So naturally, I picked A JRPG as a project I where I could both practice coding and challenge myself. I named the project the Weekend RPG. So I buckled down to see how far I could get. For anyone who is interested, I used java with netbeans on a mac. The only non-standard library I used was Gson to make working with json a bit easier. I created all the assets myself and made no effort whatsoever to make them look nice. I only cared they looked like what they represent.

JRPG prototype in Java

As evident in the screenshot, the results are crude. It’s also doesn’t satisfy the label: “game” since it’s missing a way to progress and win/lose. However, it runs. It takes user input to move around and you can chat with the 3 npcs. There is logic associated with moving. You can’t stand on an NPC, or walk on water (blue tiles). As a first effort I’m happy with it.

It was also a good learning experience. When I first started it, I didn’t realize how cluttered my code would end up. Changing pretty much anything would difficult and I found it extremely useful to generalize my code through abstract classes and inheritance rather than duplicating implementation of common tasks. Lastly I came to accept that I’m likely doing a lot of things in a horribly inefficient way. As an example of that, the tile layout is stored as an external json file, and I found that reading the file and unpacking them as objects gets really slow on larger maps.

I’m confident that I can expand this prototype further with some more work. However, I’m not going to. At least not this java project. Coming up with my own implementations of common tasks like displaying sprites on a screen is going to consume a lot of time for little gain. Instead I’m going to switch to C# and use the Unity engine.

So why did I choose Unity.

  • It is free (at least it is for educational purposes)
  • It is used commercially by big name development studios
  • It doesn’t do all the work for me. Despite offloading a lot of the background tasks, it will still provide a challenge.

So my first task is to replicate my java prototype on unity. Exciting. Lets see how it goes.