Asteroids Project
Updated 384 Days AgoPublic

This page outlines the steps need to create a basic version of the classic game Asteroids. You should make sure you understand the content of the Basic Tutorials tagged with Beginner III before beginning this project.

NOTE: Like other project pages this tutorial does not cover every tiny step the user must complete and instead summarizes. This requires the reader to understand basic concepts from preceeding tutorials to complete the project.

Learning Objectives

  • Reaffirm the learning objectives of Beginner III tutorials.

Level Setup

The Player

Player Archetype

Player Movement

  • Command : Add Resource
  • Create a ZilchScript using the Component template and name it PlayerMovement
  • Upload the Player to a new archetype called Player

Properties

  • Define properties of type Keys in PlayerMovement for the forward, backward, left, right, and shoot keys for the player
  • Define properties of type Real called Speed and RotationSpeed

Moving

Rotating

  • In PlayerMovement in OnLogicUpdate
    • Declare a local rotation variable
  • Check if the Left and Right input keys defined above are down using Zero.Keyboard.KeyIsDown()
  • Declare a local variable rotationSpeedRadians and initialize it to RotationSpeed converted to radians.
  • Use Transform.RotateWorld() to rotate the object by rotation * rotationSpeedRadians * event.Dt

Player Shooting

  • Command : Add Resource
  • Add a ZilchScript using the Component template and name it ObjectSpawner
  • Command : Add Resource
  • Add a ZilchScript using the Component template and name it CreateOnInput
  • Upload the Player to a new archetype called Player

Properties

  • In ObjectSpawner
    • Define a property of type Archetype named ArchetypeToSpawn
    • Define a property of type Real named InitialVelocity
    • Define a property of type Boolean named UseRandomDirection (defaulting to false)
  • In CreateOnInput
    • Define a property of type Keys in ObjectSpawner named SpawnKey

Spawning Projectiles

  • In the ObjectSpawner component
    • Create a new function named SpawnObject()
    • In SpawnObject()
      • Create a ArchetypeToSpawn object at the position of the Player
      • If ObjectSpawner.UseRandomDirection is true then get a normalized random direction, or if UseRandomDirection is false use Orientation.WorldForward for the direction of the object's inital velocity.
      • Set the initial velocity of the object.
  • In the CreateOnInput component.
    • Connect to LogicUpdate
    • In OnLogicUpdate
    • Set the velocity of the newly created Projectile to this.InitialVelocity * this.Owner.Orientation.WorldForward

The Projectile

  • Command : Add Resource
  • Create a ZilchScript using the Component template and name it DestroyOnCollision
  • Under the Sprite component change the VertexColor
  • Upload the Projectile to a new archetype called Projectile

DestroyOnCollision

Properties

  • In DestroyOnCollision
    • Define a property of type Boolean named DestroyOwner (defaulting to false)
    • Define a property of type Boolean named DestroyOther (defaulting to false)

Destroying On Collision

  • In DestroyOnCollision
    • Connect to the CollisionStarted event
    • In OnCollisionStarted
      • If DestroyOther is true call event.OtherObject.Destroy()
      • If DestroyOwner is true call this.Owner.Destroy()
  • Play the game
    • At this point the ship should be able to move, rotate, and shoot.

Astroids

Spawning Asteroids

CreateOnInterval Component

  • Add a ZilchScript using the Component template and name it CreateOnInterval
  • Move the AsteroidSpawner outside the viewport so the GameCamera can not see it
  • Upload the AsteroidSpawner to a new archetype called AsteroidSpawner

Properties

  • In CreateOnInterval
    • Define a property of type Real in CreateOnInterval named SpawnRate
    • Define a property of type Boolean in CreateOnInterval named StartOnInit defaulting to true
    • Define a non-property member variable of type ActionsSet in CreateOnInterval named SpawnSequence

Interval Spawning

  • In CreateOnInterval
    • Declare a function named StartSpawnSequence
    • In StartSpawnSequence
      • Construct a new ActionSequence using this.Owner.Actions and assign it to the member variable SpawnSequence
        • Construct a Delay action using SpawnSequence and SpawnRate
        • Construct a Call action using SpawnSequence and ObjectSpawner.SpawnObject
        • Construct a Call action using SpawnSequence and StartSpawnSequence
    • In the Initialize function
      • If StartOnInit is true
        • Call StartSpawnSequence

The ScreenWrap Component

  • Add a ZilchScript using the Component template and name it ScreenWrap

ScreenWrapping

  • The ScreenWrap component should look like this
ScreenWrap
class ScreenWrap : ZilchComponent
{
  [Dependency] var Transform : Transform;
  
  [Property]
  var Camera : CogPath = CogPath();
  
  function Initialize(init : CogInitializer)
  {
    Zero.Connect(this.Space, Events.LogicUpdate, this.OnLogicUpdate);
  }

  function OnLogicUpdate(event : UpdateEvent)
  {
    //Get the viewport component
    var viewport = this.Camera.Cog.CameraViewport;
    
    //prevent dividing by zero when the viewport resolution is (0,0) on game close
    if(Math.LengthSq(viewport.ViewportResolution) == 0.0)
      return;
      
    //get the normalized viewport
    var worldPos = this.Transform.WorldTranslation;
    var screenPos = viewport.WorldToScreen(worldPos);
    var viewportPos = viewport.ScreenToViewport(screenPos);
    var normalizedViewportPos = viewportPos / viewport.ViewportResolution;
    
    //screen wrap in normalized viewport space
    if(normalizedViewportPos.X > 1.0)
      normalizedViewportPos.X = 0.0;
    else if(normalizedViewportPos.X < 0.0)
      normalizedViewportPos.X = 1.0;
    
    if(normalizedViewportPos.Y > 1.0)
      normalizedViewportPos.Y = 0.0;
    else if(normalizedViewportPos.Y < 0.0)
      normalizedViewportPos.Y = 1.0;
    
    //convert the wrapped viewport position to world space
    viewportPos = normalizedViewportPos * viewport.ViewportResolution;
    screenPos = viewport.ViewportToScreen(viewportPos);
    worldPos = viewport.ScreenToWorldZPlane(screenPos, worldPos.Z);
    
    //set the object's position
    this.Transform.WorldTranslation = worldPos;
  }
}
  • Drag and drop an instance of the Asteroid Asteroid and Player in the level
  • Under ObjectSpawner
    • Set the Camera CogPath property to reference the Gamecamera

The complete asteroids project

At this point you should have a small ship navigating the screen, shooting, screenwrapping, and destroying asteroids.

Last Author
arend.danielek
Last Edited
Jan 2 2018, 12:37 PM
Projects
None
Subscribers
None