Figure 1 Initial Sketch and Photo

The Pollinator

ATEC 6343

Dr. Paul Fishwick

Karen Doore

May 12, 2014

By Derek L. Manns

Figure 2 Sketch of Control flow

My Idea was to represent my interpretation of bee pollination through space exploration and colonization of planets.

Using control flow model with a Finite State Machine, the classic gameplay of Asteroids, the arcade game, is demonstrated with cellular automata.

Figure 3 Creative Automata

Here are the instructions:

Figure 4 Instructions for Demo Controls

Functionality created for this Demo:

  1. Thruster to propel the ship
  2. Controls from the keyboard and mouse
  3. Xbox standard controller used: Analog for steering, X button for propulsion, A button to engage object (Planets).
  4. Touch/Mouse click for tablet and smart phones

The top left corner of the gameplay space is represented as a minimap. This map displays the Finite State Machine (FSM).

Figure 5 Minimap of Finite State Machine

Figure 6 Finite State Machine representation

While the Finite State Machine is represented above the key to the control flow is shown below.

Figure 7 Demo

Below is the JavaScript used in association with the Unity Engine.

Bee Script

#pragma strict
var pollinate:int;
var fly:int;

var rotateSpeed:float;
var pollinEmitter:ParticleSystem;
var maxSpeed:float;

//declare flowers for control flow triggers
var flower01:boolean;
var flower02:boolean;
var flower03:boolean;
var flower04:boolean;
var flower05:boolean;
var flower06:boolean;
var flower07:boolean;
var flower08:boolean;
var flower09:boolean;


//enumeration defining proper sequence 
enum FlowerState { None, Alpha, Beta, Gamma, Delta, Epsilon, Zeta, Theta, Eta, Mu, Done };


//enumeration state
var currentState:FlowerState;

//timer variables
var startTimer:float;

//Game Object state indicator visual queue green lights and final objective successful
var indicators:GameObject[];


var stateSpaceshipAnimator:Animator;
var stateObjects:GameObject[];

//error indicator if proper sequence is not followed
var fsmError:boolean;

//Button presses from other functions
var leftDown:boolean;
var rightDown:boolean;
var thrustDown:boolean;
var engageDown:boolean;


//Audio Clips
var ThrustSound:AudioClip;
var LionSound:AudioClip;
var PlanetVisit:AudioClip;
var ErrorFsm:AudioClip;

function Start () {
    pollinEmitter.Stop();
//set currentState
currentState = FlowerState.None;
stateSpaceshipAnimator.Play("StateMachineSpaceCraftIdle");

}
//reset indicator array
function resetIndicator()
{
    for (var i:int = 0; i<indicators.Length; i++)
    {
        currentState = FlowerState.None;
        indicators[i].SetActive(false);
    }
    for (i = 0; i<stateObjects.Length; i++)
    {
        stateObjects[i].renderer.material.color = Color.white;
        //stateObjects[10].renderer.material.color = Color.red;
    }
}


