Month: November 2015

Building a world!

titlePicture2

An ongoing process throughout this project has been to create a world in which our character will explore and exist in. From early stages in development we decided that there will be one large hub filled with a town, various points of interest and treasure. Also, within this hub there will be entrances spread around the map which will teleport our protagonist into randomly generated caverns or dungeons. These entrances are depicted as cave entrances in mountain sides or holes in the ground which our character can climb down. Other types of entrances might be implemented later depending on how the map develops.

So this task was given to me, and ever since we started on this project, I have worked on this every now and then when inspiration strikes. Luckily I am given this freedom on this portion of the project because it isn’t as strongly tied to what everyone else is doing, unlike my other major task, creating our player character. This is due to the fact that everyone has their own test scene. So the majority of the logic based testing and game balance is done in the developers test scene, rather than in the main world where the game will primarily take place.

So how is our world created? I’m glad you asked!

We took some time deciding how this world would be created. Our first attempt at getting started was to use a program called Tiled Map Editor. This is a program designed specifically for making 2D maps for games. To import the maps into Unity we were going to use a plugin called Tiled 2 Unity, which imports maps made in Tiled Map Editor, to Unity. As the name suggests.

Tiled Map Editor: http://www.mapeditor.org/
Tiled 2 Unity: http://www.seanba.com/tiled2unity

At first this method worked great. Tiled Map Editor is an amazing tool and makes map editing very easy and the maps you create look great with minimal effort. Importing to Unity using the plugin was also easy and painless. The problems started when we tried to share our maps with each other over git. When another group member tried viewing the map which was created and imported to Unity and then sent over git, pieces of the map and textures were missing and it just looked terrible. After researching the problem and finding no solution, or solutions which didn’t fix the issue for us. We decided that we may in fact have to use the standard map editing tools in Unity.

The map editing tools in Unity are in fact quite powerful, if you are working with 3D games, which we are not. Unity is known for being quite terrible for working with 2D maps and it feels like all the tools available were implemented by the Unity team as an afterthought. This may be directly linked to the fact that Unity is in fact called “Unity 3D”. But I powered through and eventually got used to using it, and when I got used to it, it wasn’t so painful to work with.

Moving on to how I actually created a map, or world, if you will.

So we first got lots of sprite sheets from the Open Game Art website. These sprite sheets are free for everyone to use, as long as we give the correct recognition. We decided to try and stick to the sprites created for The Liberated Pixel Cup (LPC) since they all had the same art style and worked well together.

Most of the sprite sheets were created so you could slice them up into 32 by 32 pixel squares. Once that was done it was simply a matter of placing the squares which matched next to each other to create what you wanted. If you look at the picture below you can see that it has been cut into squares (32×32 pixels). This sheet is the sheet I used to create some of the paths in our game. The sheet is set up nicely so you have everything you require to make whatever size dirt path or area you wish.

spriteSheet

The sprite editor shown above is the Unity tool for cutting up sprite sheets, and is quick and painless to use. The painful part starts when you have to start positioning them and lining them up besides each other. Unity has a pivot for the sprites, as you can see on the picture above, the pivot is set to the center on this sprite. The pivot is used when you want to snap the sprites together (line up the sprites pixel perfect). This makes it much easier to align sprites and make everything pixel perfect. This sounds amazing in theory, but in practice it wasn’t as easy to use. Each individual sprites needs to be given its own pivot position, and even when clicking apply, the pivot position didn’t always apply. A lot of the time I just relied on zooming in really far and manually placing the sprites so they aligned.

When I have created a collection of sprites which depict something, which I hope looks reasonable. I save it as a prefab in our project. A prefab is basically a finished product which we want to use in our game. A good example of a prefab would be a tree. The idea is that, if we have one hundred trees in this world I have want to create, instead of me making one hundred separate trees, with an ordering layer, and its own box collider. I can instead make one tree, save it as a prefab, and then I can basically click and drag it into our world to add it. Every tree of this type will then have its own ordering layer and box collider so I don’t have to set it one hundred times. Instead, just to add some variation, I can change the scale of each tree, so each tree looks independent from each other and creates a more dynamic world.

treeList

So coming back to creating a world as a whole. The main idea with the world is to give the player a playground to explore in. We decided early on that our world will have a main town where the player can interact with other non-player controlled characters (NPCs), to learn about the world and perhaps buy and sell items. From the town there would be paths leading north, east, south and west which the player can follow to be guided to various points of interest. Out in the world the player will encounter entrances which will teleport the player into randomly generated dungeons filled to the brim with enemies and wonderful loot (If we have time to implement items). This is where the main gameplay will take place and the player will be forced to fight for their lives.

cavernEntrance

