- CONCEPTION AND DESIGN:
We create this “Find your Pokemon” game as an exploration and it also tests your outsight and memory. In the limited time, we design three themes, including garden, dark forest, and groove. From the left to right, each game behind each theme is harder than the previous one. Users need to click the mouse on the clues they find to finish the game within 20 seconds. Each time you find the clue, a part of the Pokemon’s contour will show up and it will trigger the next clue from static to moving. Once you finish the game within 20 seconds, you will get the reward, a small size Pokemon. Our main interaction is relied on the game itself, how you choose the theme, how to interact with the flowers, candles, and mushroom in each setting, and get a gift in the end.
Our main concern at first is how the users can interact with the game. We think about leap motion at first, but this idea is rejected by Eric. So we planned to use brightness tracking, however, the outcome was not good. I found the darkest room in order to test the game, it did not work out very well in terms of accuracy. In the end, we decided to use the simplest and clearest way to interact by using a mouse.
Second, we decided to recreate three “Poke boxes.” Initially, we wanted to hide the gifts inside of the Poke balls, but soon we found that it would be really hard to make a ball open. In the end, we created three Poke boxes. Moreover, the reason why we did not use the laser cut is that the laser cut is unable to achieve our goal to make it related to Poke balls. We use the element of Poke ball not in the boxes but also in the introduction and instruction of the game. Overall, our game is tightly connected to the element of Pokemon. It is necessary for us to apply a certain element to our design. In the meanwhile, I basically draw and design every part of the game in processing, I even draw the gifs by each frame.
The purpose of the whole project is designed to utilize a boring time when people already buy the tickets and wait for the movie in the cinema. The design of our game relies on Pokemon and its new movie. We hope this game can be applied to the cinema and improve the interaction between the movie and audiences, which can also be an approach to advertise the movie. So it should be an interesting game and users can be very satisfied to gain a gift in the end.
- FABRICATION AND PRODUCTION:
I am in charge of the processing and drawing part. Anna is in charge of the boxes and Arduino.
In terms of the processing’s code, I literally did not have any experience in coding before. With the help of many fellows and professors, I learn a lot from this process. I use a lot of boolean, millis, condition, if function to make the game work. I also use the Gif Animation library from Drawing is a very significant part of our project. Even though it sounds like a minor part, I took a lot of time to draw the backgrounds for different themes. I also draw every frame and made them into a gif. In order to make the contour of the Pokemon accurate, I used the grid paper to locate and calculate the coordinate (see sketch above). I spend a lot of work on designing this to make the game more beautiful. See all the gifs and backgrounds below, I draw them all by myself.
I am not sure why there are some issues with the last gif, it should be moving…
There are also some pictures of how Anna designed the boxes.
I think the most successful adaption we made is the timer suggested by Eric. Without the timer, the users do not want to try this game again. During the user test, I design the timer by simply showing the number, many users do not notice that the timer exists. And we also noticed that some very clever users can pass the most difficult setting within 30 seconds. So I adjusted the time to 20 seconds and design the new timer. Moreover, some users complained that the instruction was too long and they did not want to read it. So we reduced the content and highlighted the most important part for the users. Lastly, we borrowed a wired mouse from the equipment room to improve the user’s experience while clicking the mouse. I think the most successful part of our project is the reward system, lots of users think they really like the reward system since they can have the gift eventually.
- CONCLUSIONS:
The goal of our project is to let the audiences interact with the Pokemon while waiting for the movie. We design this game to utilize spare time before the movie time. In the previous research, I redefine “interaction” as human-centered experience with reward and a process of exploration with multiple and unexpected alternatives. For instance, the project Click Canvas is a highly interactive project made by Natthakit KIMBAB Kang, which provides multiple alternatives for users to explore and the user does not necessarily know what will come out in the next step. And the processing of matching in our project fits into the new definition I give to interaction as an experience involved with curiosity and uncertainty. In our game, we give user three options to choose and we design the order of the lines so the user definitely has a difficult time identifying which Pokemon is at first. Playing this game is also an adventure and exploration for the users.
Furthermore, Anna and I really spend time reflecting on our last project, we strongly feel that we must add the “reward” part to our final project. It turns out to be the part that most users love. I do think that reflecting on the past project and previous shortcomings help us build this game. On Thursday’s presentation, another group also adds the reward part in their project, not so naturally, but I think chocolate is a good idea. Considering the limited budget, we bought 16 Pokemon in total and they were soon given out to the kids in the IMA show. We never expect that the kids will love this game so much.
If we have more time, we will definitely add sound, more themes, and different kinds of Pokemon in the game. And we will improve the instruction part, people still complain there are too many words on it. We will make it into an interesting animation with sound to introduce to the users how this game works.
One of the users is very excited to get her Pikachu in the final show
Some screenshots of the game:
Processing Code:
import processing.serial.*;
Serial myPort;
int valueFromArduino;
import gifAnimation.*;
int condition;
int startCharmander; //start time
int startBulbasaur;
int startPikachu;
boolean hasWonC = false; // timer situation
boolean hasWonB = false;
boolean hasWonP = false;
PImage introduction;
PImage instruction;
PImage timeboard; // timer
PImage night;
PImage l1;
PImage r1;
PImage l2;
PImage r2;
PImage l3;
PImage r3;
PImage l4;
PImage[] animation;
boolean candleLight = false;
boolean candleLight2 = false;
boolean candleLight3 = false;
boolean candleLight4 = false;
boolean candleLight5 = false;
boolean candleLight6 = false;
boolean candleLight7 = false;
//Gif loopingGif;
//Gif nonLoopingGif;
Gif can;
Gif can2;
Gif can3;
Gif can4;
Gif can5;
Gif can6;
Gif can7;
Gif can8;
//boolean pause = false;
PImage grassland;
PImage bl1;
PImage br1;
PImage bl2;
PImage br2;
PImage bl3;
PImage br3;
PImage bl4;
PImage br4;
boolean bloom = false;
boolean bloom2 = false;
boolean bloom3 = false;
boolean bloom4 = false;
boolean bloom5 = false;
boolean bloom6 = false;
boolean bloom7 = false;
Gif grass;
Gif grass2;
Gif grass3;
Gif grass4;
Gif grass5;
Gif grass6;
Gif grass7;
PImage grove;
PImage pl1;
PImage pr1;
PImage pl2;
PImage pr2;
PImage pl3;
PImage pr3;
boolean grow = false;
boolean grow2 = false;
boolean grow3 = false;
boolean grow4 = false;
boolean grow5 = false;
boolean grow6 = false;
Gif mushroom;
Gif mushroom2;
Gif mushroom3;
Gif mushroom4;
Gif mushroom5;
Gif mushroom6;
public void setup() {
printArray(Serial.list());
// this prints out the list of all available serial ports on your computer.
myPort = new Serial(this, Serial.list()[16], 9600);
introduction = loadImage(“introduction.png”);
instruction = loadImage(“instruction.png”);
timeboard = loadImage(“timeboard.png”);
night = loadImage(“night.jpg”);
grassland = loadImage(“grassland.png”);
grove = loadImage(“grove.jpg”);
l1 = loadImage(“l1.png”);
r1 = loadImage(“r1.png”);
l2 = loadImage(“l2.png”);
r2 = loadImage(“r2.png”);
l3 = loadImage(“l3.png”);
r3 = loadImage(“r3.png”);
l4 = loadImage(“l4.png”);
bl1 = loadImage(“bl1.png”);
br1 = loadImage(“br1.png”);
bl2 = loadImage(“bl2.png”);
br2 = loadImage(“br2.png”);
bl3 = loadImage(“bl3.png”);
br3 = loadImage(“br3.png”);
bl4 = loadImage(“bl4.png”);
br4 = loadImage(“br4.png”);
pl1 = loadImage(“pl1.png”);
pr1 = loadImage(“pr1.png”);
pl2 = loadImage(“pl2.png”);
pr2 = loadImage(“pr2.png”);
pl3 = loadImage(“pl3.png”);
pr3 = loadImage(“pr3.png”);
size(1280, 720);
frameRate(100);
println(“gifAnimation ” + Gif.version());
//// create the GifAnimation object for playback
//loopingGif = new Gif(this, “lavalamp.gif”);
//loopingGif.loop();
//nonLoopingGif = new Gif(this, “lavalamp.gif”);
//nonLoopingGif.play();
//nonLoopingGif.ignoreRepeat();
//// create the PImage array for the interactive display
////animation = Gif.getPImages(this, “lavalamp.gif”);
can = new Gif(this, “candle.gif”);
can2 = new Gif(this, “candle.gif”);
can2.loop();
can3 = new Gif(this, “candle.gif”);
can3.play();
can4 = new Gif(this, “candle.gif”);
can5 = new Gif(this, “candle.gif”);
can6 = new Gif(this, “candle.gif”);
can7 = new Gif(this, “candle.gif”);
can8 = new Gif(this, “candle.gif”);
grass = new Gif(this, “grass.gif”);
grass.loop();
grass2 = new Gif(this, “grass.gif”);
grass3 = new Gif(this, “grass.gif”);
grass4 = new Gif(this, “grass.gif”);
grass5 = new Gif(this, “grass.gif”);
grass6 = new Gif(this, “grass.gif”);
grass7 = new Gif(this, “grass.gif”);
mushroom = new Gif(this, “mushroom.gif”);
mushroom.loop();
mushroom2 = new Gif(this, “mushroom.gif”);
mushroom3 = new Gif(this, “mushroom.gif”);
mushroom4 = new Gif(this, “mushroom.gif”);
mushroom5 = new Gif(this, “mushroom.gif”);
mushroom6 = new Gif(this, “mushroom.gif”);
}
void draw() {
if (condition==0) {
// myPort.write(‘E’);
image(introduction, 0, 0, 1280, 720);
if (mousePressed && mouseX >600 && mouseX <680 && mouseY >180 && mouseY <320) {
condition=1;
}
}
if (condition==1) {
image(instruction, 0, 0, 1280, 720);
if (mousePressed && mouseX >150 && mouseX <350 && mouseY >480 && mouseY <720) {
condition=3;
startBulbasaur = millis();
}
if (mousePressed && mouseX >600 && mouseX <680 && mouseY >480 && mouseY <720) {
condition=2;
startCharmander = millis();
}
if (mousePressed && mouseX >920 && mouseX <1200 && mouseY >480 && mouseY <700) {
condition=4;
startPikachu = millis();
}
}
// Charmander Part
if (condition==2) {
//myPort.write(‘L’);
tint(255, 167);
image(night, 0, 0);
image(can, 620, 60, 50, 40);
image(can2, 560, 270, 60, 40);
image(can3, 480, 420, 90, 70);
image(can4, 680, 260, 50, 60);
image(can5, 720, 460, 65, 55);
image(can6, 620, 500, 80, 60);
image(can7, 400, 280, 50, 40);
image(can8, 440, 600, 90, 90);
//tint(255, 57);
//image(l1, 520, 60);
//image(r1, 640, 60);
//image(l2, 460, 300);
//image(r2, 700, 300);
// image(l3, 460, 480);
//image(r3, 640, 480);
//image(l4, 340, 180);
//timer here
textSize(30);
fill(255);
int timer;
timer = 20-(millis()-startCharmander)/1000;// adjust the time if you want!!
if ( !hasWonC ) {
noTint();
image(timeboard, 20, 20, 250, 100);
text(“Timer:” + timer, 110, 80);
}
if (timer < 0.1 && candleLight7 == false ) {
//condition = 5;
background(5);
textSize(32);
fill(255);
text(“BACK”, 1180, 700);
text(“Failed, try again!”, 530, 320);
}
if (mousePressed && mouseX >520 && mouseX <600 && mouseY >230 && mouseY <310) {
//can3.pause();
//can2.pause();
can.play();
candleLight = true;
}
if (candleLight == true) {
tint(255, 57);
image(l2, 460, 300);
}
if (mousePressed && mouseX >600 && mouseX <680 && mouseY >20 && mouseY <100 && candleLight == true) {
can4.play();
candleLight2 = true;
}
if (candleLight2 == true) {
tint(255, 57);
image(l1, 520, 60);
}
if (mousePressed && mouseX >660 && mouseX <740 && mouseY >260 && mouseY <340 && candleLight2 == true) {
can5.play();
candleLight3 = true;
}
if (candleLight3 == true) {
tint(255, 57);
image(r1, 640, 60);
}
if (mousePressed && mouseX >720 && mouseX <800 && mouseY >420 && mouseY < 500 && candleLight3 == true) {
can6.play();
candleLight4 = true;
}
if (candleLight4 == true) {
tint(255, 57);
image(r2, 700, 300);
}
if (mousePressed && mouseX >580 && mouseX <700 && mouseY >480 && mouseY < 580 && candleLight4 == true) {
can7.play();
candleLight5 = true;
}
if (candleLight5 == true) {
tint(255, 57);
image(r3, 640, 480);
}
if (mousePressed && mouseX >360 && mouseX <440 && mouseY >240 && mouseY < 320 && candleLight5 == true) {
can8.play();
candleLight6 = true;
}
if (candleLight6 == true) {
tint(255, 57);
image(l4, 340, 180);
}
if (mousePressed && mouseX >380 && mouseX <520 && mouseY >540 && mouseY < 660 && candleLight6 == true) {
can8.play();
candleLight7 = true;
}
if (candleLight7 == true) {
tint(255, 57);
image(l3, 460, 480);
noTint();
fill(52, 118, 157, 200);
noStroke();
// rect(580, 290, 145, 50, 20);
rect(390, 290, 510, 90, 20);
rect(1170, 665, 105, 50, 20);
textSize(32);
fill(255);
text(“BACK”, 1180, 700);
text(“Congratulation!”, 400, 325);
text(“Take your Pokemon in the box!”, 400, 365);
//fill(255, 100, 190);
//noStroke();
//rect(580, 290, 145, 50);
myPort.write(‘C’);
hasWonC = true;
}
if (mousePressed&& mouseX >1200 && mouseX <1280 && mouseY >680 && mouseY <740) {
condition=1;
myPort.write(‘D’);
candleLight = candleLight2 = candleLight3 = candleLight4 = candleLight5 = candleLight6 = candleLight7 = false;
//can2.stop();
can.stop();
//can3.stop();
can4.stop();
can5.stop();
can6.stop();
can7.stop();
can8.stop();
can.jump(0);
can2.jump(0);
can3.jump(0);
can4.jump(0);
can5.jump(0);
can6.jump(0);
can7.jump(0);
can8.jump(0);
hasWonC = false;
}
}
// Bulbasaur Part
if (condition==3) {
image(grassland, 0, 0);
image(grass, 610, 580, 95, 95);
image(grass2, 780, 300, 70, 70);
image(grass3, 620, 30, 50, 50);
image(grass4, 450, 300, 60, 60);
image(grass5, 470, 540, 75, 75);
image(grass6, 690, 250, 55, 66);
image(grass7, 800, 610, 110, 100);
//image(bl1, 370, 30);
//image(br1, 640, 30);
//image(bl2, 370, 210);
//image(br2, 640, 210);
//image(bl3, 370, 330);
//image(br3, 640, 330);
//image(bl4, 310, 330);
//image(br4, 640, 330);
textSize(32);
fill(255);
int timer = 20-(millis()-startBulbasaur)/1000;//adjust the time if you want
if ( !hasWonB ) {
noTint();
image(timeboard, 20, 20, 250, 100);
text(“Timer:” + timer, 110, 80);
}
if (timer < 0.1 && bloom7 == false ) {
background(5);
textSize(32);
fill(255);
text(“BACK”, 1180, 700);
text(“Failed, try again!”, 530, 320);
}
if (mousePressed && mouseX >580 && mouseX <680 && mouseY >560 && mouseY <640) {
bloom = true;
}
if (bloom == true) {
tint(255, 87);
image(bl3, 370, 330);
noTint();
grass2.loop();
}
if (mousePressed && mouseX >720 && mouseX <840 && mouseY >250 && mouseY <350 && bloom == true) {
bloom2 = true;
}
if (bloom2 == true) {
tint(255, 87);
image(br3, 640, 330);
noTint();
grass3.loop();
}
if (mousePressed && mouseX >610 && mouseX <660 && mouseY >5 && mouseY <70 && bloom2 == true) {
bloom3 = true;
}
if (bloom3 == true) {
tint(255, 87);
image(br1, 640, 30);
noTint();
grass4.loop();
}
if (mousePressed && mouseX >430 && mouseX <520 && mouseY >280 && mouseY <360 && bloom3 == true) {
bloom4 = true;
}
if (bloom4 == true) {
tint(255, 87);
image(bl1, 370, 30);
noTint();
grass5.loop();
}
if (mousePressed && mouseX >460 && mouseX <530 && mouseY >530 && mouseY <620 && bloom4 == true) {
bloom5 = true;
}
if (bloom5 == true) {
tint(255, 87);
image(bl4, 310, 330);
noTint();
grass6.loop();
}
if (mousePressed && mouseX >680 && mouseX <750 && mouseY >240 && mouseY <320 && bloom5 == true) {
bloom6 = true;
}
if (bloom6 == true) {
tint(255, 87);
image(bl2, 370, 210);
image(br2, 640, 210);
noTint();
grass7.loop();
}
if (mousePressed && mouseX >780 && mouseX <910 && mouseY >580 && mouseY <720 && bloom6 == true) {
bloom7 = true;
}
if (bloom7 == true) {
tint(255, 87);
image(br4, 640, 330);
noTint();
fill(58, 80, 22, 200);
noStroke();
rect(390, 290, 510, 90, 20);
rect(1170, 665, 105, 50, 20);
textSize(32);
fill(255);
text(“BACK”, 1180, 700);
text(“Congratulation!”, 400, 325);
text(“Take your Pokemon in the box!”, 400, 365);
myPort.write(‘A’);
hasWonB = true;
}
// Back on option A
if (mousePressed&& mouseX >1200 && mouseX <1280 && mouseY >680 && mouseY <740) {
condition=1;
myPort.write(‘B’);
bloom = bloom2 = bloom3 = bloom4 = bloom5 = bloom6 = bloom7 = false;
//grass.stop();
grass2.stop();
grass3.stop();
grass4.stop();
grass5.stop();
grass6.stop();
grass7.stop();
grass.jump(0);
grass2.jump(0);
grass3.jump(0);
grass4.jump(0);
grass5.jump(0);
grass6.jump(0);
grass7.jump(0);
hasWonB = false;
}
}
if (condition==4) {
image(grove, 0, 0);
image(mushroom, 600, 580, 120, 120);
image(mushroom2, 820, 300, 90, 90);
image(mushroom3, 750, 485, 90, 90);
image(mushroom4, 430, 485, 95, 95);
image(mushroom5, 610, 200, 75, 75);
image(mushroom6, 380, 300, 80, 80);
//image(pl1, 280, 40);
//image(pr1, 640, 40);
//image(pl2, 280, 360);
//image(pr2, 640, 360);
//image(pl3, 280, 360);
//image(pr3, 640, 360);
textSize(32);
fill(255);
int timer = 20-(millis()-startPikachu)/1000;//adjust the time if you want
if ( !hasWonP ) {
noTint();
image(timeboard, 20, 20, 250, 100);
text(“Timer:” + timer, 110, 80);
}
if (timer < 0.1 && grow6 == false ) {// ass things
background(5);
textSize(32);
fill(255);
text(“BACK”, 1180, 700);
text(“Failed, try again!”, 530, 320);
}
if (mousePressed && mouseX >580 && mouseX <720 && mouseY >500 && mouseY <700) {
grow = true;
}
if (grow == true) {
image(pl2, 280, 360);
noTint();
mushroom2.loop();
}
if (mousePressed && mouseX >800 && mouseX <920 && mouseY >280 && mouseY <400 && grow == true) {
grow2 = true;
}
if (grow2 == true) {
image(pr2, 640, 360);
noTint();
mushroom3.loop();
}
if (mousePressed && mouseX >730 && mouseX <820 && mouseY >480 && mouseY <580 && grow2 == true) {
grow3 = true;
}
if (grow3 == true) {
image(pr3, 640, 360);
noTint();
mushroom4.loop();
}
if (mousePressed && mouseX >410 && mouseX <520 && mouseY >480 && mouseY <580 && grow3 == true) {
grow4 = true;
}
if (grow4 == true) {
image(pl3, 280, 360);
noTint();
mushroom5.loop();
}
if (mousePressed && mouseX >600 && mouseX <680 && mouseY >160 && mouseY <300 && grow4 == true) {
grow5 = true;
}
if (grow5 == true) {
image(pr1, 640, 40);
noTint();
mushroom6.loop();
}
if (mousePressed && mouseX >370 && mouseX <450 && mouseY >270 && mouseY <370 && grow5 == true) {
grow6 = true;
}
if (grow6 == true) {
image(pl1, 280, 40);
fill(180, 109, 33, 200);
noStroke();
//rect(580, 290, 145, 50, 20);
//rect(1170, 665, 105, 50, 20);
//textSize(32);
//fill(255);
//text(“BACK”, 1180, 700);
//text(“Success!”, 590, 325);
rect(390, 290, 510, 90, 20);
rect(1170, 665, 105, 50, 20);
textSize(32);
fill(255);
text(“BACK”, 1180, 700);
text(“Congratulation!”, 400, 325);
text(“Take your Pokemon in the box!”, 400, 365);
myPort.write(‘E’);
hasWonP = true;
}
if (mousePressed&& mouseX >1200 && mouseX <1280 && mouseY >680 && mouseY <740) {
condition=1;
myPort.write(‘F’);
grow = grow2 = grow3 = grow4 = grow5 = grow6 = false;
//grass.stop();
mushroom2.stop();
mushroom3.stop();
mushroom4.stop();
mushroom5.stop();
mushroom6.stop();
mushroom.jump(0);
mushroom2.jump(0);
mushroom.jump(0);
mushroom4.jump(0);
mushroom5.jump(0);
mushroom6.jump(0);
hasWonP = false;
}
}
}
Arduino Code:
#include <Servo.h>
Servo myservo1;
Servo myservo2;
Servo myservo3;
char valueFromProcessing;
void setup() {
Serial.begin(9600);
myservo1.attach(9);
myservo2.attach(10);
myservo3.attach(11);
}
void loop() {
// to receive a value from Processing
while (Serial.available()) {
valueFromProcessing = Serial.read();
}
if (valueFromProcessing == ‘A’) {
myservo1.write(130);
}
if (valueFromProcessing == ‘B’) {
myservo1.write(30);
}
if (valueFromProcessing == ‘C’) {
myservo2.write(130);
}
if (valueFromProcessing == ‘D’) {
myservo2.write(30);
}
if (valueFromProcessing == ‘E’) {
myservo3.write(300);
}
if (valueFromProcessing == ‘F’) {
myservo3.write(100);
}
// too fast communication might cause some latency in Processing
// this delay resolves the issue.
delay(10);
}