Thursday, 12 November 2015

IP3 User testing

As stated in the SoD, the testing session would let the user test separately the digital form of the product and the physical form of it.

Footage below shows the digital end testing

Users mostly have positive feedback to the digital form of the product. The concept is easy for them to understand. Most importantly, the hints provided on the screen would guide the user to guess the word instead of receiving the hints from the developer. Some users mentioned that, the digital form would be adequate to only be controlled by keyboard, instead of pushing "right" and "left" button to choose the letter. Also, almost all users indicated, the game would have more fun if there's more animation included in the prototype. One user also pointed out that, the game could be developed a multiple player mode for more players to play against each other. This concept has been considered long ago, but developer would more expect to see the idea of the concept. Therefore, multiplayer would be a nice add-on for the actual product.

Footage below shows the testing process of physical form

From the video, it could be shown that the pointer has been nearly broken. Although several testing has been done before the one inside the video, still the pointer was too easy to get damaged. The main reason for this the wires massively affects the spinning movement of the wheel. The wires were hard to move under the base as the old gaming console is hard to redesign. At this point, it was been realised that for the better performance of the prototype, a new base should be made. Another reason for the messy wires is that as the wheel is for spinning, while there's wire attached to the pointer, the spinning movement would twist the wires.
Users gave several suggestions to further develop the prototype. One user pointed out thati it worths a try to just switch the material of pointer and indicator. Specifically, make soft indicators and hard pointer. Another user informed the developer that it would be great if the chosen letter could be shown at the stage instead of in the console box. The initial purpose of the spinning wheel is that one indicator would be one letter to choose. However, as the wheel still could not accurately spin to each exact location, it might as well better to show the current letter on the screen to make the game more playable.

The user feedback shows that there are several improvement needs to make to the prototype, mostly regarding the accuracy of showing the letter. The most urgent development is to redesign the entire base, because the current development was largely limited by the base.





Saturday, 31 October 2015

Building of IP3's physical form

The major adjustment for the physical form is to redesign the pointers and indicators, while the spin wheel base remains unchanged (which is later proved should be as well..)

The nails for the indicator was changed from horizontal to vertical. See picture below: 

This reduced the damage caused by the sharp end of the nails to the soft pointer. As the pointer would remain using a soft one, it is important to redesign the set up of the indicators. However, this redesign caused another problem. Setting the nails vertically would reduce the stability of the nails itself. At the first testing by developer himself, the nails would be easily bend down by the pointer. In this case, duct tape were used to stabilise the nails on the wheel. Furthermore, foams were used on the wheels, which also went across the nails. This made the each nail has something to infill between them to make them hold against each other. Detailed shown below: 


In the IP2's feedback session, users mentioned that the spinning wheel is too unstable and it was easy to accidentally make a push action which inputs the letter. To solve this, foams were added under the bottom of the spinning wheel. This would not affect the spinning movement. Instead, this makes the spinning more stable, because the wheel would not be waggly as before.




*The testing session has been extended to 11 Oct after the scheduled session. See the next post for the testing result


Wednesday, 14 October 2015

Code development for IP3

To let the interaction of IP3 could be stood alone by users themselves without the interaction of the developer, an additional hinting box would be added to the main interface, specifically, below the game board. The hint for a guessing word would appear in the box when the word is randomly selected through the function. With the hints shown on the screen, the word guessing part of the game is fully finished.

First of all, a new array was made as a public variable for the latter inputting of the hints.

 public var wordArray: Array = new Array();  

After that, the existing word array was changed from
 public var words:Array =   
      [  
           "tiger",  
           "lion",  
           "deer",  
           "bear",  
           "horse",  
           "eagle"  
      ];  
to
 public var words: Array =   
      [  
           ["turtle", "I have four legs and a tail. I have no teeth. I can swim and dive underwater. I carry my house around with me. I am a..."],  
           ["bear", "I live in the woods. I'm very big and furry. I have a big nose, a little tail and four legs. I like to eat fish and berries.I am a..."],  
           ["whale", "I live in the ocean. I swim wherever I want. I sing to my family. I can breathe through a hole in the top of my head. I am a..."],  
           ["parrot", "I have a tail. I can fly. I'm covered in colorful feathers. I can whistle and I can talk. I am a..."],  
           ["horse", "I have four legs and a long tail. I eat oats and hay. I love to run fast. I let people ride on my back. I am a..."],  
           ["frog", "My skin is green and slippery. I have four legs and webbed feet. I eat bugs and little fish. I can swim under water and hop on land. I am a..."]  
      ];  

