Saturday 23 November 2013

Sorry for the delay!

Sorry for the delay, I've had quite a bit of stuff going on recently. I have still been working on the visualiser though I just haven't found time to blog about it. :)

I left off last time by saying I'll try and fill some arrays with data from the AudioSource.GetOutputData(); function and use them to transform some objects, so that's exactly what I did. I created an array of values and created a couple hundred cubes to transform with the values. Each frame I iterate through each value in the array, while iterating through each cube in the scene, I then transform the current cube's y scale by the value in the array.

Here's the code :

void Update()
{
audioSource.GetOutputData(outputData[],channel,window);
for(int i = 0; i <= outputData.Length; i++)
       {
cubes[i].transform.localScale = new Vector3(1,outputData[i] * modifer,1);
       }
}

Simple right? :D

This produced some strange, unexpected results. I expected to see a wave form constantly changing to the sound of the music. What I saw was that to some extent near the start of the wave however towards the end the cubes seemed to 'stick' or stop reacting for a while.

Here's a video and picture I took of my visualiser at this stage.



If you watched the video you can see what I mean. It doesn't look right.

I played around with some variables a bit because I was sure my code was working as expected, I mean look at the start of the wave. After playing around for a while I tried making the number of cubes and sample size the same. Instantly I noticed a difference, now every cube represented one value from the sample, constantly. What I could see was a perfect wave form as expected.

Unfortunately, I don't have any pictures of this I was so excited by how amazing the waveform looked I had to keep working on making it look more awesome! I had an idea from the start to make my waveform into a circle so I tried that. I used the standard Cartesian circle equation :

(x-a)^2 + (y-b)^2 = r^2

and wrote a method in my sampler script to place my cubes in a circle. The circle equation provides both a plus and minus value so I decided to place two cubes at a time after calculating each point on the circle.

void orderCubes(int radius, GameObject[] array)
{
      int totalLoopCount = 0;
      int xloopCount = -64;
      float yloopCount = 0;
      float Center = array.Length / 4;
      float r2 = radius * radius;
      while(xloopCount <= array.Length)
      {
               if (alterCube)
               {
                         yloopCount = (Mathf.Sqrt(r2 - xloopCount * xloopCount));
                         array[i] = Instantiate(cubeObj, new Vector3(Center + xloopCount, 0, Center + yloopCount), Quaternion.identity) as GameObject;
                         alterCube = !alterCube;
                }
                else
                {
                         array[i] = Instantiate(cubeObj, new Vector3(Center + xloopCount, 0, Center - yloopCount), Quaternion.identity) as GameObject;
alterCube = !alterCube;
xloopCount++;
                }
        }
}

I call orderCubes(); at the start of the program. I pass in a radius and an array of cubes, the method then iterates through each x co-ordinate on the virtual axis calculating its respect value for +y and -y while Instantiating cubes for each. The scene was now producing a awesome looking circular waveform. It wasn't what I wanted but I'll talk about that next time. I added lights, changed the song, and added some colour. That's all for now so until next time, enjoy the video.






Wednesday 30 October 2013

Research Results!

So when I said research I basically meant I'll do some googling and see what comes up ;)

What did come up was some visualisers other people have made using unity. Some of these visualisers aren't exactly what I intend to create but they did point me in the direction of  two functions :

AudioSource.GetOutputData(Array[], Channel);

and

AudioSource.GetSpectrumData(Array[], Channel, Window);

The functions will fill an array from the channel specified with data related to the Amplitude or Frequency an Audio Source respectively.

This is great, the values that I get I can then use for transformations, colours etc...

Now I know what functions to play with I'll try and fill some arrays with the data from the functions and use them to transform some objects in my Unity3D scene! :)




Tuesday 29 October 2013

I'm back!

Hi there, it's been a very long time since I posted anything on here, that's due to university work piling up and too much time spent playing games. After the university work pile was cleared I continued playing games and enjoying summer! I am back now though with a new idea and therefore a new project. I'm not at university right now I am actually on a year of industrial placement at an awesome company in cambridge! Even though I'm working full time there I can't get enough of it apparently so I'm going to start blogging about this new project idea I have; inspired by my newly aquired placement.

ANYWAY

My idea is fairly simple, it is a mobile 3d music visualiser made in unity.

If you don't know what a music visualiser is a quick google will provide you with some images you may be familiar with. In short I will be making a 3D scene that dynamically responds to the music I play into my application.

I have no idea if this is possible while writing this blogpost but I've come across some methods and techniques that I think will enable me to at least come up with a proof of concept. If it goes well I hope I can make it into something awesome :)

Here are some basic (mostly 2d visualisers)


