This week's assignment is to write an application that interfaces users with an input and/or output device (individual); to compare different tool options (in-group).
* All source files can be downloaded here.
* To keep the momentum of the previous weeks, I tried to write down what I understand about interfaces and communication protocols.
* I need to individually write an application that interfaces users with an input and/or output device. My plan for this week's progress was to write and test the applications with a commercial board. After the lockdown, I will test them with a board I make.
* This week's group assignment is to compare different development tool options.
There was so much to learn this week. I thought this week's content would only revolve around software/application development, but it was actually a lot wider. Hence, in addition to work on the assignments, I would like to research further and correct what I had in mind about interfaces. Allow me to go through a very long note without any images attached, or go straight to the assignments below.
Now I really understand why people need 4 years of university not to get confused when encountering networking terms like interfaces, protocols, buses, ports, connectors, etc. For example, there are so many things covered in just a single USB standard, and I couldn't afford to read all this huge amount of knowledge (my brain was starting to hurt). I could only look for information regarding the differences between these terms, and this Quora thread was a good starting point.
The term interface can have various meanings in different contexts, but all relate to a shared boundary across which two or more separate components of a computer system exchange information. The interfaces can be physical or virtual. A physical interface can be a connector for a cable modem and a virtual interface can be an API that allows the software to communicate with other software.
While an interface refers to the connecting point between 2 physical/virtual objects, a protocol defines rules to be complied with for exchanging information on that connecting point. Having said this, then interface is exactly where the elements communicate, transmit, and receive information. Whereas, a protocol is an agreed method or a guideline of steps for them to be able to understand each other. Devices and computing subsystems are interconnected through interfaces based on specific protocols. For us, the interfaces would be the ears and mouths, or hands in the case of communicating with the protocol of sign language.
A bus is a specific kind of interface and it uses an implementation of some protocols to transfer data between components inside a computer. An example is the bus that connects a CPU to an internal memory within the same motherboard. The CPU knows what to say at what time to access memory and the memory knows how to reply with data when it is requested.
A port is commonly defined as a communication endpoint between the computer and external hardware. A port can refer to either a software port (for example, port 80 is a network port which is a logical number that allows HTTP traffic on a network), or a physical slot of the host computer that matches physical plugs or jacks (USB port, HDMI port, serial port).
In the hardware context, the connector is the unique endpoint of a physical plug or jack. The interface is the meeting point of the connector and the port which is designed in the circuitry of the devices. It includes the design of both the plug and the port, the number and purpose of the wires, and the electrical signals that are passed across them.
Let's take an example of a 5-wire connector. Depending on which pin has which voltages/signaling, and what it is plugged into, the same connector can be used for all sorts of different interfaces - from MIDI ports/interfaces to PC/AT keyboard ports/interfaces. The protocol (that's which pins do what, at what voltages, and how that's interpreted by the computer/device at the end of the cable), however, varies. We cannot plug a MIDI cable to a PC/AT keyboard port and hear something. The two devices must have a protocol in common to speak to each other.
As mentioned above, interface is where the separated components of a computer system communicate, transmit, and receive data. The information exchange can be between software, computer hardware, peripheral devices, humans, and combinations of these. For example, we have hardware (device) interfaces, software interfaces, or user interfaces.
Hardware interfaces exist in many of the components, such as the various buses, ports, storage and I/O devices, etc. that allow physical devices to interact to a computer or other devices. For example, an Arduino Uno board being connected to a USB port is actually connected to the USB interface of the system, or a TV may connect to a Blu-ray player via an HDMI cable (HDMI interface). A hardware interface is described by the mechanical, electrical, and logical signals at the interface and the communication protocol for sequencing them (sometimes called signaling).
Wired hardware interfaces can be parallel with several electrical connections carrying parts of the data simultaneously, or serial where data are sent one bit at a time:
In case of wireless communication, we have network interface card (NIC) and WNIC which are circuit boards that provide networking capabilities for a computer. They may enable a wired Ethernet connection or a wireless connection (such as Wifi or Bluetooth) via a PAN, a LAN or over a large-scale network through IP. These interface devices use an antenna to communicate via microwave radiation.
A software interface may refer to a wide range of different types of interface at different levels: an operating system may interface with pieces of hardware; applications or programs running on the operating system may need to interact via data streams, filters, and pipelines; and in object-oriented programs, objects within an application may need to interact via methods.
Interfaces between software components can provide constants, data types, exception specifications, and method signatures. Sometimes, public/global variables are also defined as part of data interfaces. In some object-oriented languages like Java or C#, the term interface is used to define an abstract type that contains no data (fields) but defines behaviors (methods). An application programming interface (API) is a computing interface to a software component or a system, that defines how other components or systems can use it. A RESTful API is an API that uses HTTP requests to GET, PUT, POST, and DELETE data from the database of an application. These are the concepts that I'm familiar with.
A user interface is a point of interaction between a computer and humans. It includes any number of modalities of interaction where data is transferred between the user and the computer system. UI layers may interact with one or more human senses, including tactile UI (touch), visual UI (sight), auditory UI (sound), etc. This week's assignments mostly revolve around user interfaces.
Composite user interfaces (CUI) are UIs that interact with two or more senses. The most common CUI is a graphical user interface (GUI), which is composed of a tactile UI and a visual UI capable of displaying graphics. When sound is added to a GUI it becomes a multimedia user interface (MUI). There are 3 broad categories of CUI: standard (keyboards, mice, etc.), virtual (VR), and augmented (AR).
I continued to build on top of a program written in the 11th week which I used to play the theme song of Super Mario game. First I added 3 more songs to the program: Harry Potter, Game of Thrones, and Tetris by looking for their melodies and tempos online. This is a cool repository with a collection of many of my favorite songs. However, the way the durations were calculated and how the music was composed vary. Hence, I had to rewrite a bit and it was such a hard job!
The next step was to write the Processing program. Processing is a flexible software sketchbook that allows its users to write code with Java-based syntax within the context of the visual arts. I used to code in Java so it was not a big problem. The Serial library of Processing was used to open a serial communication with the Arduino Uno board through the USB port, and then I could call write()
functions to send the ID of the selected song to the Arduino program.
As shown in the above image, the code will be executed again and again within draw()
function. I made a mistake by using the mousePressed == true
condition instead of the mousePressed()
function, that's why we could see in the console that the songs were repeated. Also, to control the data received from the Arduino side and avoid song repetitions, I sent a songId = 0
to stop the buzzer in between. In the end, here is how data was transferred from Processing to Arduino:
Here you go the long but simple programs I wrote:
/*
* convert notes to frequency
*/
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
/*
* pin variables
*/
#define buzzer A0
/*
* data received from Processing app
*/
char songId;
/*
* melody and tempo of Super Mario
*/
int mario[] = {
NOTE_E7, NOTE_E7, 0, NOTE_E7, 0, NOTE_C7, NOTE_E7, 0, NOTE_G7, 0, 0, 0, NOTE_G6, 0, 0, 0,
NOTE_C7, 0, 0, NOTE_G6, 0, 0, NOTE_E6, 0, 0, NOTE_A6, 0, NOTE_B6, 0, NOTE_AS6, NOTE_A6, 0,
NOTE_G6, NOTE_E7, NOTE_G7, NOTE_A7, 0, NOTE_F7, NOTE_G7, 0, NOTE_E7, 0, NOTE_C7, NOTE_D7, NOTE_B6, 0, 0
};
int mario_tempo[] = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
};
/*
* melody and tempo of Tetris
*/
int tetris[] = {
NOTE_E5, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_A4, NOTE_A4, NOTE_C5, NOTE_E5, NOTE_D5, NOTE_C5,
NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_C5, NOTE_A4, NOTE_A4, NOTE_D5, NOTE_F5, NOTE_A5, NOTE_G5, NOTE_F5,
NOTE_E5, NOTE_C5, NOTE_E5, NOTE_D5, NOTE_C5, NOTE_B4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_C5, NOTE_A4, NOTE_A4, 0
};
int tetris_tempo[] = {
4, 8, 8, 4, 8, 8, 4, 8, 8, 4, 8, 8, -4, 8, 4, 4, 4, 4, 3,
-4, 8, 4, 8, 8, -4, 8, 4, 8, 8, 4, 8, 8, 4, 4, 4, 4, 4, 4
};
/*
* melody and tempo of Game of Thrones
*/
int got[] = {
NOTE_G4, NOTE_C4, NOTE_DS4, NOTE_F4, NOTE_G4, NOTE_C4, NOTE_E4, NOTE_F4,
NOTE_G4, NOTE_C4, NOTE_DS4, NOTE_F4, NOTE_D4, NOTE_G3, NOTE_AS3, NOTE_C4, NOTE_D4,
NOTE_G3, NOTE_AS3, NOTE_C4, NOTE_D4, NOTE_F4, NOTE_AS3, NOTE_DS4, NOTE_D4, NOTE_F4,
NOTE_AS3, NOTE_DS4, NOTE_D4, NOTE_C4
};
int got_tempo[] = {
2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2,
2, 1, 1, 2, 2, 1, 1, 4,
4, 4, 1, 1, 4, 4, 1, 1, 4
};
/*
* melody and tempo of Harry Potter
*/
int harrypotter[] = {
NOTE_D4, NOTE_G4, NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_D5, NOTE_C5, NOTE_A4, NOTE_G4, NOTE_AS4, NOTE_A4,
NOTE_F4, NOTE_GS4, NOTE_D4, NOTE_D4, NOTE_G4, NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_D5,
NOTE_F5, NOTE_E5, NOTE_DS5, NOTE_B4, NOTE_DS5, NOTE_D5, NOTE_CS5, NOTE_CS4, NOTE_B4, NOTE_G4
};
int harrypotter_tempo[] = {
4, -4, 8, 4, 2, 4, -2, -2, -4, 8, 4, 2, 4, -2, 4,
-4, 8, 4, 2, 4, 2, 4, 2, 4,
-4, 8, 4, 2, 4, -2
};
/*
* begin serial communication at the same baud rate with the Processing program
*/
void setup(void)
{
pinMode(buzzer, OUTPUT);
Serial.begin(115200);
}
/*
* receive songId from Processing app
* and pass it as an argument to sing() function
*/
void loop()
{
if (Serial.available())
{
songId = Serial.read();
}
sing(songId);
// avoid repeated songs
songId = '0';
delay(2000);
}
/*
* use tone() to play songs with the buzzer: targeted pin, frequency, duration
* songId is the parameter
*/
void sing(char id)
{
if (id == '1')
{
int duration = 0;
for (int i = 0; i < (sizeof(mario) / sizeof(int)); i++) {
// to calculate the note duration, take one second divided by the note type
// e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
duration = 1000/mario_tempo[i];
tone(buzzer, mario[i], duration);
// to distinguish the notes, set a minimum time between them
delay(duration * 1.30);
// stop the tone playing
noTone(buzzer);
}
delay(10);
}
else if (id == '2')
{
int duration = 0;
for (int i = 0; i < (sizeof(tetris) / sizeof(int)); i++) {
duration = 1800 / abs(tetris_tempo[i]);
if (tetris_tempo[i] < 0) {
// notes are represented with positive durations are regular note, just proceed
// dotted notes are represented with negative durations
// increases the duration in half for dotted notes
duration *= 1.5;
}
tone(buzzer, tetris[i], duration);
delay(duration * 1.10);
noTone(buzzer);
}
delay(10);
}
else if (id == '3')
{
int duration = 0;
for (int i = 0; i < (sizeof(got) / sizeof(int)); i++){
duration = got_tempo[i] * 250;
tone(buzzer, got[i], duration);
delay(duration);
noTone(buzzer);
}
delay(10);
}
else if (id == '4')
{
int duration = 0;
for (int i = 0; i < (sizeof(harrypotter) / sizeof(int)); i++){
duration = 1600 / abs(harrypotter_tempo[i]);
if (harrypotter_tempo[i] < 0) {
duration *= 1.3;
}
tone(buzzer, harrypotter[i], duration);
delay(duration * 1.10);
noTone(buzzer);
}
delay(10);
}
}
/*
* declare an object of Serial class
* for sending and receiving data over serial communication protocol
* in this case I called it "Uno"
* because my USB port was connected to an Arduino Uno board
*/
import processing.serial.*;
Serial Uno;
/*
* declare the icons used
*/
PImage icon1;
PImage icon2;
PImage icon3;
PImage icon4;
/*
* load icons and open the serial connection
*/
void setup() {
size(700, 700);
background(230);
/*
* load images in the "data" folder
*/
icon1 = loadImage("mario.png");
icon2 = loadImage("tetris.png");
icon3 = loadImage("harry-potter.png");
icon4 = loadImage("got.png");
/*
* add arguments for the serial communication: parent, port name, baud rate
* use the same baud rate with the Arduino program
*/
Uno = new Serial(this, "/dev/cu.usbmodem14301", 115200);
}
/*
* similar to loop() in Arduino
*/
void draw() {
image(icon1, 120, 120);
image(icon2, 450, 120);
image(icon3, 120, 400);
image(icon4, 450, 400);
}
/*
* function called whenever the mouse is clicked
*/
void mousePressed() {
Uno.write(check());
Uno.clear();
}
/*
* send the id of the song selected to the Arduino program
*/
char check() {
if (120 < mouseX && mouseX < 270 && 120 < mouseY && mouseY < 270) {
println("Super Mario Bros");
return '1';
}
else if (450 < mouseX && mouseX < 600 && 120 < mouseY && mouseY < 270) {
println("Tetris");
return '2';
}
else if (120 < mouseX && mouseX < 270 && 400 < mouseY && mouseY < 550) {
println("Harry Potter");
return '4';
}
else if (450 < mouseX && mouseX < 600 && 400 < mouseY && mouseY < 550) {
println("Game of Thrones");
return '3';
}
else {
return '0';
}
}
It's time for music!
After being introduced to Pygame by my classmate David Prieto, I found it really cool and the way it works is kinda easy to understand. Since I have never programmed anything properly in Python, I decided to give it a try. Pygame is a cross-platform set of Python modules designed for writing video games. It includes computer graphics and sound libraries designed to be used with the Python programming language. To install Pygame, I ran $ pip install pygame in Terminal and then wrote a Flappy Bird clone. In case you didn't know, Flappy Bird was written by a Vietnamese developer. Also, I had developed a Flappy Bird clone using Android Studio before, so the task was simply to TRANSLATE Java to Python.
I started with writing the classic program of making the bird jump by pressing the space bar. In order to get used to the new Python language, I referred to some online projects, for example here and here. I tried to rewrite the program in a simpler way, and it worked perfectly, so I could get rid of one debug layer. The code will be explained below.
The next step was to use pySerial library to access the data received from the USB port. First I used the exact Arduino program I wrote in the 9th week to begin the serial communication and printed the distance values so that the Python program could read it. Next, I imported the pySerial library in my Python code and opened a serial communication with the same port and baud rate as in the Arduino program. With this, I could read the data printed, converted them to numbers, and used them to adjust how high the bird could jump. I then faced a problem that the bird was not pulled down as law of gravity but kept flying higher and higher. The measured data was also really unstable:
After asking David to take a look at my code, he suggested that maybe that was a problem of trying to read the sensor's data twice before calling the jump()
function: once when I pressed the space bar, and once when the data is available. I simply deleted the extra Bird.read()
line, and it worked (not like a charm because I was so bad of playing this game, and the accuracy of the sensor was not really high)!
To stabilize the readings and make it smoother, I referred to the filtering technique introduced by Oscar here. Basically, the program reads repeatedly from the sensor, calculates a running average and prints it to serial monitor. Below is the final working code with detailed comments:
/*
* pin variables
*/
int trig = 32;
int echo = 35;
/*
* variables for filtering readings
*/
int readings[5]; // array of readings
int currentIndex = 0; // index of the current reading
int total = 0;
int average = 0;
/*
* begin serial and initialize all readings to 0
*/
void setup() {
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
Serial.begin(115200);
for (int i = 0; i < 5; i++) {
readings[i] = 0;
}
}
/*
* filter and print values
*/
void loop() {
// subtract the last reading
total = total - readings[currentIndex];
// read distance from the sensor
readings[currentIndex] = readDistance();
// calculate total value
total = total + readings[currentIndex];
if (currentIndex >= 5) {
currentIndex = 0;
}
// calculate average value
average = total / 5;
Serial.println(average);
delay(1);
}
/*
* read distance values
*/
int readDistance() {
digitalWrite(trig, LOW);
delayMicroseconds(5);
digitalWrite(trig, HIGH);
delayMicroseconds(20);
digitalWrite(trig, LOW);
duration = pulseIn(echo, HIGH);
distance = (duration * 0.034)/2;
return distance;
}
/*
* libraries incl. pySerial and Pygame
*/
import os
import sys
import serial
import pygame, math
from random import randint
from time import sleep
/*
* initialize Pygame
*/
pygame.init()
/*
* useful constant variables
* since Pygame doesn't have a collision detection feature
*/
WIDTH = 1000
HEIGHT = 580
BIRD_WIDTH = 50
BIRD_HEIGHT = 36
PIPE_WIDTH = 75
PIPE_LENGTH = 450
PIPE_GAP = 10
/*
* loading graphics
*/
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Flappy Bird!")
bird = pygame.image.load('bird.png')
background = pygame.image.load('bg.png')
pipeBottom = pygame.image.load('pipe.png')
pipeTop = pygame.transform.rotate(pipeBottom, 180)
font = pygame.font.SysFont('Comic Sans MS', 30)
/*
* open serial connection with the Arduino Uno board
* if there are more than 10 values in queue, reset input buffer
*/
uno = serial.Serial("/dev/cu.usbmodem14301", 115200)
uno.setDTR()
uno.flush()
if (uno.in_waiting > 10):
uno.reset_input_buffer()
/*
* setup the game: game states, scores, counters, etc.
*/
def setupGame() :
global gameRun
gameRun = True
global gameOver
gameOver = False
global gameStart
gameStart = False
global gameRunCount
gameRunCount = 0
global score
score = -2
global pipes
pipes = []
/*
* create a new Bird object with an initial position (250,250)
*/
Bird.birdX = 250
Bird.birdY = 250
Bird.vel = 0
/*
* Bird class
*/
class Bird :
birdX = 250
birdY = 250
distanceVal = 0
vel = 0
/*
* read data from serial communication and convert to integers
*/
def read() :
strDistance = uno.readline().strip().decode('utf-8')
// handle the case of missing data
if not strDistance:
Bird.distanceVal = 0
else:
Bird.distanceVal = int(strDistance)
// trigger a custom USEREVENT when data is available
if Bird.distanceVal != 0 :
jump = pygame.event.Event(pygame.USEREVENT)
pygame.event.post(jump)
/*
* filter the value and adjust the velocity of the bird
*/
def jump() :
if 3 < Bird.distanceVal < 30:
Bird.vel = -Bird.distanceVal
else:
Bird.vel = 0
/*
* update the bird position
*/
def update() :
if gameStart :
if Bird.birdY < (HEIGHT - BIRD_HEIGHT) :
Bird.birdY += Bird.vel
Bird.vel += 1
else :
Bird.birdY = (HEIGHT - BIRD_HEIGHT)
die()
if Bird.birdY < 0 :
Bird.birdY = 0
Bird.vel -= 0
else :
Bird.birdY = 250 + math.sin(gameRunCount/10) * 15
/*
* Pipe class
*/
class Pipe() :
def __init__(self, direction, x, length) :
self.direction = direction
self.pipeX = x
self.pipeLength = length
/*
* update the pipes' positions as the bird moves
*/
def update(self) :
if self.direction == "BOTTOM" :
screen.blit(pipeBottom, (self.pipeX , HEIGHT - self.pipeLength))
else :
screen.blit(pipeTop, (self.pipeX , self.pipeLength - PIPE_LENGTH))
if not gameOver :
self.pipeX -= PIPE_GAP
/*
* detect collision by comparing (x,y) of the bird and (x,y) of the pipes
*/
def checkCollide(self) :
if self.direction == "TOP" :
if Bird.birdX + BIRD_WIDTH >= self.pipeX and self.pipeX + PIPE_WIDTH >= Bird.birdX :
if Bird.birdY <= self.pipeLength :
die()
else :
if Bird.birdX + BIRD_WIDTH >= self.pipeX and self.pipeX + PIPE_WIDTH >= Bird.birdX :
if Bird.birdY + BIRD_HEIGHT >= HEIGHT - self.pipeLength :
die()
/*
* function to generate a random pair of pipes
* when the bird passes a pair of pipes, score++
*/
def generatePipes() :
random = randint(100, 200)
pipes.append(Pipe("TOP", 900, random))
pipes.append(Pipe("BOTTOM", 900, HEIGHT - (random + BIRD_HEIGHT * 4)))
global score
score += 1
/*
* game over function
*/
def die() :
global gameOver
gameOver = True
gameRun = False
/*
* call the setupGame() function to prepare the game
*/
setupGame()
/*
* execute codes while the game state is runned
*/
while gameRun:
pygame.time.delay(5)
/*
* listen to events: ESC key, space board, and the custom USEREVENT
*/
for event in pygame.event.get() :
if event.type == pygame.KEYDOWN :
if event.key == pygame.K_ESCAPE :
gameRun = False
elif event.key == pygame.K_SPACE :
if not gameStart :
gameStart = True
if not gameOver :
Bird.read()
Bird.jump()
elif event.type == pygame.QUIT :
gameRun = False
elif event.type == pygame.USEREVENT :
if not gameOver :
Bird.jump()
/*
* display the background, generate pipes, update the bird position
*/
screen.blit(background, (0,0))
if gameRunCount % 45 == 0 and gameStart :
generatePipes()
for p in pipes :
p.update()
p.checkCollide()
Bird.update()
screen.blit(bird, (Bird.birdX, Bird.birdY))
/*
* update distances for debugging
*/
distance = font.render(str(Bird.distanceVal), False, (0, 0, 0))
screen.blit(distance, (20, 45))
/*
* update scores
*/
scoreboard = font.render(str(score), False, (255, 255, 255))
if score > -1 :
screen.blit(scoreboard, (20, 20))
pygame.display.update()
if not gameOver:
gameRunCount += 1
/*
* quit Pygame
*/
pygame.quit()
I re-uploaded the code to the ESP32 board designed during the 9th week. It's totally impossible to take a picture and win a high score, but in general, the result are the same. Just try to move my hand poco a poco!
To make this part more like a "group" assignment, I included here the development tools that my classmates went through in addition to what I did. All of them tried many workflows and made amazing programs, but I limited the list to workflows that are different from mine.
Student | Application | Input device | Output device | Development tools | Language | Development board | Device interface | What I find interesting |
---|---|---|---|---|---|---|---|---|
Myself | Ringtone collection | - | Passive buzzer | Processing | Java | Arduino Uno | Processing's Serial | Well-documented, lots of tutorials, is inexhaustible for bigger projects with lots of libraries |
Myself | Flappy Bird | Ultrasonic sensor | - | Pygame | Python | My Final Project's ESP32 board | pySerial | Many modules specialized for graphic games |
Benjamin Scott | Wavemaker | Inertial Measurement Unit (IMU) | - | WebSocket + Progressive Web App + P5.js | JavaScript | Barduino | WebSocket's broadcast message | Full-duplex asynchronous messaging |
Antoine Jaunard | Experimental music instrument | Buttons, light & sound sensors | - | openFrameworks | C++ | Circuit Playground Express | Serial | No specific IDE, clean and simple projects containing both Arduino and oF programs |
There're indeed many more tools I'd love to try for this week's assignment, for example Unity or Blynk. However, at this point, I decided that application programming is not really my focus while participating the Fab Academy. Hence, I'm quite OK with what I did this week.