CONCEPTION AND DESIGN:
- My earliest conception was an alarm clock driven by Arduino, 2 Neopixel 8*8 boards and some weird components such as a fan, which arose from those awkward experiences when my own clock woke both my roomates up while I still slept like a dog. I came to realize that noise is not always the most effective way to bring one off bed, and sometimes it makes trouble, so I came up with an idea with lots of prank elements: Just as usual, the Neopixels would be used as the clock display. The difference was that you can adjust the alarm mode according to the sleeping habits of your roommates and your own characters. For example, one of the plans was that when it was the time, the clock would first give out tentative ringing tones, and if the user wakes up in time, by doing 5 full bicep curls in 10 seconds the alarm would be totally turned off. However, if this doesn’t work, a powerful fan attached to the clock would be activated and blow you till you wake and do something. It would repeat every 5 minutes until totally turned off. You can also disable the ringing tones and leave the fan only. With the help of pressure sensors in the beds, the system can also judge the conditions of your roommates to make judgements whether to forbid some functions. The interactivity lies on that the system can detect the conditions of the residents and automatically make adjustments and the users perform certain tasks to get corresponding results. To achieve this interactivity, I designed several buttons for the device to ease operation. Sadly, they were not accomplished before the user testing. However, I did see something made by the classmates that interested me, such as a tyre pump game about the Disney-Pixar movie Up. So I started to think about adding more animated and interactive effects to my work.
- I forgot to bring my kits and other materials back from the shelf before the big clean and I lost them. What’s worse, a large part of my codes were not preserved after I updated Arduino. So I decided to start all over and focused more on software than hardware. Making a video game became a practical choice. After evaluating several conceptions, I chose to make a 2D space shooting game with Star Wars elements.
FABRICATION AND PRODUCTION:
The goal of my alarm clock is to bring a customized, comfortable and even a little comical alarm service.
Core materials:
- Cardboards
- Arduino uno *1
- Breadboard *1
- Neopixel 8*8 *1
- Several cables
- 5V motor with fan blades *1
- Tilt sensor *1
- Yellow LED *1
- Tapes
- Buzzer *1
- Printing paper.
I chose the materials based upon these principles:
- Accessibility. —— All materials are accessed either in my toolkit or equipment room in 826 so that it’s easy to fix the broken parts and find alternatives in time.
- Machinability. —— I had to make sure the materials are easy to work on because time didn’t allow me to spent too long on processing them. I abandoned the thought of 3D printing or laser cutting but chose cardboards as the main materials.
I chose the form/element based upon these principles:
- Durability. —— It’s very important to all interactive works, but especially to a physical game like this, which requires solid devices with simple external form and reliable structure.
- Entertaining aspect. —— This is why I chose to build a miniature scene. It strengthened the contrast of the volume and made the alarm clock stick out as the main role. It also reflected the modern people’s fear of unpunctuality in a humorous but ironic way.
There were also corresponding codes which were not accomplished. Sadly, this was as far as I went before all these creations as along with my kits were thrown away on Friday because I forgot to take them before the big clean. So later I designed the space shooting game called X-wing as a compensation.
Demonstration:
Codes:
import ddf.minim.spi.*; import ddf.minim.signals.*; import ddf.minim.*; import ddf.minim.analysis.*; import ddf.minim.ugens.*; import ddf.minim.effects.*; import processing.dxf.*; import processing.sound.*; SoundFile sound; PImage img; int loopcount; float life = 100; float energy = 100; PVector[] enemy = new PVector[5]; PVector[] direction = new PVector[5]; PVector[] bullet = new PVector[5]; PVector[] direction1 = new PVector[5]; int flag = 0; int start = 0; int count; float time = 0; float lasting = 0; int max = 2; int level = 1; int invade; void setup() { size(600, 600); background(0); img = loadImage("xwing3.png"); for (int index = 0; index < 5; index++ ) { enemy[index] = new PVector(random(width/6, width*5/6), 10); direction[index] = new PVector(0, 2); } for (int index = 0; index < 5; index++ ) { bullet[index] = new PVector(mouseX, mouseY); direction1[index] = new PVector(0, 100); } // minim = new Minim(this); //player = minim.loadFile("s.mp3", 2048); //player.play(); } void draw() { if (start == 0) { background(0); fill(#E3E3E3); textAlign(CENTER); textSize(44); fill(#EE6AA7); text("START", 0.5 * width, 0.5 * height); fill(#E3E3E3); start = 0; time = 0; life = 100; count = 0; flag = 0; level = 1; energy = 100; invade = 0; } if (start == 1) { if (lasting == 1) { start = 5; } if (count <= 50) { max = 1; level = 1; } if (count <= 180 && count > 50) { max = 2; level = 2; } if (count <= 400 && count > 180 ) { max = 3; level = 3; } if (count > 400 ) { if (max < 5) { max = 4 + (int)time; } else { max = 12; } level = 5; } time += 0.01; if (life <= 0) { start = 2; } if (invade >= 10) { start = 2; } if (life < 100 && life > 0) { life += 0.03; } else { life = 100; } for (int index = 0; index < 5; index++) { if (direction[index].y < max) direction[index].y *= 1.005; } background(0); noStroke(); fill(#9932CC); fill( #F8F8FF); fill(#E3E3E3); noStroke(); for (int index = 0; index < 5; index++) { float dis = sqrt((mouseX - enemy[index].x)*(mouseX - enemy[index].x)+(mouseY - enemy[index].y)*(mouseY - enemy[index].y)); if (dis <= 30) { life-= 20; ellipse(mouseX, mouseY, 70, 70); enemy[index].y = 10; enemy[index].x = random(width/6, width*5/6); } } for (int index = 0; index < 5; index++) if (enemy[index].y >= 569 && enemy[index].y <= 570) { if (count > 0) { count --; } if (invade <= 10) { invade++; } } textAlign(LEFT); fill(255); textSize(0.03*width); text("SCORE: "+count, 0.8*width, 0.1*height); text("TIME: "+time, 0.8*width, 0.05*height); text("LEVEL: "+level, 0.8*width, 0.15*height); if (0<= invade && invade <= 3) { fill(255); } if (4<= invade && invade <= 6) { fill(255, 240, 0); } if (7<= invade && invade <= 8) { fill(255, 200, 0); } if (invade >= 9) { fill(255, 0, 0); } text("INVASION: "+invade, 0.8*width, 0.2*height); fill(255); text("POSITION:"+mouseX+","+mouseY, 20, 60); fill(#F8F8FF); for (int index = 0; index < 5; index++) ellipse(enemy[index].x, enemy[index].y, 30, 30); fill( #F8F8FF); for (int index = 0; index < 5; index++) enemy[index].y += direction[index].y; for (int index = 0; index < 5; index++) { if (enemy[index].y >= 580 ) { enemy[index].y = 10; enemy[index].x = random(100, 500); } } if (mousePressed) { if (energy > 0) { flag = 1; fill(255, random(20, 60), 0); stroke(255, random(20, 60), 0); strokeWeight(3); for (int index = 0; index < 5; index++) line(bullet[index].x-52, bullet[index].y+10, bullet[index].x-52, bullet[index].y-10); for (int index = 0; index < 5; index++) line(bullet[index].x+52, bullet[index].y+10, bullet[index].x+52, bullet[index].y-10); for (int index = 0; index < 5; index++) line(bullet[index].x-48, bullet[index].y+10, bullet[index].x-48, bullet[index].y-10); for (int index = 0; index < 5; index++) line(bullet[index].x+48, bullet[index].y+10, bullet[index].x+48, bullet[index].y-10); //for (int index = 0; index < 5; index++) // line(bullet[index].x-5, bullet[index].y+10, bullet[index].x-5, bullet[index].y-10); //for (int index = 0; index < 5; index++) // line(bullet[index].x+5, bullet[index].y+10, bullet[index].x+5, bullet[index].y-10); fill( #F8F8FF); for (int index = 0; index < 5; index++) bullet[index].y -= direction1[index].y; for (int index = 0; index < 5; index++) { if (bullet[index].y <= 0) { bullet[index].y = mouseY; bullet[index].x = mouseX; } } energy -= 0.3; if (energy <= 0) { flag = 0; } for (int index = 0; index < 5; index++) { if (enemy[index].x - mouseX <= 65 && enemy[index].x - mouseX >= 35 && enemy[index].y - bullet[index].y <= 30 && enemy[index].y - bullet[index].y >= -30) { ellipse(enemy[index].x, enemy[index].y, 30, 30 ); count++; enemy[index].y = -300; enemy[index].x = random(100, 500); if (energy <= 90) { energy = energy + 10; } else if (energy > 90) { energy = 100; } } if (enemy[index].x - bullet[index].x <= -35 && enemy[index].x - bullet[index].x >= -65 && enemy[index].y - bullet[index].y <= 30 && enemy[index].y - bullet[index].y >= -30) { ellipse(enemy[index].x, enemy[index].y, 30, 30 ); count++; enemy[index].y = -300; enemy[index].x = random(100, 500); if (energy <= 90) { energy = energy + 10; } else if (energy > 90) { energy = 100; } } } } } stroke(255); strokeWeight(2); line(mouseX-10, mouseY, mouseX+10, mouseY); line(mouseX, mouseY-10, mouseX, mouseY+10); noStroke(); fill(255, 0, 0); rect(10, 30, 30 * 0.1 * life, 5); fill(20-0.2*energy, 20+2*energy, 200+0.5*energy); rect(10, 20, 3 * energy, 5); image(img, mouseX-62, mouseY-75); } if (start == 2) { background(0); fill(#E3E3E3); textAlign(CENTER); textSize(24); fill(#EE6AA7); text("YOU LOSE.", 0.5 * width, 0.3 * height); text("SURVIVAL TIME: "+time+" seconds", 0.5 * width, 0.5 * height); text("SCORE:"+count, 0.5 * width, 0.7 * height); fill(#E3E3E3); } if (start == 3) { background(0); fill(255); textSize(24); textAlign(LEFT); text("SCORE: "+count, 450, 50); text("TIME: "+time, 450, 20); text("LEVEL: "+level, 450, 80); text("INVASION: "+invade, 450, 110); time = 0; life = 100; count = 0; flag = 0; level = 1; energy = 100; invade = 0; fill(#9932CC); fill(#F8F8FF); fill(#E3E3E3); ellipse(mouseX, 580, 30, 30); textAlign(CENTER); textSize(14); fill( #EE6AA7); stroke(#EE6AA7); textSize(22); //if (start == 5) { text("RULE", 300, 150); textAlign(LEFT); text("1. Move your mouse to control the ship", 10, 190); text("2. Press the mouse to open fire ", 10, 230); text("3, Dodge the enemies to avoid harm", 10, 270); text("4. Ammo and HP are shown on the top left", 10, 310); text("5. Press s to stop during the process", 10, 350); text("6. Do not let in >= 10 enemies", 10, 390); textAlign(CENTER); text("[CLICK ANYWHERE TO CONTINUE]", 300, 450); stroke(#EE6AA7); fill(#E3E3E3); } } void mousePressed() { if (start == 3) { //if (mousePressed && mouseX >= 200 && mouseX <= 500 && mouseY >= 400 && mouseY <= 500) start = 1 ; } if (start == 2) { start = 0; } if (start == 0 && mouseX > (width * 0.4) && mouseX < (width * 0.6) && mouseY > (height * 0.4) && mouseY < (height * 0.6)) { start = 3; } } //pause in the process void keyPressed() { if (key == 's') { lasting = 1 - lasting; if (lasting == 0) start = 1; } }
CONCLUSIONS:
Though my task changed in the midway, the goal didn’t change. As is mentioned above, my goal is to design something that is smart, utilitarian and relaxing with a little surprise. Below is aimed at the second work which is relatively more accomplished.
From my perspective, my project aligns with the definition of interaction in these ways:
- Offering necessary tips and reminders to the players through interactive screen display.
- Reading the electronic signals of the player’s state.
- Playable, restartable and fair with proper game rules.
My project doesn’t align with my definition of interaction enough in these ways:
- Failing to adding hardware to the project to complicate and enrich the user experience.
- Primitive screen display with no proper background or cool enemy appearance
- Lack a better game level mechanism.
- Improper difficulty settings.
Possible solutions:
If there were enough time. Of course I understand where they should be going.
What I learnt from my accomplishments are that:
- it is really hard to tell the principle of making the people feel some interactive designs complicated, interesting or simply worth treating well.
- My time management skills had no improvement compared with midterm.
- More attention should be paid to the daily schedule and school calendar.
- Consult instructors in time and learn from tutorials.
ANNEX
- Original Processing game code: https://blog.csdn.net/ralphfjy/article/details/70186787
- RGB Large Digital Clock: https://create.arduino.cc/projecthub/makiko/rgb-large-digital-clock-579e80?ref=tag&ref_id=led&offset=23