The reason for doing this is that each word would be matched from itself with its hints by calling words[x][0] and word[x][1] (x is the randomly chosen word).
*Alternative way of doing this is to create another array with only the hints, but eventually, this combining array method was used for the hinting system.

A new function called "setUpHints()" was added into the list of startGame function (underlined below)
 public function startGame() {  
           chooseWord();  
           //trace(wordArray[chosenWord]);  
           setUpInstructions();  
           setUpHints();  
           getGuess();  
      }  

Before adding the setUpHints function, a text box was added into the main stage, given the name "hintbox", which would be used as the elements to show the hints at the stage to users.


In the existing function setUpWordArray(), new variables for hints are required to be added into the function. Moreover, as the word array was changed, the existing variables also needs to be adjusted. This would ensure that the hints would show up to the stage with the matched randomly selected word.
Specifically, the code was adjusted from:

 public function setUpWordArray()  
      {  
           for(var k:int = 0; k < words.length; k++)  
           {  
                var thisWord = words[k];  
                var thisWordArray:Array = new Array();  
                for(var l:int = 0; l < thisWord.length; l++)  
                {  
                     thisWordArray.push(thisWord.charAt(l));  
                }  
                wordArray.push(thisWordArray);  
           }  
           trace(wordArray.length);  
      }  
to:
 public function setUpWordArray() {  
      for (var k: int = 0; k < words.length; k++) {  
           var thisWord = words[k][0];
           var thisHint = words[k][1];  
           var thisWordArray: Array = new Array();  
           var thisHintArray: Array = new Array();  
           var l: int = 0;  
           for (l; l < thisWord.length; l++) {  
                thisWordArray.push(thisWord.charAt(l));  
           }  
           wordArray.push(thisWordArray);  
           hintArray.push(thisHint);  
      }  
      trace(wordArray.length);  
 }  
The added and adjusted part has been highlighted by underlines. An additional line was added to push the hinting text into the hintArray which would be later pushed into the main stage.

Eventually, the setUpHint function was added:
 public function setUpHints() {  
      trace("Show hint");  
      hintbox.text = hintArray[chosenWord];  
 }  
This would push the hint to the main stage which is matched with the randomly chosen word.

Sunday, 11 October 2015

IP2 User testing

The user testing took place at the DP session on 7 Oct. Five users were asked to test the digital prototype and filled the feedback form. This post would summarise the response from the user test and provide a strong reference for developing the IP3.

Quantitative questions
The quantitative questions in the user test focused on the general impression of users to the prototype. All five users gave the prototype more than 3 out of 5 (including 3) points to its fun feature. Most of the users found the interaction of prototype is easy to understand except one gave a mediocre point (3 of 5). For the suitability between prototype form and game, most users also gave positive points to the result. All the users approved that the prototype makes the game more interesting.

Qualitative questions
Users gave sufficient opinions to the prototype in the survey questions as well. Most users think, for the concept itself, hinting system is efficient to the game process which must be enabled for the final product. Ideas were also given for developing the interaction level of the prototype including changing nails to soft conductors, making a small wheel where users could hold left or right. Some interesting idea like changing the current version to a spinning wheel, which would pick a random letter while spinning the wheel to make the game more challenging.

Specifically, ask to the opinion to develop the control of prototype, users talked about the specific actions as below:
- Flat touch points on the edge combining with the soft pointer
- Making the wheel itself more steady and durable, which would reduce the accident input while interacting with the wheel.
- Managing the wires of the prototype by moving them from the surface to the buttom
- Make the touch surface larger to increase the feedback level between to inductors.


During the instant feedback, users mostly complained about the current control of the  prototype, as it was too easy to accidentally receive inputs. This would be the major development for the next version of prototype. Also, on the coding part, hinting system would be added into the game interface to let the game fully stand alone without offering hint from the developer.

Testing video footages:



Monday, 5 October 2015

Developed Code for IP2

To edit the previous code to fit in with the physical prototype, the ActionScript code needs to be developed. The main aspect that needs to be changed is the input method.

All the change was made in the main.as

 public var wordArray:Array = new Array();  
 public var letterArray:Array =   
      [  
      "a","b","c","d","e","f","g","h","i","j","k","l","m",  
      "n","o","p","q","r","s","t","u","v","w","x","y","z"  
      ]  
 public var letterIndex: int = 0;  