function Update () {
//moving left and right, horizontally, will rotate our Bee 
var h = Input.GetAxis("Horizontal");

if(leftDown)
    h = 1.0f;
if(rightDown)
    h = -1.0f;

//moving vertical we only need to press up
var v = Input.GetButton("Vertical");
//var l = Input.GetButton("Left");
//var r = Input.GetButton("Right");

//controller button A = 0
var a = Input.GetButton("ctrlAgreen");

//controller button X = 2
var x = Input.GetButtonDown("ctrlXblue");

//we'll rotate everytime we press horizontal
//delta time is the time between each update so there is no difference in speed
transform.Rotate(Vector3(0,0,h * Time.deltaTime * rotateSpeed));

//pressing the fly(vertical) button emit pollin
if(v || a || thrustDown)
{
    //play Thruster
    //audio.PlayOneShot(ThrustSound);
    
    if (pollinEmitter.isStopped)
    {
        pollinEmitter.Play();
    }
    
    //set to move at the same speed as the Bee
    //if (rigidbody.velocity.magnitude < maxSpeed)
        rigidbody.AddForce(transform.up * Time.deltaTime * fly);
    
    //Play sound when flying other wise stay silent ** until we chose a great idle sound
    if(!audio.isPlaying)
    {
        audio.Play();
    }
}
else
{
    if(audio.isPlaying)
    {
        audio.Stop();
    }
    pollinEmitter.Stop();
    //rigidbody.velocity = Vector3.zero;
}
    
    //if you press the spacebar the timer will start to determine how long you must remain on the asteroid(flower)
    if (Input.GetKeyDown(KeyCode.Space) || x || engageDown){
        if(flower01 == true){
            currentState = FlowerState.Alpha;
            indicators[0].SetActive(true);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftAlpha");
            stateObjects[0].renderer.material.color = Color.green;
            stateObjects[9].renderer.material.color = Color.white;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(false);
            audio.PlayOneShot(PlanetVisit);
        }    
        if(flower02 == true && currentState == FlowerState.Alpha){
            currentState = FlowerState.Beta;
            indicators[1].SetActive(true);
            stateObjects[1].renderer.material.color = Color.green;
            audio.PlayOneShot(PlanetVisit);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftBeta");
        }else if (flower02 == true && !indicators[1].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftBetaWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);
                
        }
        if(flower03 == true && currentState == FlowerState.Beta){
            currentState = FlowerState.Gamma;
            indicators[2].SetActive(true);
            stateObjects[2].renderer.material.color = Color.green;
            audio.PlayOneShot(PlanetVisit);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftGamma");
        }else if (flower03 == true && !indicators[2].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftGammaWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);    
        }
        
            
        if(flower04 == true && currentState == FlowerState.Gamma){
            currentState = FlowerState.Delta;
            indicators[3].SetActive(true);
            stateObjects[3].renderer.material.color = Color.green;
            audio.PlayOneShot(PlanetVisit);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftDelta");
        }else if (flower04 == true && !indicators[3].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftDeltaWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);    
        }
        if(flower05 == true && currentState == FlowerState.Delta){
            currentState = FlowerState.Epsilon;
            indicators[4].SetActive(true);
            stateObjects[4].renderer.material.color = Color.green;
            audio.PlayOneShot(PlanetVisit);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftEpsilon");
        }else if (flower05 == true&& !indicators[4].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftEpsilonWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);    
        }
        if(flower06 == true && currentState == FlowerState.Epsilon){
            currentState = FlowerState.Zeta;
            indicators[5].SetActive(true);
            stateObjects[5].renderer.material.color = Color.green;
            audio.PlayOneShot(PlanetVisit);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftZeta");
        }else if (flower06 == true&& !indicators[5].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftZetaWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);    
        }
        if(flower07 == true && currentState == FlowerState.Zeta){
            currentState = FlowerState.Theta;
            indicators[6].SetActive(true);
            stateObjects[6].renderer.material.color = Color.green;
            audio.PlayOneShot(PlanetVisit);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftTheta");
        }else if (flower07 == true&& !indicators[6].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftThetaWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);    
        }
        
        if(flower08 == true && currentState == FlowerState.Theta){
            currentState = FlowerState.Eta;
            indicators[7].SetActive(true);
            stateObjects[7].renderer.material.color = Color.green;
            audio.PlayOneShot(PlanetVisit);
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftEta");
        }else if (flower08 == true && !indicators[7].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftEtaWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);    
        }
        if(flower09 == true && currentState == FlowerState.Eta){
            currentState = FlowerState.Mu;
            indicators[8].SetActive(true);
            indicators[9].SetActive(true);
            stateObjects[8].renderer.material.color = Color.green;
            audio.PlayOneShot(LionSound);
                
            //Application.LoadLevel("MainMenu");
            //audio.Play();
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftMu");
        }else if (flower09 == true && !indicators[8].active){
            //stateSpaceshipAnimator.Play("StateMachineSpaceCraftMuWRONG");
            audio.PlayOneShot(ErrorFsm);
            resetIndicator();
            stateObjects[9].renderer.material.color = Color.red;
            stateObjects[9].transform.GetChild(0).gameObject.SetActive(true);    
        }        
                    
    }

}

//entering trigger
function OnTriggerEnter(col:Collider){
    //Debug.Log("Entering " + col.gameObject.name);
    
    //hit collider 
    if (col.gameObject.name.Contains("alpha"))
    {
        flower01 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("beta"))
    {
        flower02 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("gamma"))
    {
        flower03 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("delta"))
    {
        flower04 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("epsilon"))
    {
        flower05 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("zeta"))
    {
        flower06 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("theta"))
    {
        flower07 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("_eta"))
    {
        flower08 = true;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("mu"))
    {
        flower09 = true;
    }
}

//leaving trigger
function OnTriggerExit(col:Collider){
    //Debug.Log("Exiting " + col.gameObject.name);
    
    //hit collider 
    if (col.gameObject.name.Contains("alpha"))
    {
        flower01 = false;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("beta"))
    {
        flower02 = false;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("gamma"))
    {
        flower03 = false;
    }
    //hit collider 
    if (col.gameObject.name.Contains("delta"))
    {
        flower04 = false;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("epsilon"))
    {
        flower05 = false;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("zeta"))
    {
        flower06 = false;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("theta"))
    {
        flower07 = false;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("_eta"))
    {
        flower08 = false;
    }
    
    //hit collider 
    if (col.gameObject.name.Contains("mu"))
    {
        flower09 = false;
    }
}

Main Menu/Complete Script

#pragma strict

function Start () {
    
}

function Update () {
    //Load Demo
    if (Input.anyKeyDown){
            Application.LoadLevel("leo_galaxy");
    }    

}

ScreenWrap Script

#pragma strict
var wrap:Vector2;
var wrapScreenMax:Vector2;