So for now that's all I'm going to say, I'm going to go off and research this idea and get back to you!

See you soon!

Tuesday 19 March 2013

Branches!

I'm now on my Easter 'break' which means ill be spending a lot of time on my team project! Incidently this means there is going to be more blogs/longer blogs :) 

Anyway back to business! I have a random dungeon path generator that recognises how many rooms are around it and knows where those adjacent rooms are. That's cool but one path? that's pretty... well... linear and often times linear equals boring. So let's add some branches to the path giving the player some options when traversing the dungeon. What those options are can be decided at a later date.

To crate a branch to my dungeon the code is going to be very similar to that of the main path, however the starting location will be a room that already exists along the main path. To do this I generate a random number between 0 and the length of the path which will be represented by roomCount.

Random.Range(0,roomCount);

I will then take the co-ordinates of a room that have this random number as an index within the array. This is our starting room. After the first room is found the code for making a branch is almost identical to that of drawing the main path with some altered variable names.


uhh, maybe there needs to be some other changes... So I introduced some new public and private variables;

public bool branches : branches is used to decide if the path should have branches via an if statement.
private int branchCount : branchCount is used to count the rooms created that are represent branches, if added to roomCount will produce the index of that room in the array.
public int branchNumber : branchNumber adjusts the number of branches attached to the path
public int branchLength : branchLength adjusts the number of rooms in a branch.

The problem in the previous picture is that there was nothing telling the branches when to stop.

Using branchNumber and branchLength I'm defining  a stopping point for branch creation.



So my branches are working somewhat but I can instantly see where the issue is. Branches crossing over each other and branches crossing with the main path cause my adjacent calculations to exceed 4 rooms and currently there is no option if a room has 5 or more adjacent rooms. To fix this I either have to give options for having 5 or more adjacent rooms, remove the unnecessary additional adjacent rooms or just stop looking for rooms if I have 4 already. So naturally I did all of them just to be safe. :D

I changed the 4 room if statement to

if(adjacentCount >= 4) { Instantiate 4 Door Prefab }

That way if there are somehow 5 or more adjacent rooms it will just place 4 doors.

I then introduced some booleans

bool N
bool S
bool E
bool W

If a room has been found at any of the respective positions, the boolean value will change. If one of the boolean values have changed another room at that location cannot increment adjacentCount.

if(Yarr[j] == roomY+1 & Xarr[j] == roomX & E == false) { adjacentCount++; E = true; }

Lastly I want to remove rooms that have the same value as other rooms. To do this I go through the array with one for loop:

for(int i = 0; i <= roomCount+branchCount; i++)

I then go through the array again inside that loop using another for loop:

for(int i = 0; i <= roomCount+branchCount; i++)
{
         for(int j = 0; j <= roomCount+branchCount; j++)
}

using the If statement:

if(Xarr[j] == roomX & Yarr[j] == roomY & j != i)

I set the X and Y value of the room being compared to -10. When it comes to drawing rooms if a room has -10 X and or -10 Y, just don't draw it.

for(int i = 0; i <= roomCount+branchCount; i++)
{
        roomX = Xarr[i];
        roomY = Yarr[i];
        for(int j = 0; j <= roomCount+branchCount; j++)
        {
                 if(Xarr[j] == roomX & Yarr[j] == roomY & j != i)
               {
Xarr[j] = -10;
Yarr[j] = -10;
 }
        }
}

The Final Product :




There were some other issues that were down to typos in the code that didn't come out with compiler errors that are now fixed :)

Tuesday 12 March 2013

Which way should I be facing!?

Aaaaaaaaaaand we're back, I've been spending most of my time doing other assignments so I've only just found some time to write a post. Last post I showed a picture of a dungeon path that recognised how many rooms were adjacent to it. Thats all good but how do we utilise the information about adjacent rooms and use it to line up and remove unecessary doors?

Well firstly I used some mathematical methods I learnt in GCSE! Binary Logic and Pascal's Triangle. I know there are 4 different relative door positions:

North, South, East, West.

4^2 tells us the number of combinations there are which is 16. If I include the option of 0 adjacent doors as a 0 value that makes 5 options, the 5th row of pascals triangle tells me the distribution of possibilities:

1 4 6 4 1

Now let's check if my GCSE maths was actually useful by doing some logic. Each bit in these calculations represent a possible room or door position.

nsew
0000
0001 w
0010 e
0011 ew
0100 s
0101 sw
0110 se
0111 swe
1000 n
1001 nw
1010 ne
1011 new
1100 ns
1101 nsw
1110 nse
1111 nsew

Posibilities :

0 Doors/Rooms : 1
1 Door/Rooms : 4
2 Doors/Rooms : 6
3 Doors/Rooms: 4
4 Doors/Rooms : 1

