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 :