As of right now while I’m writing this, our world has a basic layout. There is a town in the middle, a mountainous area off to the west, a river and lake down to the south and a farm area to east. And of course there is The Dark Forest to the north, which I have named such for ominous and adventurous reasons. We still haven’t decided on any name for the world yet, but I’m almost positive that we will come up with something colourful and original like Wondershire, or Fantopia.

Before I am happy with the world I am creating I still have a bit more work to do. I want to have more dungeon entrances spread all around the map. I would also like to fill the map up enough so that you never have your character in a screen which only shows grass. As this gives you little sense of where you are on the map and is just plain boring to look at. I also need to enclose the map so our player doesn’t just wonder off into the abyss that is a world with no textures.

Otherwise the world creation is an ongoing process which can always be worked and improved upon, as well as just generally adding more things to it. Atleast until the final build of the project.

Into the caverns we go!

Greetings, adventurer!

Today, we’re going to create some caverns. Correction, we’ll make the computer create these caverns for us. that’s right it’s randomly generated dungeons.

I want to make it very clear that there are many ways to do this. You can for instance use TinyKeepDev method. There is also this fantastic presentation by Zach Aikman of 17-BIT, which I highly recommend.

We went for a fairly simple implementation. The first thing we did was to create a 2d int array map which hold either 1 or 0. 1 means wall, 0 means floor. We then fill it, using a fill percent variable which dictates the amount of wall percentage to fill in the array. Something to note is that we want a special if statement to cover the borders, such that the cavern has borders. Moving on, we now  have a 2d array map[x,y] with 0’s and 1’s.

What do we do with it? We then run it through a modified version of Conway’s game of life in order to smooth the map a couple of times and we only need to draw the map. We now have a map with potentially many different spaces. In this context we define a space as an area of floor tiles.We need the largest such space and to do that we run a depth first search where each tile is a vertex. Now all we need is spawning “stuff” (monsters, treasure chests, etc…) and we’re done.

Now into some detail and code.

Let’s start with the creation of the map.

createMap

Now, you might think that this randomiser is an overkill, but well… Why not? Anyway, the principle is simple.

for each pair of coodinates x,y :

if map[x,y] is a border -> make it a wall n make it a wall

else -> if it’s below the fillPercent variable, make it a wall, else make it a floor.

Earlier I mentioned The Game of Life, here it is.

smooth and getAdj

Now that we have a map, we need to determine the largest space. It’s a very standard implementation of DFS (Depth First Search) using recursion. You can use stack as well. However we also need to loop through the graph.

runthrough

I love traversing a grid like graph, it’s just so cozy and intuitive.

DFS

All we need now is to draw the map.

drawmap

The position is x*0.32, y*0.32 because we’re using 32 bit sprites.

That’s all for today, hope you found this educational and and enjoyable. I actually over complicated things a bit, however I did so because I wanted a set of features like storing the most southern tile in the largest space in a cavern as a spawning point for the player, much of this could be done in far simpler manners if your game doesn’t need the same features as ours.

Best Regards

p219 Development Team

A deeper look at the enemies

Greetings, adventurer.

Today, we are taking a deeper look into the enemies. How they are built, how they behave and then we will take a look at the scripts.

For this post, I ‘am going to create a new enemy from scratch, while trying to reuse general scripts.

Today I will show you how to create “Ghost”, a completely new enemy that I will create as I write this. Ghost’s ability will be partly invisible. It will do damage on impact, and move to another location and attack again. A dungeon nightmare with other words.

Step 1: Manage the sprites

To begin with, we need a sprite. We have downloaded free sprites from LPC. The first thing we have to do, is slicing the sprite. The sprite is represented as a “.png” file. To slice the sprite, I highlight the sprite, select sprite mode: multiple and press “Sprite editor”. From here we have to do a little try and fail to slice the sprite correctly. Sometimes it slices automatically correct, but sometimes we have to manually try different slice sizes to find the correct one. In this case, I had to slice it manually with pixel size 40×46.

2015-11-17

Step 2: Creating animation

After the slicing, I now have 12 different pictures that represent the enemy. I now have to create animations. In total 8 animations. Four moving animations, one In each direction, and four idle animations. We also need an death animation, which is created is the same way, but it can be whatever you like. I will use a green explosion animation.

To do this, I select those pictures I want to use for an animation, right click -> create -> animation, and give it a proper name, e.g. GhostMoveLeft or GhostIdleRight.

Next, I move all of my animations to the animation folder, and create an animator controller called GhostAC.

Here we create 3 new states: idle, isWalking and isDead with transition between them as shows in the picture below. We also need to create some parameters: valueX, valueY, isWalking and isDead. We use isWaling and isDead as conditions for entering/leaving isWaling and isDead animations. After we have created the motion field, it is important to check “Loop time”, so the animation is not just played once.

That’s all for the animations, lets move over to create the physical part of the ghost.

 

Step 3: Adding the enemy to the game

