Deprecated: Creation of dynamic property wpdb::$categories is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$post2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$link2cat is deprecated in /var/www/twodee/blog/wp-includes/wp-db.php on line 668

Deprecated: Return type of WP_Theme::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 554

Deprecated: Return type of WP_Theme::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 595

Deprecated: Return type of WP_Theme::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 535

Deprecated: Return type of WP_Theme::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-theme.php on line 544

Deprecated: Return type of WP_REST_Request::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 960

Deprecated: Return type of WP_REST_Request::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 980

Deprecated: Return type of WP_REST_Request::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 992

Deprecated: Return type of WP_REST_Request::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/rest-api/class-wp-rest-request.php on line 1003

Deprecated: Return type of WP_Block_List::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 151

Deprecated: Return type of WP_Block_List::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 175

Deprecated: Return type of WP_Block_List::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 164

Deprecated: Return type of WP_Block_List::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 186

Deprecated: Return type of WP_Block_List::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 138

Deprecated: Return type of WP_Block_List::offsetExists($index) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 75

Deprecated: Return type of WP_Block_List::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 89

Deprecated: Return type of WP_Block_List::offsetSet($index, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 110

Deprecated: Return type of WP_Block_List::offsetUnset($index) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 127

Deprecated: Return type of WP_Block_List::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/twodee/blog/wp-includes/class-wp-block-list.php on line 199

Deprecated: Creation of dynamic property Automattic\Jetpack\Connection\Manager::$error_handler is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 91

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Instagram_Gallery::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-instagram-gallery.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Mailchimp::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php on line 17

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 21

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$is_wpcom is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 22

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php on line 20

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_site_specific_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 24

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Subscribers::$wpcom_is_wpcom_only_endpoint is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php on line 15

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property WPCOM_Widget_Goodreads::$shelves is deprecated in /var/www/twodee/blog/wp-content/plugins/jetpack/modules/widgets/goodreads.php on line 33

Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /var/www/twodee/blog/wp-includes/script-loader.php on line 348

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_classic_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 347

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 349

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$toolbar_block_side is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 350

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$panels_block is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 351

Deprecated: Creation of dynamic property Advanced_Editor_Tools::$used_block_buttons is deprecated in /var/www/twodee/blog/wp-content/plugins/tinymce-advanced/tinymce-advanced.php on line 354

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /var/www/twodee/blog/wp-includes/class-wp-block-type.php on line 333

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /var/www/twodee/blog/wp-includes/class-wp-term.php on line 198
» CS 491 Lecture 12 – Properties and Projectiles

teaching machines

CS 491 Lecture 12 – Properties and Projectiles

March 10, 2016 by . Filed under
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /var/www/twodee/blog/wp-includes/category.php on line 383
gamedev3, lectures, spring 2016.

TODO

Lab

Today we pick up where we left off in Our Color vs. Their Color, the sequel to Our Animal vs. Their Animal. If you didn’t finish the camera switching coroutines from last time, start there. Ask plenty of questions if things are behaving strangely! From there we’ll add shot that can be picked up and fired at tanks of the opposing color.

Shot

First let’s add a sphere game object. Name it Shot, give it a rigidbody component, and turn it into a prefab. Delete the instance from the scene.

Give the prefab a ShotController script, which we’ll leave blank for the time being.

Spawner

Where does this shot come from? We don’t want each tank to carry an endless supply, because infinite bullets ruin games. Instead, let’s have the shot will fall from the sky. Add a ShotSpawner empty to the scene. Place it somewhere near your default tank so you can quickly test things out without having to first drive over to spawner.

Give it a ShotSpawnerController script which will continuously emit shot. Give it a public game object named shotPrefab. Drop in the shot prefab in the Inspector.

Let’s create a coroutine to do the emitting:

IEnumerator Emit() {
  while (true) {
    Instantiate(shotPrefab, transform.position, Quaternion.identity);
    yield return new WaitForSeconds(timeBetweenDrops);
  }
}

Fire off the coroutine in Start with StartCoroutine.

Playtest. Does shot fall?

Team Enum

To track what side a tank is on and from which side a fired shot comes from, let’s add an enum named Team. Create a new C# script, but delete all the default text and replace it with this simple enum:

public enum Team {
  A, B, NEUTRAL
}

Team Materials

Let’s color each tank and shot according to the team to which it belongs. Create three materials, one for team A, one for team B, and one neutral color, used for shot that hasn’t been claimed.

Coloring Tanks

Let’s use our work from the previous two steps to get tanks colored according to their team. Add a TankController script to the tank parent prefab. Give it a public Team variable and a public Material array with two elements. The Team variable will be assigned per instance, but we can safely assign the materials on the prefab.

With the prefab selected, drop in materials A and B into the array in the Inspector.

Add an UpdateColor method that colors the tank according to its current team. Color is determined by the material, which is a property of the MeshRenderer component that’s part of the tank model object, which is a child of the parent. So, we must do some querying to get at what we need:

Transform child = transform.Find("REPLACE WITH NAME OF THE CHILD TANK OBJECT");
child.GetComponent<MeshRenderer>().material = materials[team == Team.A ? 0 : 1];

Call UpdateColor in Start to assign each tank its initial color. Find some of your tank instances in the hierarchy and alter their team in the Inspector.

Also add a public Flip method. If the tank is of team A, switch it to B. And vice versa. Update the color after switching. We’ll call this method later when a tank gets hit by shot from the other team.

Playtest. Do you see tanks of opposing colors?

Tank’s Shot Property

Let’s handle picking up the shot now. For this, we’re going to use a feature of C# that is worth knowing: properties. Properties let you expose state of an object in a controlled way. Outside clients feel like they’re directly accessing instance variables through natural syntax, but in reality they are calling special accessor methods that give you complete control over that state. In essence, properties let methods masquerade as variables. There may not even be an instance variable behind the property! The value might be derived from some other data.

The state that we’ll make a property for is the shot that a tank may or may not be holding. We first add a backing store for this shot:

private GameObject _shot;

Note that it’s private. Now let’s add a public property to manage access to this state:

public GameObject shot {
  get {
    return _shot;
  }
  set {
    // we'll expand this soon
  }
}  

Whenever someone expresses tank.shot, this will behave like a call to tank.getShot(). Whenever someone expresses tank.shot = rhs, this will behave like a call to tank.setShot(rhs). If we ever want direct access to the state, we just use _shot.

Shot’s Team Property

Let’s also add a team property to the shot. We’ll use this to color the shot according to its current team. First, add a Material array with three elements to the shot prefab, and drop in materials A, B, and neutral. Add an UpdateColor method:

void UpdateColor() {
  MeshRenderer renderer = GetComponent<MeshRenderer>();
  if (team == Team.A) {
    renderer.material = materials[0];
  } else if (team == Team.B) {
    renderer.material = materials[1];
  } else {
    renderer.material = materials[2];
  }
}

Now add a team property, whose setter triggers an update of the color:

private Team _team;
public Team team {
  get {
    return _team;
  }

  set {
    if (value != _team) {
      _team = value;
      UpdateColor();
    }
  }
}

Claiming Shot

Initially, let’s have a tank claim a shot when it collides with it. We could handle this collision in either TankController or ShotController. Let’s do it in ShotController. Since shots will collide with many things (ground, obstacles), give the tank parent prefab tag Tank. Then we can add a discriminating OnCollisionEnter method:

void OnCollisionEnter(Collision collision) {
  if (collision.gameObject.tag == "Tank") {
    // assign this shot to the TankController
  }
}

Replace the comment with an assignment to the tank’s shot property.

Then, back in TankController, expand the set to slurp up the shot only if it doesn’t already own one:

set {
  if (_shot == null) {
    _shot = value;
    // assign this shot's team to tank's team
  } else if (value == null) {
    _shot = null;
  }
}

Playtest. When you run into a shot, does it change color?

Picking Up Shot

Instead of just leaving the shot on the ground, let’s pick it up. In the setter for the shot’s team, if the team is not NEUTRAL, use SetActive(false) on the game object to hide the shot that just got picked up.

Playtest. Do the claimed shots disappear?

Firing Shot

Let’s give the tank the ability to fire the shot it’s holding. Add a public Fire method that looks something like this:

if tank has a shot
  make shot active again
  set it's position to be tank's + tank's forward * some scale
  add forward force to shot's rigidbody
  shot = null

Then, in PlayerController, let’s trigger this when the Fire1 button is down. By default, Fire1 is the left mouse button or left Control key. We listen for user input in the Update method:

if (Input.GetButtonDown("Fire1")) {
  // get TankController and fire
}

Playtest. Can you fire the shot?

Flipping Colors

When a tank gets hit by a fired shot, let’s flip its color. Head back to ShotController.OnCollisionEnter. Instead of blindly assigning the shot’s owner, let’s expand the logic a bit:

if collided with tank
  if shot is neutral
    assign shot to tank
  else if shot's team != tank's team
    flip tank's color
    destroy shot

Playtest. Do tanks switch color when hit?

Neutralizing Misses

When a shot hits the ground or any other non-tank object, let’s neutralize it so it becomes fair game for future pickups. In OnCollisionEnter, let’s add a case for hitting non-tanks:

if collided with tank
  ...
else
  set shot's team to NEUTRAL

Halo

It’d be nice if you could look at a tank and see if it currently carried a shot. Let’s add a reddish glow to tank’s packing heat.

Unity provides a halo effect that we can use, but there appear to be some bugs or just unsupported features that make it difficult to enable or disable dynamically. If we add a Halo component, we should be able to say something like this:

tank.GetComponent<Halo>().enabled = true;

But I can’t get this to work. Instead, let’s add a child to the tank parent prefab. Position it right at (0, 0, 0). Give it a Halo component and switch the color to something dangerous. Deactivate the child object in the Inspector by checking the box in the upper-left corner.

In TankController, add a private game object named halo. In Start, grab a reference to it by searching for it:

halo = transform.Find("Halo").gameObject;

In the shot property’s setter, activate this object when a shot is picked up, and deactivate it when the shot goes null.

Playtest. Do the halos appear when you pick up a shot and disappear when you fire?