Creators – Week 10

This week we continued the second week of our Gem Search project. We completed the ItemScatterer component by:

  • Completing the Distribute() function to scatter our items, temporarily lamp posts, across the environment
  • Writing a FindNearest() function to keep track of which item that we’ve spawned is closest to the player at all times

We then finally tested it by adding an ActivateNearest() function to light up the nearest lamp post and give us a visual validation that things are working.

Distribute

Our function to distribute the items comes in has five main pieces to it:

  1. A calculation to workout the top-left-back corner of the space covered by the ItemScatterer
  2. A pair of loops which move us over the space in the X and Z directions
  3. A calculation to workout the current position that we’re at on the top of the ItemScatterer
  4. A probability check to determine if this is a location we should be placing an item
  5. A Physics.Raycast() call which allows us to determine the exact height of the ground at this position

The Corner Calculation

The top-left-back corner, which we’re calling start, is calculated using the position of the ItemScatterer and the size that’s been specified:

        Vector3 start = new Vector3(transform.position.x - size.x / 2.0f,
                                    transform.position.y + size.y / 2.0f,
                                    transform.position.z - size.z / 2.0f);

The transform.position of ItemScatterer is going to be in the centre of its box. To get to the left and the back we take off half the box’s size in the X and Z directions respectively. To get to the top of the box, we add half the box’s size in the Y direction.

The Loops

The pair of loops look like this:

for (float xOffset = 0.0f; xOffset < size.x; xOffset += spacing)
{
    for (float zOffset = 0.0f; zOffset < size.z; zOffset += spacing)
    {
        ....
    }
}

The first loop, or outer loop, takes a variable called xOffset, initially zero, and keeps increasing it by spacing (default of 3) until it’s bigger than size.x. The represents us moving from the left to the right of the ItemScatterer.

The second loop, or inner loop, takes a variable called zOffset, initially zero, and keeps increasing it by spacing (default of 3) until it’s bigger than size.z. The represents us moving from the back to the front of the ItemScatterer.

The other important thing to note is that because the second loop is inside the first, for every step we make in X, we cover all positions in Z. Here’s what this looks like:

Calculating the Current Position

The calculation if the current position is relatively straightforward, the offsets in the X and Z directions are our loop variables and already calculate and we’re not changing the value of Y at all:

            Vector3 thisPos = start + new Vector3(xOffset, 0.0f, zOffset);
  

Probability Check

We already have our probability property for us to specify the chances of a location having an item. We compare this to Random.value, which is a random value between 0 and 1. If Random.Value is less than probability, then we’ll place something:

 // Check probability
 if (Random.value < probability)
 {
    // Place an item
 }

Physics Raycast

We have already placed our rocks and terrain into a layer named “Ground”. We only want to place our items on this layer. We can make sure that we only check this layer by using a LayerMask in our call to Physics.Raycast(). We add a new pubic string property to our class called groundLayerName and give it the default “Ground”:

public string groundLayerName = "Ground";

In our Distribute() function then, at the top before the loops, we can create the LayerMask:

LayerMask lm = LayerMask.GetMask(groundLayerName);

We also need to create a RayCastHit variable. This is somewhere that Physics.RayCast() can fill in details about what it hit. The complete code looks like this:

 // Check for ground
 RaycastHit hit = new RaycastHit();
 if (Physics.Raycast(thisPos, Vector3.down, out hit, size.y, lm))
 {
     Instantiate(item, hit.point, Quaternion.identity, transform);
 }

Physics.Raycast() returns a bool value (either true or false) and the if statement determines whether or not to Instantiate an item depending on whether or not ground was hit. The version of Physics.Raycast() we’re using takes the following inputs:

  1. The position to start the search from: thisPos which we calculated previously.
  2. The direction to search in: Vector3.down.
  3. The RaycastHit object that we want filled in: hit. Note the special out instruction that shows we’re going to getting values back from this – it’s not an input.
  4. The distance to search: size.y – no point searching further than this
  5. The LayerMask to use: lm which we calculated previously

The Instantiate is very standard, but we’ve also supplied our own transform as the parent transform. This means when the items are created, they are beneath ItemScatterer in the Heirarchy.

Find Nearest

For a human to scan a classroom and determine which desk is closest is something we do very quickly and intuitively, but a computer program generally has to take a more methodical approach. We look at each desk in turn and calculate how far away it is from us. If this is the first desk, or it’s closer than the previous desk we thought was the closest, we remember this desk and distance is is from is. We keep doing this until there are no more desks to compare against.

Here’s what the code to do this looks like:

   public Transform player;Q 
   public GameObject nearestItem;
    

    private void FindNearest()
    {
        GameObject foundNearest = null;
        float nearestDist = 0.0f;

        for (int childIndex = 0; childIndex < transform.childCount; childIndex++)
        {
            Transform thisChildTransform = transform.GetChild(childIndex);
            float thisDistToPlayer = (player.position - thisChildTransform.position).magnitude;

            if (foundNearest == null || thisDistToPlayer < nearestDist)
            {
                foundNearest = thisChildTransform.gameObject;
                nearestDist = thisDistToPlayer;
            }
        }

        nearestItem = foundNearest;
    }

We have two new public properties, one to hold the Transform of the player so we can know their position, and the other which will get assigned the nearestItem to the player every time it’s calculated. We call this FindNearest() function from Update() so that it gets run every frame.

Since we Instantiated our items as children of ItemScatterer, we can use transform.childCount and transform.GetChild(n) to know how many children we have and to get each one in turn, respectively.

Subtracting one Vector3 from another Vector3 returns a third Vector3 containing the displacement between them. Getting the magnitude of this returns the actual distance.

Finally our check:

if (foundNearest == null || thisDistToPlayer < nearestDist)
            