function Awake () {
    //wrap = Vector2 (Camera.main.GetScreenWidth.width - (Screen.width *1.5),Screen.height - (Screen.height *1.5));
    //wrapScreenMax = Vector2 (Screen.width - (Screen.width * 0.5),Screen.height - (Screen.height *0.5));
    var wrap:Vector3=Camera.main.ScreenToWorldPoint(Vector3(0,0,Camera.main.transform.position.y));
    wrap=Vector3(wrap.x-1,wrap.z-1);
    var wrapScreenMax:Vector3=Camera.main.ScreenToWorldPoint(Vector3(Screen.width,Screen.height,Camera.main.transform.position.y));
    wrapScreenMax=Vector3(wrapScreenMax.x+1,wrapScreenMax.z+1);
}

function Start () {

}

function Update () {
    //wrap sceen on x axis
    if(transform.position.x > wrapScreenMax.x){
        transform.position.x=wrap.x;
    }
    if(transform.position.x < wrap.x){
        transform.position.x=wrapScreenMax.x;
    }
    //wrap screen on y axis
    if(transform.position.z > wrapScreenMax.y){
        transform.position.z=wrap.y;
    }
    if(transform.position.z < wrap.y){
        transform.position.z=wrapScreenMax.y;
    }
    
}

function OnDrawGizmosSelected () {
        // Display the boundry for wrap when gameObject selected
        Gizmos.color = Color.red;
        Gizmos.DrawLine (Vector3 (wrap.x,1,wrap.y), Vector3 (wrapScreenMax.x,1,wrap.y));
        Gizmos.DrawLine (Vector3 (wrap.x,1,wrap.y), Vector3 (wrap.x,1,wrapScreenMax.y));
        Gizmos.DrawLine (Vector3 (wrapScreenMax.x,1,wrapScreenMax.y), Vector3 (wrap.x,1,wrapScreenMax.y));
        Gizmos.DrawLine (Vector3 (wrapScreenMax.x,1,wrapScreenMax.y), Vector3 (wrapScreenMax.x,1,wrap.y));

    }

Right Button Script

#pragma strict


var ship:GameObject;

function Start () {

}

function Update () {

}

function OnMouseDown(){
    ship.GetComponent(beeFly).rightDown = true;
}

function OnMouseUp(){
    ship.GetComponent(beeFly).rightDown = false;
}

Movement Script

#pragma strict

var ship:GameObject;


var leftDown:boolean;
var rightDown:boolean;
var thrustDown:boolean;
var leftDownCheck:boolean;
var rightDownCheck:boolean;
var thrustDownCheck:boolean;
var check:boolean;

function Start () {
    leftDown = false;
    leftDownCheck = false;
    rightDown = false;
    rightDownCheck = false;
    thrustDown = false;
    thrustDownCheck = false;
    
    check = false;
    
}

function Update () {
    if(leftDown)
        ship.GetComponent(beeFly).leftDown = true;
        
    if(rightDown)
        ship.GetComponent(beeFly).rightDown = true;
        
}

function OnMouseUp(){
    check = true;
}

function OnGUI () {
        if(check)
            {
                ship.GetComponent(beeFly).leftDown = false;
                ship.GetComponent(beeFly).rightDown = false;
            }
        
        
        if (GUI.Button (Rect (10,100,150,100), "Left"))
        {
            leftDown = true;
        }    
                
        if (GUI.Button (Rect (110,100,150,100), "Right"))
        {
            
            rightDown = true;
        }
}

Controller script

#pragma strict


var ship:GameObject;

var isLeft:boolean;
var isRight:boolean;
var isThrust:boolean;
var isEngage:boolean;

function Start () {

}

function Update () {

}

function OnMouseDown(){
    if(isLeft)
        ship.GetComponent(beeFly).leftDown = true;
    if(isRight)
        ship.GetComponent(beeFly).rightDown = true;
    if(isThrust)
        ship.GetComponent(beeFly).thrustDown = true;
    if(isEngage)
        ship.GetComponent(beeFly).engageDown = true;
}

function OnMouseUp(){
    if(isLeft)
        ship.GetComponent(beeFly).leftDown = false;
    if(isRight)
        ship.GetComponent(beeFly).rightDown = false;
    if(isThrust)
        ship.GetComponent(beeFly).thrustDown = false;
    if(isEngage)
        ship.GetComponent(beeFly).engageDown = false;
}

Left Button Script

#pragma strict

var ship:GameObject;

function Start () {

}

function Update () {

}

function OnMouseDown(){
    ship.GetComponent(beeFly).leftDown = true;
}

function OnMouseUp(){
    ship.GetComponent(beeFly).leftDown = false;
}

References

Fishwick, Dr. Paul(2012). “Paul Fishwick”.

Retrieved from www.cise.ufl.edu/~fishwick/Welcome.html

Fishwick, Dr. Paul(2014). “Creative Automata”.

Retrieved from http://www.creative-automata.com