So now I know the properties of each room, but how do I program my script to utilise this? Well my script can already figure out how many adjacent rooms there are, and thanks to Pascal and Binary Logic we know that each number of adjacent rooms have certain possibilities and we know the combinations of these possibilities, so first we need to allow our script to represent these combinations.

I created 4 new Boolean variable types; Nbool, Sbool, Ebool, and Wbool. These types represent the bits from earlier and are all initialised as false at the start of the path calculation loop. If a room is adjacent, one of these Boolean values is set to true depending on its' relative co-ordinate.

Next I'll perform a check inside the if statements from before. If for example, Nbool and Sbool are true, this would mean adjacentCount is 2.

if(adjacentCount == 2)
{
      if(Nbool == true & Sbool == true)
      {
              //Load a room with a door the North and South side.
      }
}

Using other relevant if statements I can place every room appropriately.

On the Unity side of things this became somewhat of an issue due to run time rotation transformations but eventually it lead to me defining public variables for every possible room (all 15 of them) and setting up pre-transformed prefabs for all of them. Here's what i got.


And there you have it.... wait what?!



Well it looks like Darksteel set me up with some dodgy prefabs! It's fine though I hard-coded them into the correct position. I'll get some replacements eventually but this will have to do for now. :)

Here's what i got after hard-coding the transformations.


Saturday 9 March 2013

Knowing what's around you!

So I have all these beautiful room prefabs but my script doesn't know when to use the appropriate one! Not only that but it doesn't know which way the prefab needs to be facing! Fortunately I have a plan to get this working.

My script needs to figure out how many rooms are adjacent to the room in question. To do this I need to know the properties of an adjacent room. An adjacent room will have the same co-ordinates as the room in question except it's X or Y value will be 1 higher or 1 lower. Now how do I get my script to check this? Firstly I start off by choosing a room to check, this can be done using a for loop.

for(int i = 0; i <= roomCount; ++i)
{
      Xcheck = Xarray[i];
      Ycheck = Yarray[i];
}

This loop will fetch me every room co-ordinate in the arrays for checking, but I want to check every room values against every other room in the arrays! To do this I embed another for loop inside the for loop I just created.

for(int i = 0; i <= roomCount; ++i)
{
        Xcheck = Xarray[i];
        Ycheck = Yarray[i];
        for(int j = 0; j <= roomCount; ++j)
       {
                if(Xcheck == Xarray[j]+1)
               {
               This room is adjacent
               adjacentCount++;
               }
       }
}

I then introduce several if statements to check if the room's co-ordinates determined by j are adjacent, if the if statement passes then an integer variable called adjacentCount is incremented. When it comes to drawing the room I can then use another if statement such as "if(adjacentCount == 4)" then load a 4 doors prefab. adjacentCount is then reset when a new room is being checked.

I introduced these changes to my script as well as colour changes to each prefab so they are more visible and here is my result.

Red Room = 1 Door
Blue Room = 2 Doors
Green Room = 3 Doors
White Room = 4 Doors


Prefabs and Player Controls

Okay so I have some kind of path generating and I've ironed out some obvious bugs I can see from the scene viewer in Unity, but now it's time to get inside the dungeon and test it from the inside as if I were playing the game. For this to happen I'm going to get some outside help. I need rooms to load instead of these primitive Unity cubes as well as a Player Character to run through these rooms with.

Rooms -

I'm lucky enough to have some housemates with skills in different areas, two of them being product design. One of these housemates (lets call him Darksteel) agreed to make me some place holder rooms for my dungeon. I needed some hollowed out cubes with doors on each side in several combinations.

4 Doors
3 Doors
2 Doors (Parallel)
2 Doors (Adjacent)
1 Door

Darksteel promptly made me these rooms and I modified my script to load in his 4 door rooms as prefabs, added some lights and this is what I got :


Unfortunately I haven't edited my script to detect which room to load in but I think that deserves it's own blog post as it's going to be somewhat complex.

Player Character -

I'm also very lucky to be teamed up with some other skilled programmers who are working on other parts of the game unrelated to dungeon generation. This meant we already had a Player Character prefab set up, this meant I could just reuse the assets they had created. I  then set up my script to load in the Player Character prefab into the First Room using the same if statement I made to draw it. Other than that some changes I made were the scale of the Player Character and adding Terrain and Mesh collision to my prefabs.

It is now possible to traverse my dungeon from the inside as if you were playing the game :)

Here is a pic from the Player Character's camera :

Friday 8 March 2013

Starts, Ends and Wall Hugging