Several new arrays were set as the public function.
The "letterArray:Array =  [... ]" is to set a completed alphabetical list, and the "letterIndex" is an initialised number to determine which letter to pick for the guessed word.

 public function getGuess()  
 {  
      stage.addEventListener(KeyboardEvent.KEY_UP, wheelActions);  
 }  
the new getGuess() function changed the KEY_DOWN to KEY_UP, and instead of running previous "getletter" function, a new function called wheelActions() was made

 public function wheelActions(e:KeyboardEvent)  
           {  
                switch(e.keyCode)  
                {  
                     case 37:  
                          letterIndex ++;  
                          //letterDisplay.text = letterArray[letterIndex];  
                          if (letterIndex > 25)  
                          {  
                               letterIndex = 0  
                          }  
                          trace(letterIndex, " ", letterArray[letterIndex]);  
                          break;  
                     case 39:  
                          letterIndex --;  
                          //letterDisplay.text = letterArray[letterIndex];  
                          if (letterIndex < 0)  
                          {  
                               letterIndex = 25  
                          }  
                          trace(letterIndex, " ", letterArray[letterIndex]);  
                          break;  
                     case 32:  
                          getLetters(e.keyCode);  
                          break;  
                     default:  
                          break;  
                }  
           }  
The wheelAction() function is to set the key bindings for the "wheel" to turn clockwise and counter-clockwise. Unlike before that the getletter() function directly received the pushed button on the keyboard to the guessed word, this new function would add or reduce the number of letterIndex and then push the received number into the wordArray.

 public function getLetters(letter)  
           //public function getLetters(e:KeyboardEvent)  
           {  
                //trace(String.fromCharCode(e.charCode));  
                guess.push(letterArray[letterIndex]);  
                //guess.push(String.fromCharCode(e.charCode));  
                var currentGuess = guess.length - 1;  
                trace(guess);  
                guessDisplay[currentGuess].text = guess[currentGuess];  
                if (guess.length == wordArray[chosenWord].length)  
                {  
                     stage.removeEventListener(KeyboardEvent.KEY_UP, getLetters);  
                     checkGuess();  
                }  
           }  
As listed above, the getLetters (e:KeyboardEvent) was disabled and the variable for guess.push function becomes (letterArray[letterIndex]).


The default letter locates at letterArray[0] which equals to "a". Also, if the letterIndex is more than 25  (if clockwise) or less than zero (if counter-clockwise), the letterIndex would reset to "a" or "z".


Physical interactive prototype



The physical input idea for the board game is to make a alphabetical wheel which allows the player to select and choose different letters by spinning the wheel:




Draft & Paper prototype:
















The physical prototype consists of three parts:

1) The pointer wheel

2) The interactive base

3) The alphabetical wheel







1) Pointer wheel

This is the only part the player allowed to spin. While player spins the wheel, the pointer on the wheel would trigger the conductive parts on the interactive base, which indicates which way the player spins. On the bottom of the pointer wheel, there would be a conductive area where enables the "push" function. Making a complete circuit between pointer and the base.




update:

To develop the interaction method, the pointer would be split into two part, where each part would be connected to different button. By doing this, the making of base could be easier, and the wires could be less messy.









2) Interactive base

A wheel larger than the pointer wheel. It is supposed to have 26 conductive bits around the edge, however, in order to identify both direction spinning, there should have 26*2 conductive bits.

There also need some way to stabilise the pointer in the middle of two conductive bits, the stabilised part need to be soft and inductive.




Update:

To split up two part at the pointer, it doesn't need this method to tell the difference of spinning direction.




3) Alphabetical wheel

This wheel is just an wheel telling player which letter is being selected, and it does not necessarily need any circuit-activities involved. This could be drawn on a paper and used as the base of the other two wheels.







Circuit management

The pointer wheel should be connected to different button inputs:

Pointer part A: button "A"

Pointer part B: button "D"

Pointer bottom: button "Space bar"




The interactive base should be connected to the ground (earth) output, which makes each contact between two wheels would make a complete circuit.










!!! IMPORTANT update:

Instead of building entire part of pointer wheel and interactive base, I found an old game controller (Playstation DJ Hero game board) which could be developed to the two interactive parts of the prototype. However, the game board would only be used as the base of the prototype, in other word, no existing wiring or programming system would be used for the interactive prototype.









Tearing the console apart is very satisfying...






The metal wire is made of Tin and Lead, which both are conductive.



Two wires were bent as a circle and stuck together for holding the nails later