In my scene I create an empty game object. I start by moving this game object closer to the player, so I can see the enemy when I start the game. But the enemy is not visible yet. First we have to add a sprite render. For the game object, we have an inspector panel to edit it. From here we add the sprite render (which is a component).  Now we just have to drag the sprite into the sprite render, and we have a visual enemy.

2015-11-17 (3).png

Step 4: Adding the animator controller

Now we have to add the Ghost animator controller that we created earlier. There is two ways of doing this. You can do it the normal way by finding “Animation” in the component list, or you can do it the easy way. You can just drag “GhostAC” into the inspector panel, and it automatically add the animation controller. Pretty easy.

Step 5: Adding box collider

Next the enemy need a box collider. This is so other objects, as the player, cannot run though the enemy.

Step 6: Adding rigidbody

Then we need to add a rigidbody, which gives the enemy physics in the game such as mass, gravity and collision.

Step 7: Scripting

Now comes the fun part. The first thing we want to add is the enemy stats script which controll the health, damage and stats. The setup for code is pretty simple.

First, you start with field variables and public variables. public variables can be changed in inspector and will be unique for each game object that uses the script. Field variables will be initialized by the constructor name Start()

</span>Animator anim;
GameObject statScaler;
GameObject player;
Scaler level;
<div>public int attackDamage;
public int health;
public bool debug;
public int damageIncrease;
public int yieldExp; <span style="font-family: Courier New;">

Field variables will be initialized by the constructor name Start()

</span>void Start () {
statScaler = GameObject.Find ("StatScaler");
player = GameObject.Find("Player");
anim = GetComponent&lt;Animator&gt; ();
level = statScaler.GetComponent&lt;Scaler&gt; ();
damageIncrease = level.GetScale ();
attackDamage += damageIncrease;
//health += damageIncrease;
yieldExp = 100;

}
Next, we have the built in function Update(), which is called for each frame. In this script we use Update() to decide is the enemy is dead or alive.
 void Update() {
if (health &lt;= 0) {
Die ();
}
}
A method for getting the enemy health
public int getHealth(){
return this.health;
}
A method to kill the enemy
public void Die() {
if(debug)
print ("dead");
health = 0;
anim.SetBool ("isDead", true);
anim.SetBool ("isWalking", false);
}
A terminate method. This is called on the last frame of the death animation to remove the game object when it is dead.
void Terminate() {
player.GetComponent&lt;PlayerStats&gt;().IncreaseCurrentExperience(yieldExp);
Destroy (gameObject);
}
A method to get the attack damage from the enemy
public int GetAttackDamage() {
return this.attackDamage;
}
And at last we have a method which is called when the enemy is attacked by the player
public void TakeDamage(int damage) {
if (debug)
print ("Taking dmg. health = " + health);
health -= damage;
}
This whole script is a prefab, which means that this script can be Applied to any enemy we decide to create in the future, or something else that need to have a health and can be killed.
Step 7b: Adding attack script
Now we need tok create a script for the enemy to attack the player. As a ghost, i think that is should move slow against the player, hit it once, and move away from the target again in another direction. Since it is a ghost, it should also be invisible from time to time. To do this, I reuse the hitAndRun script we have for the bat and extend it with some lines of code to adjust for the Ghost.
Just to be clear. I am not creating a whole new script for each enemy. I extend those we already have to be general for multiple enemies. This script already have methods for moving toward and away from the player.
For the Ghost to use hitAndRun-script, I added these lines of code.
Some variables
private bool isInvisible = false;
private float invisStart = 0;
private float invisStop = 0;
private float invisCD = 2.0f;
private float invisTime = 1.0f;
The logic. These lines of code will only apply to enemies named “Ghost”. In this way, it will not affect bat or other enemies using this script.

if (this.name.Equals ("Ghost")) {
if ((Time.time &gt; invisStop + invisCD) &amp;&amp; !isInvisible) {
GhostEnableInvisible ();
}
if ((Time.time &gt; invisStart + invisTime) &amp;&amp; isInvisible) {
GhostDisableInvisible ();
}
}

And two methods for change visibility


void GhostEnableInvisible(){
invisStart = Time.time;
isInvisible = true;
spriteRender.enabled = false;
}
void GhostDisableInvisible(){
invisStop = Time.time;
isInvisible = false;
spriteRender.enabled = true;
}

Step 8: Creating prefab

Now, the enemy is complete. The only thing left is creating a prefab of the enemy. This means that it is saved in the prefab folder  as a prefab, and can just be clicked and dragged into any scene you cant. Then you can modify og create as many copies you want out of it. Creating prefabs in Unity is very easy. Just right click -> create -> prefab, and drag the newly created enemy into it and give it a name.

 

2015-11-17 (5).png

Here is a picture of “Ghost” chasing me.

That’s all for today. Hope you enjoyed.

Best regards

P219 Development Team