Although the pictures from my last post looked acceptable there were some issues that would take several generations of the dungeon to see clearly.
  • Wall Hugging.
  • No clear start or end.
  • Redrawing of rooms.
Wall hugging -

You may be able to notice in the last picture i posted that the dungeon will hit a wall and stick to it, this is because once the dungeon hits a wall it will have an equal chance to move away from the wall as it does to attempt to move into the wall. I fixed this issue with a small if statement that changes the values of Yvar (the variable that effects the probability for the next room to move up or down). If the Y value is equal to gridSize or 0 then Yvar will change from 50 to 25 or 75, reducing the probability to move in the same direction. This fix is far from perfect but it does the job for the time being and produces some interesting looking dungeons.

No clear start or end -

Visibly determining whether a room is the start or end would be difficult, however as far as my script is concerned there isn't one. This may not seem like a problem right now, and that's because it's not, but when it comes to implementing other features such as; a stash at the start of every dungeon, making sure there are no enemies in the first room or have some kind of entrance door, I would like to know which room is the start and which is the end.

To do this I used an integer variable that increments every time a new room co-ordinate is decided (roomCount). From this I know the index of the array that contain the last room's co-ordinates. I then used two if statements "if(arrayPosition == 0)" and "if(arrayPosition == roomCount)". Finally to make these rooms visibly noticeable i changed their colours.

Redrawing of rooms -

This is the biggest of the 3 problems in my opinion, from the pictures it is impossible to see this but from the code you can clearly see how this is possible. Currently if a new room has been placed by incrementing Y there is nothing saying that the next room to be placed will be on a decrement of Y, this gives the dungeon the opportunity to continuously move up and down along the Y axis and never progress along the X. This causes increased loading times and lower FPS during gameplay.

Although this is the biggest issue it isn't that difficult to fix. I introduced some Boolean variables; moveEast, moveNorth, moveSouth. My aim is to check these variables when deciding where a room shall be placed. When a room moves North (incrementing Y) moveNorth will be set to true, if moveNorth is true, a room cannot be placed by decrementing Y (moveSouth), when the room is placed by incrementing X (moveEast) both moveNorth and moveSouth will be set to false allowing the possibility for the path to move North or South again.

Here's the end result of these fixes :)


Let's get started!

Immediately after it was decided I would be focusing on dungeon generation I whipped up some code in what I'd call a mix of php and C++ (prior to writing this code i was doing a lot of php coding for my Application Development module so it was just in the back of my mind). My immediate thought is that I wanted to create a script that would produce a progressive increase in X and Y values that i could then transform some kind of prefabrication by to position 'Rooms' along my dungeon path.

The script I made would initialise a pair of variables and progressively increment or decrement either one of them but never both (this would cause a diagonal movement along a pair of axis, which I didn't want) after deciding which value (X or Y) to alter the script would then add the value to an array. This would continue under the constraint "while(X != gridSize)" this just gave the script an ending point, eventually gridSize could be any number you or I wanted.

The first 'room' to be placed into the array would start at the co-ordinates; (0,0-gridSize)  to do this I initialised the Y variable with a 0-gridSize random number generator attached to it. The next form of randomisation involves deciding whether additional room values are an increment for X or an increment/decrement to Y (There is no decrement on X because I don't want the path to go back on it's self at this moment). I did this by creating 2 addition variables initialised with a random generator between 0-100(Xvar and Yvar). I then create an if statement to decide whether X will be incremented "(If Xvar <= 25)" else increment Y (if Yvar <= 50) else decrement Y. Adjusting the numbers in the if statement will ultimately change the shape of the dungeon.

At this time i had no way of graphically representing anything i'd done so until then i spent time getting familiar with Unity3D, a few tutorials later i managed to represent the values in my array by drawing cubes into the engine then transforming their X and Z locations by the X and Y values in my array respectively.

This is what i got :)




Introduction

Hi there, I'm Joel and I'm a Computer Games Programming student at the University of Derby in the UK. I'm creating this blog not only to share the progress of my work but also to work as a semi portfolio to show future potential employers.

Currently I am working on a team project under the group name Indiecisive Studios (see what we did there?). The project is a game called 'Venture', a Hack and Slash Action Adventure Survival Game with Role Playing Game Elements in a world that is based on random terrain, item and dungeon generation, The aim of the game is to finish with the highest score possible, whether that is decided on time survived, items gained or enemies slain is still a work in progress. Venture will use the Unity3D game engine and we will be coding in C# for the most part.

My main focus so far has been to create a dungeon that is randomly generated. The methods I use to do this were up to me and for now this blog will showcase how i am progressing towards that goal. I will also mention occasionally the progress of my team and how we work together to create 'Venture'.