Nails were put along the circle, and each nail indicates a certain letter.



The bottom sides of the wheel:
The wire on the left is ground wire that connects to a metal ring, the wire on the right connects to the "Space Bar" button and was attached to the spring. When the whole pointer wheel is being pushed down, the spring and the metal ring would get contact with each other, which makes a complete circuit.


The first version of the pointer:
The conductive part of the pointer is made by aluminium foil, the two side of the pointer was separated by some cardboard paper.
However, this pointer is still too soft for going through the indicator made by zinc nails, so after several tests, the paper pointer broke down pretty soon.















The second version of the pointer:
The two conductive parts are made by thick metal wires, two wires were separated by some layers of cardboard paper and tied up by duct tape.
This made the pointer harder and less likely to be damaged by the indicators.


























The completed prototype

Monday, 14 September 2015

Actionscript code for Prototype 1

There are one stage of the prototype and three accompanied classes constructed through Actionscript. 

Stage - Mashup.fla
Main class - main.as
Player's class - player.as
player's moving number class - tile.as


The stage would contain the pre-drawn text fields for the game instruction to be presented for players. Also, 10 small text boxes would be used as the letter box for players to guess the words. The 'player' and 'tile' in the Library has their own class files and will be presented on the stage when the stage is played.




Player's class
 
This class determines the initial and moved position of the players.


Tile class





















This class determines the start off point of the tile inside the grid. Also, a mouse click event is added, which allowed developer (user) to see the number of the tile.




Main class

imported class and package
 import flash.display.MovieClip;  
 import flash.events.*;  
 import flash.text.TextField;  


Variables were set to all the elements included in the stage
 public var player1;  
 public var player1CurrentTile:int = 0;  
 public var tileArray:Array = new Array();  
 public var wordArray:Array = new Array();  
 public var words:Array =   
      [  
           "tiger",  
           "lion",  
           "deer",  
           "bear",  
           "horse",  
           "eagle"  
      ];       
 public var chosenWord:int;  
 public var letter1:TextField = new TextField();  
 public var letter2:TextField = new TextField();  
 public var letter3:TextField = new TextField();  
 public var letter4:TextField = new TextField();  
 public var letter5:TextField = new TextField();  
 public var letter6:TextField = new TextField();  
 public var wordLettersDisplay:Array = new Array();  
 public var guess1:TextField = new TextField();  
 public var guess2:TextField = new TextField();  
 public var guess3:TextField = new TextField();  
 public var guess4:TextField = new TextField();  
 public var guess5:TextField = new TextField();  
 public var guess6:TextField = new TextField();  
 public var guess:Array = new Array();  
 public var guessDisplay:Array = new Array();  
 public var guessCorrectCounter:int = 0;  
* As there a 5 spots for user's to guess the words, the words chosen for the array contained no more than five letters.

Run functions
 public function main() {  
      // constructor code  
      createGameBoard();  
      setUpLettersDisplay();  
      setUpWordArray();  
      player1 = new player(40, 490);  
      stage.addChild(this.player1);  
      startGame();  
           }  

Break down each function below:

start game function:
 public function startGame()  
 {  
      chooseWord();  
      trace(wordArray[chosenWord]);  
      setUpInstructions();  
      getGuess();  
 }  
Run the other game function to ensure the order of the game process.


 public function setUpLettersDisplay()  
 {  
      wordLettersDisplay.push(letter1);  
      wordLettersDisplay.push(letter2);  
      wordLettersDisplay.push(letter3);  
      wordLettersDisplay.push(letter4);  
      wordLettersDisplay.push(letter5);  
      wordLettersDisplay.push(letter6);  
      guessDisplay.push(guess1);  
      guessDisplay.push(guess2);  
      guessDisplay.push(guess3);  
      guessDisplay.push(guess4);  
      guessDisplay.push(guess5);  
      guessDisplay.push(guess6);  
 }  
This function would 'push' the input to another text box so the letter of the guessed would be presented separated in each box.