Says if we’ve never assigned a value to foundNearest, which will true the first time, OR (that is what the double-bars || means) the distance we just calculated is smaller than the previously smallest distance we knew about, then make this item the nearest item and remember its distance.

Code Download

The code for this week’s project is on our GitHub, as always. 

Modellers – Week 10

Hi folks, hard to believe this was our last regular session of 2019. Next week is our Christmas pizza party and show-and-tell.

This week we took a photo of a cereal box and UV mapped it to a simple cube which we scaled to the appropriate proportions. One we made our model we built a very basic studio setup and did our first render with a camera and a light.

Here are the video instructions:

Here is the final render from my model:

cerealbox_render

The file for this week can be download from here.

Once we return in January I’ll be using Blender 2.81, instead of 2.80 which we have been using, so everyone should try to upgrade if they can by going here.

Explorers Week 10 – Making Music – Electric Piano

Hi everyone,

Thank you all for coming again on Saturday, Ruaidhrí ran the session this week and I am sure you were all glad not to have to listen to me for a change.

He did musical instruments and should you how to create variables for each one so that you could have a note repeat.

No notes this week but below is the code that was used.

This coming Saturday will be run by Eoin and will be Christmas themed based! This will be our last session before our Christmas party so dust off those Christmas Hats! and Jumpers

 

Martha, Ruaidhrí, Iseult, Julie and Eoin

Explorers Week 10 – Scrolling Backgrounds

Hi everyone

Thank you to everyone who came on Saturday.

We did scrolling backgrounds and this is very useful in any type of game and can add an extra dimension to your game whether its a driving game or a flying game.

We were scrolling horizontally so we were using the xpos but remember you can just as easily scrolling vertically by just using the ypos

Here are the notes in PDF form

CDA-S8 Week_10-scrollingbackgrounds.pdf

 

Enjoy the long weekend and we will see you all the week after.

Martha

Julie, Eoin and Ruaidhrí

Creators – Finishing Pin Bowling

This week, despite a small group, we finished off the Pin Bowling game. After Christmas we’ll move onto a different game – most likely something 1st person in design.

UI Elements – Text and Buttons

We added two UI Text elements to our game and aligned them to the top left and top right hand corners respectively. One is used for showing the current score and one is used for showing the number of shots remaining. Note that when we add UI elements, Unity automatically adds a Canvas and an EventSystem for us.

UI elements don’t have a standard Transform component, instead they have a RectTransform component which is used to describe their position within their Canvas. To align to a particular location we click on the square below the words “Rect Transform” and select how we’d like to align within the Canvas by clicking one of the options while holding the Shift and Alt keys to set both the pivot and position.

screen-shot-2016-11-29-at-22-41-48

Continue reading

Beginners Scratch – Challenge 9 – Create a Breakout Game

CDA-S2-Challenge09-BrickGame

This week, the challenge in Beginners’ Scratch was to write your own version of the classic Breakout game.

This game uses lots of the big ideas that we have encountered in previous weeks, and that are good to know about when preparing to get yellow belts. These big ideas include:

  • Loops and Decisions
  • Variables and Broadcasts
  • Making Sprites Move
  • Animation and Sound

Here are my notes from the day (PDF format): CDA-S2-Challenge09-BrickGame.pdf

Here is my version of the game: http://scratch.mit.edu/projects/cdathenry/2964870

If you would like a copy of my slides in PowerPoint format, get in touch via Twitter or the comments.

Scratch Advanced – Week 10 – Christmas Game – Final Episode

What are we going to learn this week.

1. Global Variables – A  Variable that all Sprites can see.

2. More requirements

3. Ninja Belts

And that is about it for new things. We are primarily going to be concerned with getting the Present working in the Christmas Game and the final display of what you have caught.

Now, we will start in reverse and look at the “more requirements” part first. Remember we had a requirement for the game that a present should fall and if we catch it, it should be put under the tree. Well we can write that out a little better as another set of Requirements, so here goes:

More Requirements:

The present should:

1. There should be Ten presents.

2. The presents should fall in the two minutes at random times.

3. Each present should fall from the Sleigh to the ground.

4. If the present touches the fire, then it is caught, and should be moved under the tree, anywhere under the tree, but not all on top of each other.

5. Each present should be a different size and colour.

6. If a present is caught we need to keep track of how many we have caught.

So, what we can do is create one present that meets all of the above requirements and then copy it.

For number 6, it looks like we need a Global Variable so all the Present Sprites can update it. So lets make that..

And while we are on the subject of Global Variables, if the Present Sprite needs to drop from the Sleigh, it needs to know where it is, so the Sleigh needs to update a Global Variable with it’s X value all the time.

If you select the Stage, when you create a variable it is automatically a Global Variable. You don’t get the option to create it “for this Sprite only”

We need one for the X Position of the Sleigh and one to record the number of Presents.  Don’t forget to update the Sleigh Sprite so that it updates the X Position variable. Something like this:

SleighCode

Notice that I don’t have the Green Flag to Start the Game, I have used a GameStart broadcast, this is Broadcast from the Stage where I have all my initialisation code as well.

While we are creating the Global Variables, we can also create the two lists that we need to store the names and descriptions, so two lists as well.

This is what I have to set the lists at the begining of the Game:

StageCode

Now back to the Present and the requirements.

This is the code that I have that meets the requirements… Random Colour, Random time delay, after the delay, go the X Position of the Sleigh…

Present01

Now we have to sort out how to recognise if the present has been caught by the fireplace. I picked one of the colours in the fire, and used the if touching code to find out if it has been caught. If it is caught, then we move it to the Tree.

We don’t just move the Present to the same point though otherwise they would all land on top of each other. I pick a random point under the Tree. Like this: