Rafael Fajardo
Director, SWEAT collaborative
Associate Professor,
Emergent Digital Practices
University of Denver


Projects: Generic Game Engine Source Code

<?xml version="1.0" encoding="UTF-8"?>
<widget version="1.0">

/*This work is licensed under the Creative Commons Attribution-ShareAlike License. 
  To view a copy of this license, 
    visit http://creativecommons.org/licenses/by-sa/2.0/ 
    or send a letter to Creative Commons, 
      559 Nathan Abbott Way, Stanford, California 94305, USA.

//Coding work done by Chad Schmidt (schlitzNTL@netscape.net)
//Original concept for a tile based game engine utilizing files
//as scenes(worlds) for the game created by Andrew Woolridge

							//Sets up the widget window to hold the game (leaves it transparent by default)

<window title="Generic Game Engine 1.0">

							//This image is the grayish background for the entire game
<image src="images/chrome/bevelBackground.png">
							//*I use this preference to actually store saved data from scenes so that each scene remembers
							//*how it was left
<preference name="saveStates">

/*This section of code deals with the action buttons available to the user*/

							//This button allows the user to move upwards
<image src="images/chrome/upArrow.png">			//This is where the button image is
  <name>up</name>					//This is the name of the image(used for referring to the image)
  <hOffset>300-(width/2)</hOffset>			//This is what determines the horizontal position of the image
  <vOffset>367</vOffset>				//This is what determines the vertical position of the image
  <zOrder>500</zOrder>					//This determines the zOrder of the image(higher above lower)
  <onMouseUp>moveUp()</onMouseUp>			//This tag calls the slideUp() function when the user clicks on the image
							//The next few images follow the same basic ideas as the comments above
							//This button allows the user to move down
<image src="images/chrome/downArrow.png">

							//This button allows the user to move right
<image src="images/chrome/rightArrow.png">

							//This button allows the user to move left
<image src="images/chrome/leftArrow.png">

							//This button allows the user to plant a coffee tree
<image src="images/chrome/actionA.png">

							//This button allows the user to harvest coffee beans from a coffee tree
<image src="images/chrome/actionB.png">

/*This section of code deals with the text based stats that appear on the bottom of the game*/

							//This text deals with the players score during the game
  <data>Score: 0</data>					//The Data is a text string and can be refrenced and changed later in the code
  <size>10</size>					//The Size determines the text size of the string displayed
  <hOffset>12</hOffset>					//This determines the horizontal position of the text
  <vOffset>379</vOffset>				//This determines the vertical position of the text
  <zOrder>506</zOrder>					//This determines which image will show above the others(higher above lower)
  <color>#FFCC00</color>				//This determines the color of the text
  <name>scoreText</name>				//The name is what can be used to refrence this variable later on (ex. scoreText.data)
							//The following text variables follow the same basic ideas as the commetns above
							//This text displays the players current life
  <data>Life: 1</data>

							//This is actually a button that allows the player to see their inventory
							//This text allows the user to see how many coffee seeds they still have
  <data>Seeds: 0</data>
							//This text allows the user to see how many coffee beans that they have harvested
  <data>Beans: 0</data>

/*The onLoad trigger is fired when the movie first loads.  This is where I have stored all of my functions that enable the*/
/*gameplay as well as the functions that load all of the data into the game*/
<action trigger="onLoad">

/*This section of code is where I define all of my variables*/
var theArray = [];		//This array stores the map tiles used to create the background of the game
var theInventory = [];		//This array stores the inventory objects that Juan may pick up on his travels
var plants = [];		//This array is used to store the coffee trees and there associated data
var saveData = [];		//THis array is used to store data from the saveStates prefrences to load saved states
var tileSize = 32;		//this variable defines in pixels the width/height of the tiles
var cols = 18;			//How many tiles wide the screen will be (18*32)=576
var rows = 11;			//How many tiles high the screen will be (11*32)=352
var hOff = 12;			//The hOff is the horizontal offset that the main game window will have from the application window
var vOff = 12;			//The vOff is the vertical offset that the main game window will have from the application window
var charDir = "right";		//The charDir is a variable used to keep track of which way the character is facing
var life = 1;			//Life is a variable used to keep track of the character's remaining life
var score = 0;			//Score is a variable used to keep track of the users score
var beans = 0;			//Beans is a variable used to keep track of the users number of coffee beans harvested
var seeds = 0;			//Seeds is a variable used to keep track of the number of seeds the character has left
var animCheck = false;		//The startTimer is used as a check as so that the program doesn't try and access the characters image before
				//the character is on screen
var gameBegin = false;		//*This variable makes sure that the clearData() function is not called as the first scene is loaded(it would
				//*cause errors)
var lastScene = ""		//*This variable is used to let the saveState() knows which scene it is saving data for
				//startScene is a variable that stores the path to the first scene loaded in the game
var startScene = "scenes/outsideHouse.gges"
				//Tiles is a multi-dimensional array used to store the path to image files that the map in the world
				//text files reference.  The second item is used for whether or not the tile blocks the characters
				//movements, true it blocks movement, false it allows movement
var tiles = {			
	d: ["images/tiles/dirt.png", true],
	g: ["images/tiles/grass.png", false],
	w: ["images/tiles/wall.png", true],
	f: ["images/tiles/floor.png", false]

/*This section of codes loads up the splash screen before the game is played*/
function startScreen(){
  backImage= new Image();				//This creates a new image onto the window
  backImage.src = "images/chrome/maskTile.png";	//.src defines the path to the image file
  backImage.hOffset = hOff;				//Once again, the horizontal position
  backImage.vOffset = vOff;				//The vertical position of the image
  backImage.width = (tileSize*cols);			//This alters the natural width of the image
  backImage.height = (tileSize*rows);			//This alters the natural height of the image
  backImage.zOrder = 2;					//The zOrder of the image determines whether it is displayed
  							//on top or below other images (lower is below higher)

  startButton = new Image();				//This is the startButton
  startButton.src = "images/chrome/startButton.png";
  startButton.hOffset = hOff+((cols*tileSize)/2)-25;
  startButton.vOffset = vOff+((rows*tileSize)/2);
  startButton.zOrder = 3;
  startButton.onMouseUp = "fadeOut();readFile(startScene);";	//This sets up so that the reaFile() function is called when
  							//the user clicks on the image.

  logoImage = new Image();				//This is the the SWEAT logo
  logoImage.src = "images/chrome/titlePlate.png";
  logoImage.hOffset = hOff+((cols*tileSize)/2)-125;
  logoImage.vOffset = startButton.vOffset-startButton.height-tileSize-50;
  logoImage.zOrder = 4;

/*This function fades out the main menu screen*/
function fadeOut(){
  logoImage.fade(255, 0, 80);				//This line fades the logo image from full visible to invisible
  logoImage.zOrder=0;					//The image is then placed at the lowest possible zOrder so that it will not be seen
  startButton.fade(255, 0, 80);
  backImage.fade(255, 0, 80);

/*This function reads all of the data out of a world text file and stores it for future use, as well as calls the*/ 
/*functions used to draw the background, characters, and other images*/
function readFile(newScene){
  var tempSaveArray = new Array();
  if(gameBegin == true){				//*If gameBegin is true (if this isn't the first run of loadFile())
    saveState();					//*This function will save the state the previous scene was left in
    clearData();					//*This function clears all the data from the previous loadFile()
  							//*This next line is used twofold, first by trying to parse the saveStates using the
							//*current scene we can check later to see if we have a saved state for it, and
							//*also begins like when the events are read out of a file below to parse out
							//*everything but the needed data
  saveData = preferences.saveStates.value.split("<" + newScene + ">");
  if(saveData[1] != undefined){				//*This checks to see if the newScene was parsed out, which means save data is available
  							//*This next line parses out the rest of the unecessary data in the saved states
    tempSaveArray = saveData[1].split("</" + newScene + ">");
  charDir="right";					//Sets up Juan at a default right facing when entering a new world
  lastScene = newScene;					//*This sets lastScene equal to newScene in prep for the next time a new file is read
  var scenePath = runCommand("cat " + newScene);	//This variable stores the full path to the text world text file to be loaded
  var mapArrayTemp = new Array();			//These two arrays are used to splice out the map section of the world text file from
  var mapArrayFinal = new Array();			//the rest of the text file
							//These next two lines splice out the map section of the world text file
  mapArrayTemp = scenePath.split("<map>") 
  mapArrayFinal = mapArrayTemp[1].split("</map>")

  							//These next two lines splice out the events section of the world text file
  eventArrayTemp = scenePath.split("<events>");
  eventArrayFinal = eventArrayTemp[1].split("</events>");
  eval(eventArrayFinal[0]);				//The eval line creates a variable out of the eventMap array set up in the file

  							//These next two lines splice out the characters section of the world text file
  characterArrayTemp = scenePath.split("<characters>");
  characterArrayFinal = characterArrayTemp[1].split("</characters>");
  eval(characterArrayFinal[0])				//The eval line creates a variable out of the characters array set up in the file

  							//NOTE: The splicing is accomplished by first cutting out everything before the map
							//tag storing the rest in an array and then cutting out everything after the map tag
							//in that array leaving only stuff between the map and map tags, events and
							//characters are accomplished in the same way.
							//*This next if statment block loads saved data for events over the ones read out of the
							//*file so that the game remembers for example the power ups you have picked up and
							//*doesn't put them in the game every time you reload a scene
  if(tempSaveArray[0] != undefined){			//*This if check actually checks to see if there is save data available
 							//*These next two lines splice out everything but the actual data in the save states
  							//*you see the save data is formatted like the files, so I do basically the same thing here
    eventsSavedArray = tempSaveArray[0].split("<events>");
    eventsSavedArrayTwo = eventsSavedArray[1].split("</events>");
    eval(eventsSavedArrayTwo[0])			//*This line creates a variable(eventArray) out of the text data
    gameBegin=true;					//*From now on this will make sure that all the clear data function is called

  setupGame(mapArrayFinal[0]);				//This calls the setupGame function which involves drawing everything to the screen

/*VERSION 1.1*/
/*This function saves the details of the current scene for use if the user returns to it*/
function saveState()
var i = 0;						//*Purely an iterator variable for the loops below
  tempArray = new Array();				//*This creates a new array to help figure out if the scene being saved alread
							//*has saved data in memory
  tempArrayTwo = new Array();				//*This array does the same thing

  							//*This next line begins to parse out save data for the scene to be saved if it exists
  tempArray = preferences.saveStates.value.split("<" + lastScene + ">");
  if(tempArray[1] != undefined){			//*If the above statement found old save data then the next group of statements runs
  							//*This next statement parses out the save data of only the scene to be saved
    tempArrayTwo = tempArray[1].split("</" + lastScene + ">")
    tempArrayTwo[0]="<" + lastScene + ">\n";	//*The following statements that begin with tempArrayTwo= or += all are designed to save
    tempArrayTwo[0]+="<events>\n"			//*the data in the eventArray to the save file in the same exact format as the format
    tempArrayTwo[0]+= "eventArray = ["			//*of the .gges files.
    for(i=0; i < eventArray.length; i ++){		//*If you would like to see the format of the data saved then uncomment (delete the "//")
    tempArrayTwo[0]+="\n{\nhloc: "			//*in front below this group of statements that read "print(tempArray[0] + tempArr..."
     tempArrayTwo[0]+=eventArray[i].hloc		//*and turn the debug option to on up top of the code.
      tempArrayTwo[0]+=",\nvloc: ";			//*NOTE: the for loop above is designed so that the entire eventArray of the scene to
      tempArrayTwo[0]+=eventArray[i].vloc		//*be saved is run through and stored, however, at the top and bottom of this section
      tempArrayTwo[0]+=",\nhOff: "			//*are parts not in the loop specifically because they only written once...at the beginning
      tempArrayTwo[0]+=eventArray[i].hOff;		//*or end of the save data
      tempArrayTwo[0]+=",\nvOff: "
      tempArrayTwo[0]+=eventArray[i].vOff		//*ALSO NOTE: This section of code overwrites all old save data for the scene, the sction
      tempArrayTwo[0]+=",\neventImagePath: \""		//*below this deals with writing new save data
      tempArrayTwo[0]+="\",\neventCode: \""		//*ALSO NOTE: If you didn't know "\n" causes a carraige return(a new line)
      tempArrayTwo[0]+="\",\neventImage: "
      if(eventArray[i+1] != undefined){			//*This line checks to see if there is an event after the one being written
        tempArrayTwo[0]+=",\n";				//*If there is an event next this writes a comma to seperate the two events
        tempArrayTwo[0]+="\n]\n";			//*If there is no next event this writes a "]" to signal the end of the event data
    tempArrayTwo[0]+="</" + lastScene + ">";
    							//*This next line writes everything back into the saveStates, tempArray[0] writes all
						       	//*of the saved scenes before the one being saved, tempArrayTwo[0] writes the scene
							//*being saved, tempArrayTwo[1] writes all the scenes after the current one.  The
							//*reason for re-writting all of the scenes is because we overwrite the entire save data
							//*and have to re-write all the saved data that wasn't changed.	
    preferences.saveStates.value=tempArray[0] + tempArrayTwo[0] + tempArrayTwo[1];
    //print("Sec1:\n" + tempArray[0] + "\nSec2:\n" + tempArrayTwo[0] + "\nSec3:\n" + tempArrayTwo[1]); 
							//*This next section of code does the same thing as the section above, however this only
							//*runs if there is no old save data for the scene to be saved
  preferences.saveStates.value+="<" + lastScene + ">\n";
  preferences.saveStates.value+="eventArray = ["
    for(i=0; i < eventArray.length; i ++){
      preferences.saveStates.value+="\n{\nhloc: "
      preferences.saveStates.value+=",\nvloc: ";
      preferences.saveStates.value+=",\nhOff: "
      preferences.saveStates.value+=",\nvOff: "
      preferences.saveStates.value+=",\neventImagePath: \""
      preferences.saveStates.value+="\",\neventCode: \""
      preferences.saveStates.value+="\",\neventImage: "
      if(eventArray[i+1] != undefined){
    preferences.saveStates.value+="\n</" + lastScene + ">\n";
    							//*NOTE: Although there is very many other ways to fake saving data I chose this way for a
    							//*few reasons, one is to limit impact on the speed, in a massive game if you, for instance
							//*like I do with the plants just store data in a big array and only display the events in
							//*a given scene it means the processor has to run through a huge array, this way its just
							//*a quick refrence to the preferences.  Also it limits any more hardships on non-programmers
							//*and creates greater possibility and ease for future updates.  And of course gives me a
							//*bit of training on saving to preferences for future full Save Game features :)

/*This function cleans all of the data from previous scenes out of the system so it doesn't cause any problems*/
function clearData(){
  var i = 0;
  length = eventArray.length				//If I used array.length in the for loop as items were popped of the length would change
  							//causing the loop to stop prematurely, so this variable is used to store the original
							//length of the array
  for(i=0; i < length; i ++){			//This loop will run through the entire eventArray
  eventArray.pop();					//pop() removes the last item in the array, coupled with the loop, the entire array gets

  length = characters.length  				//The next three loops follow the same basic principle as the above arrays
  for(i=0; i < length; i ++){

  for(i=0; i < length; i ++){

/*This function is merely an organizer function which makes calls to a group of other functions*/
function setupGame(mapText){
  setupPlants();					//NOW WITH PLANTY GOODNESS!!
  updateNow();						//updateNow() is a built in function which forces the window to redraw itself
  animCheck=true;					//Since the character is now on screen startTimer is made true to start the
  							//characters animation

/*This function reads through the map data and draws the background map to screen*/
function setupMap(mapText){
  var curPosition = 0;					//This variable is used for tracking the current position within the array with
							//the map data
  var curChar = 'a';					//This variable is used to store a character from the mapText array
  var i=0;						//Purely a looping iterator variable
  var j=0;						//Purely a looping iterator variable
  mapText = mapText.replace(/\s/gi,'');			//Truthfully...no clue, but it does something
  for(i=0; i < rows; i ++){				//these loops set up the 2-D grid and place the 32x32 map tiles in their place 
    for(j=0; j < cols; j ++){
      curPosition = (j+(cols*i));			//This updates the current position on the grid
      curChar = (mapText.charAt(curPosition));		//This pulls the character out of the mapText array
      theArray[curPosition] = new mapTile(curChar);	//this creates a new mapTile object based on the character
      							//The next three lines deal with the placement and zOrder of the image
      							//The next line sets the images collision variable based on the map tiles array in the
							//variables section of the code

/*This function creates a mapTile object which stores all of the individual tiles data*/
function mapTile(imgSource){
  this.collision=false;					//This establishes a collision variable for the object
  this.events="";					//This establishes and events parameter for the object
  this.parameters="";					//This establishes a parameters variable for the object
  this.tileImagePath=tiles[imgSource][0];		//This establishes a variable which stores the path to the image
  this.tileImage = new Image();				//This line actually creates an image object within the mapTile object
  this.tileImage.src = this.tileImagePath;		//This defines what image file the new Image will display

/*This function sets up the events, their placement and their eventCode, or what actions they will take*/
function setupEvents(){
  var newEvent;						//This line creates a new variable which will be used for transfer of the eventCode
  var i = 0;						//Purely a loop iterator variable

  for(i=0; i < eventArray.length; i ++){		//This loop runs through the eventArray array created by the eval() line before
  if(eventArray[i].hloc != null){			//*This if statment checks to see if hloc is null (killed events have their hloc changed
  							//*to "null")
  							//The next line stores the position on the map array where the event will appear
      newEvent = theArray[eventArray[i].hloc+(cols*eventArray[i].vloc)];
      newEvent.events = eventArray[i].eventCode;	//The eventCode from the eventArray array is stored in the map array's events variable
      eventArray[i].eventImage = new Image();		//Creates a new image to represent the event or object causing the event
    							//The next line tells the image which image file to use
      eventArray[i].eventImage.src = eventArray[i].eventImagePath;
    							//These next three lines deal with the images placment and zOrder
      eventArray[i].eventImage.zOrder = 200+i;			
      eventArray[i].eventImage.hOffset = (tileSize  * (eventArray[i].hloc + eventArray[i].hOff)) + hOff;
      eventArray[i].eventImage.vOffset = (tileSize  * (eventArray[i].vloc + eventArray[i].vOff)) + vOff;

/*This function draws the character to the screen*/
function setupCharacter(){
  var i = 0;						//Purely a loop iterator variable
  							//NOTE: This game as setup has only one main character, but can be easily modified
							//to have multiple main characters
  for(i=0; i < characters.length; i ++){
    characters[i].image = new Image();			//Creates a new image to display the character with
    characters[i].image.src = characters[i].imageRight;	//Tells the image which image file to use
    							//The following three lines determine the characters placement and zOrder
    characters[i].image.hOffset = (tileSize  * characters[i].hloc) + hOff; 
    characters[i].image.vOffset= (tileSize  * characters[i].vloc) + vOff;
    characters[i].image.zOrder = 300;

/*VERSION 1.1*/
/*This function runs through the plant array when a new scene is loaded and displays plants that are in the scene and hides the rest*/
function setupPlants(){
  for(i=0; i < plants.length; i ++){			//*This runs the loop through the entire plants array

  if(plants[i].myScene == lastScene){			//*lastScene is deceptive because it now has the newScene(the current scenes) data in it
 							//*and it checks to see if the plants myScene variable is the same as the current scene 
      plants[i].plantImage.opacity=255;			//*This line makes a plant fully visible
      plants[i].plantImage.opacity=0;			//*This makes a plant invisible(because it doesn't exist ont his scene...really)

/*The next for functions deal with what happens when one of the four directional buttons is pressed*/
function moveLeft(){
if(gameBegin == true){					//*This if statement checks to see if the game has begun yet 
    if(charDir == "left"){				//The first if checks to see if the character is already facing the right direction
      characters[0].hloc -=1;				//changes the hloc variable so that on the grid the character has moved left one space
      if(!checkCollision()){				//Then it checks to make sure the space the characterjust moved into is a passable surface
        updatePosition();				//Calls the updatePosition function to redraw the character
        checkEvent();					//Calls the checkEvents function to see if the character his an event space
      }else{						//If the character can't move into the next space
        characters[0].hloc +=1;				//The character is moved back into its original position
    }else{						//If the character isn't facing to the left
      charDir = "left"					//Changes the charDir variable to reflect that the character is turning to the left
      characters[0].image.src = characters[0].imageLeft	//Changes the image file to represent the character facing left
      updatePosition();					//Calls the updatePosition to redraw the character on the screen
							//NOTE: The following three functions are mirrors of the first function, the same comments
							//apply to them
function moveRight(){
  if(gameBegin == true){							
    if(charDir == "right"){
      characters[0].hloc +=1;
        characters[0].hloc -=1;
      charDir = "right";
      characters[0].image.src = characters[0].imageRight
function moveUp(){
  if(gameBegin == true){
    if(charDir == "up"){
      characters[0].vloc -=1;
        characters[0].vloc +=1;
      charDir = "up";
      characters[0].image.src = characters[0].imageUp
function moveDown(){
  if(gameBegin == true){
    if(charDir == "down"){
      characters[0].vloc +=1;
        characters[0].vloc -=1;
      charDir = "down";
      characters[0].image.src = characters[0].imageDown

/*This function checks to see whether terrain the character is walking into is passable*/
function checkCollision(){
							//The next line checks the collision variable of the mapTile in the map array and returns
							//true for impassible and false for impassible
  return theArray[characters[0].hloc+(cols*characters[0].vloc)].collision

/*This function checks to see if the player has run into an event object and then executes the code if the character has*/
function checkEvent(){
							//The next line creates a variable pointing to the proper place in the map array
  var eventPos = theArray[characters[0].hloc+(cols*characters[0].vloc)];
  if(eventPos.events != null){				//If there is an event code
    eval(eventPos.events);				//The event code is executed (Functions can be called, alerts pooped up, etc.)

/*This function redraws the image of the character into its new position*/
function updatePosition(){
							//The next two lines reposition the character on the screen
  characters[0].image.hOffset = (tileSize  * characters[0].hloc) + hOff; 
  characters[0].image.vOffset= (tileSize  * characters[0].vloc) + vOff;
  updateNow();						//This forces an update of the widget window

/*This function eliminates an event from the world*/
function killEvent(index){
							//The next line replaces the event image with a blank PNG, effectively erasing it
  eventArray[index].eventImage.src = "images/tiles/empty.gif"
  eventArray[index].eventCode=""			//This changes the event code in the eventMap to nothing, eliminating the event
      							//The next line erases the event code from the map so it won't fire again
  eventArray[index].hloc=null;				//*Changing the hloc to null is how the game tells the setupEvents(0 function to ignore
  							//*this event

/*This function updates the life counter and life variable*/
function updateLife(amount){
life += amount;						//Adds the amount(+ or -) of life recieved into the characters current life
if(life > 5){					//Makes sure the characters life doesn't go higher than the max (5)
    life = 5;
  if(life < 0){					//Makes sure that the characters life doesn't go below zero
    life = 0;
  lifeText.data = "Life: " + life;			//Updates the text representation of the life on screen

/*This function updates the score */
function updateScore(amount){
  score += amount;					//Adds the amount(+ or -) of points recieved to the current count
  scoreText.data="Score: " + score;			//Updates the text representation to accurately reflect the new score

/*Creates a new object which will be placed into the inventory*/
function inventoryItem(){
  this.name = "nothing";				//Creates a variable that keeps the items name
  this.icon = "images/tiles/empty.png";			//Creates a variable which stores a link to the image file associated with the item
  							//NOTE: The image file is not currently implemented
  this.value = 0;					//Creates a varaible that stores the value of the item

/*This function will add an item into the characters inventory*/
function addToInventory(name, icon, value){
  var tempItem = new inventoryItem()			//Creates a variable to store the inventory item in and creates a new inventoryItem
  tempItem.name = name;					//Sets the name of the item based on the data recieved
  tempItem.icon = icon;					//Sets the image file associated with the object
  tempItem.value = value				//Sets the value of the object 
  theInventory[theInventory.length] = tempItem 		//Finally the item is plopped into the inventory array

/*This function is for displaying the inventory (Called when the user clicks on the Items text)*/
function displayInventory(){
  var tempString = ""					//Creates a temporary string variable to store all of the items data
							//The next loop runs through the inventory adding each items name and value to the 
							//string so that when displayed it will consist of the entire inventory
  for(i=0; i < theInventory.length; i ++){
    tempString += tempString+ theInventory[i].icon + "  Item: " + theInventory[i].name + "  Value: " + theInventory[i].value + "\n";
  alert("INVENTORY:\n"+tempString);			//This line displays the inventory as an alert box

/*This function allows the character to plant a tree on the map*/
function plant(){
  if(gameBegin == true){				//This if statement makes sure that the game has begun before the user tries to plant
    if (seeds>0){					//If the user has seeds left then
      plants[plants.length] = new tree();		//A new coffeeTree object is created and added to the end of the plants array
      seeds-=1;						//1 is subtracted from the number of the users seeds
      seedsText.data="Seeds: " + seeds;			//The seeds text is updated to reflect the new count of seeds left
    }else{						//If the user has no seeds
      alert('You have no Seeds!');			//Pops up an alert box telling the user they have no seeds

/*This function creates a coffeeTree object and positions it in its proper place*/
function tree(){
this.myScene = lastScene;				//*This variable keeps track of which scene the plant should show up in
  this.plantImage = new Image();			//Creates a new image to hold the coffe tree image
  this.plantImage.src = "images/tiles/plant0.png"	//This line shows the image where the coffee tree image file is
  this.hloc=characters[0].hloc;				//These two lines copy over the horizontal position and vertical position of the
  this.vloc=characters[0].vloc;				//character on the grid to the position of the tree on the grid

  							//The next line sets the horizontal position of the coffee tree image
  							//This next if block moves the trees position on the grid and image position left
							//or right one grid unit (32 pixels) dependent on the direction the character is
  if(charDir == "left"){
  }else if(charDir == "right"){
  							//This next if block moves the trees position on the grid and the image position up
						      	//or down one grid unit dependent on the direction the character is facing	
  if(charDir == "up"){
  }else if(charDir == "down"){

  this.iteration = 0					//This sets up a variable used to remember which growth step the tree is currently on

/*This function allows the character to chop down a coffee tree*/
function chop(){
  if(gameBegin == true){				//*This makes sure the user doesn't try to chop a tree before the game has begun
    var i = 0;						//Purely an lopp iterator variable
    var Hpos = characters[0].hloc;			//Creates a variable with the value of the characters current horizontal location
    var Vpos = characters[0].vloc;			//Creates a variable with the value of the characters current vertical location

    if(plants.length == 0){				//If there are no trees planted
      alert('Nothing to harvest');			//Pops up an alert telling the user there are no trees 
      }else{  						//If there are trees
      if (charDir == "left"){				//Finds if the character is turned left or right and then changes the Hpos accordingly
      }else if(charDir == "right"){
      if(charDir == "up"){				//Finds if the character is turned up or down and then changes the Vpos accordingly
      }else if(charDir == "down"){

      for(i=0; i < plants.length; i ++){		//The loop runs through all of the tree objects in the array
    							//The next line checks to see if the tree is next to the character in the direction
							//the character is facing
        if(plants[i].hloc == Hpos && plants[i].vloc == Vpos && plants[i].plantImage.opacity != 0){
          if(plants[i].iteration > 1){			//This line checks to make sure the tree is fully blooming
      							//The next line changes the image of a tree to an empty image
	    for(j=i; j < (plants.length-1); j++){	//This loop runs through the plants array
	      plants[j]=plants[j+1];			//Starting with the tree being chopped down it moves each tree down on the array
	  						//effectively erasing the cut down trees data and image
	    beans+=1					//Increases the amount of beans collected by 1
	    beansText.data = "Beans: " + beans;		//Updates the text representation of the beans the character has
	    plants.pop();					//Cuts of the last tree on the list because it has already been moved down to second
	  						//to last
							//The next line pops out an alert if the tree is not blooming yet
            alert('The coffee plant is not yet bearing fruit!')

/*This function allows an event or trigger to add seeds into the characters stash*/
function addSeeds(num){
  seeds=seeds+num;					//Adds the number of seeds recieved to the current number of seeds
  seedsText.data = "Seeds: " + seeds;			//Updates the text representation of the seeds

startScreen()						//This is the only actual action that takes place during the "onLoad" trigger and
							//it calls the splash screen
updateNow();						//This forces an update of the widget window, redrawing it

/*The onTimer trigger is fired everytime the .5 interval comes around, its used for tree growth and character animation*/
<action trigger="onTimer" interval=".5">
if(animCheck){						//if startTimer is true, which happens once the world text file is loaded
  if(charDir == "right"){				//Checks to see if the character is facing right
							//The next four lines check to see if the image file is the first or second animation
							//and then whichever it is it switches the characters animation file to the opposite
    if(characters[0].image.src == characters[0].imageRight){
      characters[0].image.src = characters[0].imageRightTwo
      characters[0].image.src = characters[0].imageRight
							//NOTE: The next 3 chunks of code are mirrors of this first chunk and the comments from
							//above are basically the same for the next chunks
  if(charDir == "left"){
    if(characters[0].image.src == characters[0].imageLeft){
      characters[0].image.src = characters[0].imageLeftTwo
      characters[0].image.src = characters[0].imageLeft

  if(charDir == "up"){
    if(characters[0].image.src == characters[0].imageUp){
      characters[0].image.src = characters[0].imageUpTwo
      characters[0].image.src = characters[0].imageUp

  if(charDir == "down"){
    if(characters[0].image.src == characters[0].imageDown){
      characters[0].image.src = characters[0].imageDownTwo
      characters[0].image.src = characters[0].imageDown
var i = 0;						//Purely an iterative variable
for(i=0; i < plants.length; i ++){
  if(plants[i].iteration == 2){				//If the plant is fully grown
    plants[i].iteration=3;				//Go to the 2nd animation in the fully grown animation
  							//And update the picture so that it represents the new image
    plants[i].plantImage.src="images/tiles/plant" + plants[i].iteration +".png";
  }else if(plants[i].iteration == 3){			//If the plant is fully grown and in the 2nd animation state
    plants[i].iteration=2;				//Change it back to the first animation state
  							//Update the image so that the plant will switch back to the 1st animation image
    plants[i].plantImage.src="images/tiles/plant" + plants[i].iteration +".png";
  }else{						//If the plant is not yet blooming
    plants[i].iteration+=1;				//Increase the iteration of the plant
  							//The next line changes the image file the plant points to
    plants[i].plantImage.src="images/tiles/plant" + plants[i].iteration + ".png";
updateNow();						//Forces an update of the widget window, redrawing the screen

/*The about-box is a pre-built Konfabulator function to display an about box :)*/