the function that create the game board (developed from Blackboard ac3 grid creation tutorial)
 public function createGameBoard()   
 {  
      var gameBoardStartX: uint = 80;  
      var gameBoardStartY: uint = 50;  
      var gameBoardTilesWide = 8;  
      var gameBoardTilesHigh = 6;  
      var tileWidth = 80;  
      var tileNumber:int = gameBoardTilesWide*gameBoardTilesHigh;  
      var tileNumberChange:int = -1;  
      for (var i = 0; i < gameBoardTilesHigh; i++) {  
           var yPos = gameBoardStartY + tileWidth / 2 + (i * tileWidth);  
           if (i > 0 && (i % 2) != 0)  
           {  
                tileNumber -= (gameBoardTilesWide-1);  
                tileNumberChange *= -1;  
           }  
           if (i>1 && (i % 2) ==0)  
           {  
                tileNumber -= (gameBoardTilesWide+1);  
                tileNumberChange *= -1;  
           }  
           for (var j = 0; j < gameBoardTilesWide; j++) {  
                var xPos = gameBoardStartX + tileWidth / 2 + (j * tileWidth);  
                var aTile: tile = new tile(xPos, yPos, tileNumber);  
                stage.addChild(aTile);  
                tileNumber += tileNumberChange;  
           }  
      }  
 }  

word pool function
 public function setUpWordArray()  
 {  
      for(var k:int = 0; k < words.length; k++)  
      {  
           var thisWord = words[k];  
           var thisWordArray:Array = new Array();  
           for(var l:int = 0; l < thisWord.length; l++)  
           {  
                thisWordArray.push(thisWord.charAt(l));  
           }  
           wordArray.push(thisWordArray);  
      }  
      trace(wordArray.length);  
 }  
This function set up the word array, which creates a list of words for players to guess.


 public function chooseWord()       
 {  
      chosenWord = Math.ceil(Math.random()*(wordArray.length-1));  
      trace("chosenWord = ", chosenWord);  
 }  
Randomly choose a word for player to guess.


 public function setUpInstructions()  
 {  
      trace("in setUpInstructions");  
      instructions.text = "Your word has " + wordArray[chosenWord].length + " letters. Type in your guess";  
 }  
This function would present a text instruction to show the total number of letters that a player is about to guess.


 public function getGuess()  
 {  
      stage.addEventListener(KeyboardEvent.KEY_DOWN, getLetters);  
 }  
&&&
 public function getLetters(e:KeyboardEvent)  
 {  
      trace(String.fromCharCode(e.charCode));  
      guess.push(String.fromCharCode(e.charCode));  
      var currentGuess = guess.length - 1;  
      trace(guess);  
      guessDisplay[currentGuess].text = guess[currentGuess];  
      if (guess.length == wordArray[chosenWord].length)  
      {  
           stage.removeEventListener(KeyboardEvent.KEY_DOWN, getLetters);  
           checkGuess();  
      }  
 }  
get the letters guessed from player by keyboard events.


 public function checkGuess()  
 {  
      for (var m:int = 0; m < wordArray[chosenWord].length; m++)  
      {  
           if(wordArray[chosenWord][m] == guess[m])  
           {  
                wordLettersDisplay[m].text = guess[m];  
                guessCorrectCounter ++;  
           }  
      }  
      if (guessCorrectCounter > 0)  
      {  
           results.text = "You got "+guessCorrectCounter+" letters correct!";  
           movePlayerTo();  
      }  
      else  
      {  
           results.text = "You didn't get any letters correct :-( ";  
           nextGuess();  
      }  
 }  
To check if the guessed word matches up with the actual word letter by letter.


 public function movePlayerTo()  
 {  
      trace("in movePlayerTo");  
      var moveToTile = player1CurrentTile + guessCorrectCounter - 1;  
      trace(moveToTile);  
      for (player1CurrentTile; player1CurrentTile <= moveToTile; player1CurrentTile++)  
      {  
           var nextTile = stage.getChildByName(String(player1CurrentTile+1));  
           trace(nextTile);  
           player1.movePlayer(nextTile.x, nextTile.y);  
      }  
      nextGuess();  
 }  
To transfer the number of correct guessed letterso the steps to take by the player.


 public function nextGuess()  
 {  
      instructions.text = "press any key to play again";  
      stage.addEventListener(KeyboardEvent.KEY_DOWN, resetGame);  
 }  
&&&
 public function resetGame(e:KeyboardEvent)  
 {  
      stage.removeEventListener(KeyboardEvent.KEY_DOWN, resetGame);  
      guessCorrectCounter = 0;  
      guess=[];  
      for (var p:int = 0; p < wordLettersDisplay.length; p++)  
      {  
           wordLettersDisplay[p].text = "";  
           guessDisplay[p].text = "";  
      }  
      results.text ="";  
      instructions.text = "";  
      startGame();  
 }  
Allow players press a random to start the next round of word guessing.