Final Project Documentation

Farsi Display on Arduino: calendar and a dinosaur game

Describe your concept

The premise of my project is very simple: construct and display Persian/Arabic letters on Arduino LCD (16×2), with the main purpose of displaying the Persian calendar date (Hijri Shamsi) and making a little dinosaur game where the barriers are Farsi letters (or a block).

How does the implementation work?

    • Description of interaction design
    • Description of Arduino code
    • Description of p5.js code
    • Description of communication between Arduino and p5.js

Interaction design:

p5.js is where the user input is stored and communicated to Arduino over serial operations. P5.js would take input based on the button the user clicks:

Arduino code:

Arduino code reads serial input and does one of three things below:

    1. Display a welcome text to the user
    2. Construct Farsi letters and display the Shamsi date on the LCD
    3. Call the main game function

For the game, I consulted the code from the Arduino project hub I used some functions for moving the barriers to the left of the screen and controlling the collision.

Link to Arduino code

p5.js code:

Establishes the handshake between p5 and Arduino. Based on the button the user clicks, p5 sends a unique digit to Arduino and Arduino will take it from there.

Link to p5.js code

What are some aspects of the project that you’re particularly proud of?

My original idea was to make a Farsi letters reshaper/constructer only, but I decided to bring more interaction to the project by adding a little game. I enjoyed making the byte arrays for different Farsi letters and refining them so that they look better when put together in a word. I’m also proud of the little box I made with the help of Professor Shiloh. I had never worked with wood before and it was last minute but it turned out fine and people found it intuitive to interact with the button and LCD once they were made into the box.

What are some areas for future improvement?

There are two limitations:

    1. The 16×2 LCD is very limited: in terms of how many custom characters you can make (only 8) and also in terms of how many characters it displays in general (32). A bigger LCD would solve this problem and improve the project.
    2. Serial input only reads English: I tried sending Farsi letters over Serial communication which resulted in a gibberish serial read by Arduino. It might be possible to send English input and transliterate it in the Arduino and display it, but not all letters can be mapped.

Demo:

final project progress

name of the project: 

lcd game & shamsi calendar

final project finalized:

p5.js menu gives the user 3 options:

    1. display random quotes (farsi and english) on lcd
    2. display hijri shamsi date and time on lcd
    3. play a little game on the lcd – using the switch

arduino & P5 handshake:

p5.js will record user’s choice from the menu and sends it to arduino to be displayed on lcd.

p5 code can be found here.

demo:

what’s left:

i would like to make a little box to hold everything in. 

Serial Communication Exercises

[in collaboration with Vivianna]

Exercise 1:

Make something that uses only one sensor  on arduino and makes the ellipse in p5 move on the horizontal axis, in the middle of the screen, and nothing on arduino is controlled by p5:

Exercise 2:

Make something that controls the LED brightness from p5:

Exercise 3:

Take the gravity wind example (https://editor.p5js.org/aaronsherwood/sketches/I7iQrNCul) and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor:

Final Project [solo]- Arduino Farsi Display

The concept:

The premise of my project is very simple: construct and display Persian/Arabic letters on Arduino LCD, with the main purpose of displaying the Persian calendar date (Hijri Shamsi) – as a gift to my dad (an older generation electrical engineer). But you can input anything through p5.js to be displayed on the LCD.

Note: Hijri Shamsi is an ancient solar calendar and one of the oldest in the world. It begins on the March equinox as determined by astronomical calculation to mark the beginning of spring, where we celebrate new beginnings (Nowruz). The months’ names are the same as ancient Zoroastrian names (represented with Farsi letters, read right to left). The days are represented using Hindu-Arabic numerals.

Sample digital representation of Hijri Shamsi date
Sample box to hold the LCD

Like all sophisticated projects, however, the devil is in the details.

Displaying special characters on LCD:

lcd.print() function only supports ASCII characters. A series of calculations and mappings are involved in order to display special characters.

LCD 16x2 can display 32 characters (2 rows, 16 columns). And each character is composed of 40 pixels (8 rows and 5 columns). You will have to write your own bit-level custom character code. Take a look at the example below:
// %%%%%%%%%%%%%%%%
byte customChar[8] = {
    0b00000,
    0b01010,
    0b11111,
    0b11111,
    0b01110,
    0b00100,
    0b00000,
    0b00000
};
// %%%%%%%%%%%%%%%%

The good news is that you can make your own letters or special characters (and fonts) on a matrix on this website and get the HEX representation for your letters.

hex representation of letter م

This is the Persian alphabet matrix (credits to gurgleapps) that I will use in this project:

// %%%%%%%%%%%%%%%%
const unsigned char pers_char [71][8] = {
    0x00, 0x1C, 0x20, 0x08, 0x08, 0x08, 0x08, 0x00, 	//0	alef1
    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 	//1	alef2 
    0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 	//2	alef3
    0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x02, 	//3	be1
    0x00, 0x00, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x10, 	//4	be2
    0x00, 0x00, 0x00, 0x01, 0x01, 0x06, 0x00, 0x07,    	//5	pe1
    0x00, 0x00, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x38, 	//6	pe2
    0x00, 0x03, 0x00, 0x01, 0x01, 0x06, 0x00, 0x00, 	//7	te1
    0x00, 0x14, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x00, 	//8	te2
    0x02, 0x05, 0x00, 0x01, 0x01, 0x06, 0x00, 0x00, 	//9	the1
    0x08, 0x14, 0x40, 0x81, 0x81, 0x7E, 0x00, 0x00, 	//10 	the2
    0x00, 0x00, 0x0C, 0x12, 0x01, 0x3E, 0x00, 0x04, 	//11	jim1
    .
    .
    .

    0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 	//69	slash
    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 	//70	backslash
};
// %%%%%%%%%%%%%%%%

And the final step is presenting the character on the LCD. If you look at the heart example above, you see a bit-level representation of the character, but gurgleapps gives us a set of hex values. So some conversion needs to happen here. Each hexadecimal digit represents four bits (binary digits). We could write a simple but useful function that converts each hex value to bitmap characters and [depending on cursor position] display the custom bitmap.

p5.js:

p5.js is where the user input is stored and communicated to Arduino over serial operations. P5.js would take the input in English, convert it into Farsi, and send it to Arduino to display on LCD. The user has to let the program know, after inputting the text, whether they want the program to translate or transliterate the text to Farsi.

Note:

This is ambitious; if the translation part does not fit into the timeframe, p5.js will only convert computer date to Shamsi date, transliterate it, and display on the LCD.

Challenges:

The biggest challenge is perhaps constructing words (my name consists of letters م ر ی م. But almost all letters have a compact form that you have to use when writing words, so my name reads مریم ). This explains why I have several variations of one letter in the hex matrix. The way I would approach this is through many rounds of trial and error and experimenting with spacing and character sizes.

The next challenge would be displaying each character in a reverse manner (the letters read from right to left). The cursor has to be reversed every time there is a character input.

The 16×2 screen is limited and there will be character overflow and boundary issues, but the main goal here is to display the date and the LCD offers more than enough space for that purpose.

Timeline:

The week of November 28th: Experiment with displaying standalone letters. Get a good idea of the 16×2 space and the position of the cursor.

The week of December 5th: Get input from p5.js. Ensure the characters form words in a correct and consistent manner.

The week of December 12th: Experiment with adding colors. Build a frame for the LCD (a small structure with a stand so it could be put on disk). Prepare for the showcase.

IM Assignment Week 10 – Maryam and Ian

Christmas is in the Air

Concept: 

Christmas is growing closer by the day, and where’s the festive mood without some carols? In this project, we are using switches, a piezo buzzer, and a potentiometer that has the five notes needed to play Jingle Bells. Switches 1 through 5 represent nodes C5, D5, E5, F5, and G5 in order. The LED on pin 13 lights up when you switch between nodes. The potentiometer lets you control the tempo. If you are not familiar with the notes, you follow the order below to play the song.

%%%%%%%%%%%

3,3,3

3,3,3

3,5,1,2

3

4,4,4,4,

4,3,3,3,3

3,2,2,3

2,5

%%%%%%%%%%%

The Switches:

In the beginning, we thought about using distance measurement sensors. We would then map different nodes of the song to the numbers we read from the sensor in a way that the tempo would increase and decrease as you get closer or farther from the sensor. But we wanted defined and distinct sounds and a more exact mapping so we decided to go with a digital I/O instead. We were also aiming to use the potentiometer to control volume initially but the buzzer was acting strange with the signal change in the potentiometer. Later we figured it was better and more practical to control the tempo via a potentiometer (the default tempo is 8).

The five nodes in the program C5, D5, E5, F5, and G5 are defined in “pitches.h”. The song sheet is converted to code tokens and provided by Project Hub and there is also a tutorial on how to do it yourself by Nathan Seidle on Github.

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void loop() {

  int knob = analogRead(A2);
  Serial.println(knob);

  tempo = map(knob, 0, 1024, 60, 255)/15;

  switchOne = digitalRead(2);
  switchTwo = digitalRead(3);
  switchThree = digitalRead(4);
  switchFour = digitalRead(5);
  switchFive= digitalRead(6);
  
  if (switchOne == HIGH) {
    sing(1);
  } else if (switchTwo == HIGH) {
    sing(2);
  } else if (switchThree == HIGH) {
    sing(3);
  } else if (switchFour == HIGH) {
    sing(4);
  } else if (switchFive == HIGH) {
    sing(5);
  }
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Full code on p5.js can be found here.

The Potentiometer:

After realizing that using the potentiometer for volume control would be difficult to do with our buzzer, we decided to use it as a means to control the tempo settings (the length of each note) of our instrument. This part of the code is used to achieve this:

void loop() {
//Potentiometer Value is Assigned to knob
  int knob = analogRead(A2);
//Tempo is Remapped and Divided
  tempo = map(knob, 0, 1024, 60, 255)/15;
. . .
//Tempo is Used to Determine Note Duration
  int noteDuration = 1000 / tempo;
  tone(melodyPin, c5, noteDuration);
}

With each loop, the value of the potentiometer is read and updated to the integer knob, which is subsequently remapped and divided; this value is then called to calculate noteDuration, which is used as a parameter that determines the length of the note played though tone(). According to this code, turning the potentiometer clockwise increases the length of a single note, while turning it counterclockwise achieves the opposite. With the potentiometer set up, our project can emit tones of differing pitches and lengths, allowing us to play neat little songs like Jingle Bells!

Demo:

Reflection:

It was an enjoyable and rewarding experience to brainstorm and collaborate on this project as a group! It definitely helped to have each other to consult (and commiserate with) when we were stuck at certain points. If we were to have more time, we would have liked to decorate our instrument with LEDs that correspond to the notes being played; regardless, we’re very proud with what we were able to achieve with this project. With each project, our familiarity with Arduino grows—and in this case, so did our teamwork. Coupled with a nice carol, this project really harnesses the Christmas spirit!

Week 9 Assignment – Arduino: analog input & output

Jewel Detector Doll

The Concept:

This week’s assignment was about combining digital and analog sensors (switch and potentiometer) to control the behavior of at least two LEDs in a creative way. I figured that using more than two LEDs would lead to too many cables on the board so I decided to go with only two LEDs.

To control the two LEDs with analog and digital sensors, I used my doll (which I’m sometimes scared of because it looks too real) as a jewel detector. If you give the doll gold jewelry (or steel or any type of conductor really, but let’s stick to gold vs non-gold for the purpose of the story), the green LED will start blinking. My job as an assistant is to be on guard; if the green light is blinking everything is fine and the jewelry is gold. But if the light is not turning on and I sense suspicious activity, I press the switch and the red LED turns on.

Breadboard Setup:

Code Highlight:

The LED will only blink if the number received from the potentiometer is greater than 500:

// %%%%%%%%%%%%%%%%%%%%%%%%%%
// convert from 0-1023 proportional to the number of a number of from 0 to 255
if (0 >= inputValue && inputValue <= 500) {
// convert from 0-1023 proportional to the number of a number of from 0 to 255
  outputValue = map(inputValue, 0, 500, 0, 255); 
}

else if(500 < inputValue && inputValue <= 1023) {
  // turn the LED on (HIGH is the voltage level)
  digitalWrite(ledPin, HIGH);   
  // wait for a second
  delay(100);
  // turn the LED off by making the voltage LOW                       
  digitalWrite(ledPin, LOW);    
  delay(100);   
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%

Production:

A short video of how the jewel detector works:

 

 

Midterm Project: Minion Puzzle

a snapshot from the puzzle

Inspiration:

My inspiration for this game was my puzzle assignments from Intro to CS that involved matrices calculations and boards (tik tac to, connect 4, etc.) and also this artwork in the Arts Center hallway:

The idea of the game is very simple. Just like the frame above, there is only one empty tile (randomly placed as a result of shuffling). Click on any empty tile’s adjacent cell to swap the two. Continue till all the pieces are in place!

Implementation:

Two (huge) classes Puzzle and Tile, seven methods, eight functions, 292 lines, and lots of debugging prints in between. 

The basic idea is how you think about any puzzle; we need to create a board, divide it into cells (that can be replaced or swapped), assign each tile a pattern in such a way that the whole board represents a complete photo, then shuffle the cells and try to solve the puzzle. Each puzzle has a different set of rules; in this puzzle, you have one empty cell and are allowed to swap it with an adjacent cell.

The tiles:

It starts with a single tile. The tile class creates an object Tile with the appropriate properties. Each tile object has a specific position on the board tile[row][column]:

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class Tile {
  
  constructor (r, c, img_index, numRows, numCols) {   
    this.r = r;
    this.c = c;
    this.numRows = numRows;
    this.numCols = numCols;
    this.img_index = img_index;
    this.img = loadImage ('resources/' + this.img_index+ '.png');
    // print("image index is: ", this.img_index);
  }
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Each tile object is also assigned an image index ranging from 0-15, and the way we are displaying it is by multiplying the tile’s row and column number by its size (defined at the beginning of the program):

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
display_tile () { 
  if (this.img_index != (this.numRows*this.numCols) - 1) {
  // print("image index is: ", this.img_index)
  image(this.img, this.c*my_width, this.r*my_height, my_width, my_height);
  }
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

The board (matrix):

We are now ready to populate an array of arrays with our tile objects. The Puzzle class has a createBoard() method that loops through the range of numRows and numCols (passed as arguments in the Puzzle object constructor). A temporary array is created for each row in numRows, and then numCols arrays (numbers of columns) are pushed into the temp array. Then a new Tile object is created for each cell. Then we push this temporary list to the board (every tile is in the correct place at this point). Now before you exit the function, you shuffle all the tiles.

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    createBoard () {
      this.board = [];
      
      for (var r=0; r<this.numRows; r++) {
        // for each row create a temp list
        var tempList = [];
        
        // add numCols tiles to the list
        for (var c=0; c<this.numCols; c++) {
          // r*c is the image index
          var new_tile = new Tile(r, c, r*this.numCols+c, this.numRows, this.numCols);
          tempList.push(new_tile);
        }
        
        // push the list to the board
        this.board.push(tempList);
      }
      this.shuffle_tiles();
    }
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Shuffling tiles:

Picking random values for any tile’s [r] and [c] values (ranging from 0 to 4). Identify its neighbors -> [[0,-1], [1,0], [0,1], [-1,0]]. Swap the tile with a neighbor from this list (also random). 

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    shuffle_tiles () {
      
      // var current_r = this.numRows-1;
      // var current_c = this.numCols-1;
      var current_r = int(random(0,4));  // initially 0-3, left most cells or right most? 
      var current_c = int(random(0,4));      

      var neighbors = [[0,-1], [1,0], [0,1], [-1,0]];
      
      // increase s to have a more standard shuffle - was 20 initially
      for (var s=0; s<10; s++) {
        var empty_tile = this.board[current_r][current_c];
        var shuffling = random(neighbors);

        var destination_r = current_r + shuffling [0];
        var destination_c = current_c + shuffling [1];

        while (destination_r < 0 || destination_c < 0 || destination_r > this.numRows-1 || destination_c > this.numCols-1) {
          shuffling = random(neighbors);
          destination_r = current_r + shuffling [0];
          destination_c = current_c + shuffling [1];
        }

        var new_tile = this.board[destination_r][destination_c];
        
        // print("Before swap: " + str(this.board [current_r][current_c].img_index) + ", " + str(this.board [destination_r][destination_c].img_index));
        
        var temp = empty_tile.img_index;
        empty_tile.img_index = new_tile.img_index;
        new_tile.img_index = temp;

        // print("After swap: " + str(this.board [current_r][current_c].img_index) + ", " + str(this.board [destination_r][destination_c].img_index));

        current_r = destination_r;
        current_c = destination_c;

        for (var r=0; r<this.numRows; r++) {
          for (var c=0; c<this.numCols; c++) {
              var the_tile = this.board[r][c];
              the_tile.img = loadImage ('resources/'+str(the_tile.img_index)+'.png');
          }
        }
      }
    }
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Swapping tiles:

Method tile_empty_adj() returns two important values: the current empty tile (empty tile has a fixed index of [3][3], but it moves around as a result of shuffle), and also a list of empty tile’s neighbors.

We record mouse[x][y] when a click happens on the empty cell’s neighbors and swap their img_index so at the next iteration of draw() when the display() method is called, the tiles would be switched and now you have a new empty cell. Repeat process.

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    swap(nonempty, empty) {
      // takes coordinates of two tiles, swap their index
      var empty_tile = this.board[empty[0]][empty[1]];
      // print("this is empty tile & img index: ", empty_tile, empty_tile.img_index);
      var new_tile = this.board [nonempty[0]][nonempty[1]];
      // print("this is new tile & img index: ", new_tile, new_tile.img_index);

      var temp = empty_tile.img_index;
      empty_tile.img_index = new_tile.img_index;
      new_tile.img_index = temp;


      var tmp=new_tile.img;
      new_tile.img = empty_tile.img;
      // loadImage ('resources/'+str(new_tile.img_index)+'.png');
      empty_tile.img = tmp;
      // loadImage ('resources/'+str(empty_tile.img_index)+'.png');
      
      // print("after swap: ", empty_tile, empty_tile.img_index);
      // print("after swap: ", new_tile, new_tile.img_index);

      for (var r=0; r<this.numRows; r++) {            
        for (var c=0; c<this.numCols; c++) {
          // print(r,c, this.board[r][c].img_index);
          if (this.board[r][c].img_index != r*4 + c) {
              return false;
          }
        }
      }

      this.win = true;
      print ("won game!");
      this.win_sound.play();
    }
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function mouseClicked () {
  
  var empty, adj, empty_adj; 
  empty_adj = my_puzzle.tile_empty_adj();

  empty = empty_adj[0];
  adj = empty_adj[1];
  // print("adjacent cells: ", adj);

  mouse = [int(mouseY/my_height), int(mouseX/my_width)];

  // print(mouse);
  for(var i=0; i<adj.length;i++) {
    if(mouse[0] == adj[i][0] && mouse[1] == adj[i][1]) {
      // print("we are here in the swap call\n");
      // switch the empty and non-empty slots
      my_puzzle.swap(mouse, empty);
      // my_puzzle.display();
    }
  }
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Win conditions:

You win if ALL the tiles in the board have the img_index initially assigned to them e.g. tile[0][0] -> img_index 0, tile[2][3] -> img_index 12 and so on. The empty cell belongs to the last tile (tile[4][4]) and that’s where it should end up for the win condition to be true.

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      for (var r=0; r<this.numRows; r++) {            
        for (var c=0; c<this.numCols; c++) {
          // print(r,c, this.board[r][c].img_index);
          if (this.board[r][c].img_index != r*4 + c) {
              return false;
          }
        }
      }

      this.win = true;
      print ("won game!");
      this.win_sound.play();
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Gameplay:

I tried to keep the instructions very minimal:

1) User is presented with an instructions screen that they can go back to at any point in the game by pressing i (i = instructions)

2) User can start the game by pressing p (p = puzzle)

3) User has the choice to play the minions’ music or mute it while they solve the puzzle (it has a low amplitude anyway). (m = mute, u = unmute)

4) In some rounds the shuffling is very complicated (due to randomness) and the user might not want to spend a lot of time on solving it (e.g. for playtesting purposes). The user has the option to reshuffle the board by pressing s (s = shuffle).

Embedded sketch:

Improvements:

Currently, I’m working on writing a function that slices any image into X equal parts (very useful for puzzle purposes). This can extend the current program from a minion puzzle to any puzzle of the user’s choosing. While this function is easy to implement, the next step that involves saving each slice (of image) back to the assets folder is a bit tricky and needs some research. But overall I think the createBoard()/swap()/shuffle()/display() methods are very extendible and are basic foundations for many board games.

[the end]

Assignment 5: Generative Text Output

Concept

For this assignment, I decided to develop a simple generative text output program through a textbox. this textbox takes user input and displays them and has the following functionalities:

  1. User can use any language keyboard to enter text
  2. User input is stored letter by letter (except action keys e.g. Shift, Backspace, Enter, etc. which is stored as one keystroke/one word)
  3. User can enter capital letter words by pressing Shift + letter or by activating Caps Lock
  4. User can delete their input letter by letter using Backspace
  5. User can clear the whole text box using the <<clear textbox>> button

Code highlight

For the implementation of the textbox, I decided to not use any input functions and make it a bit more interesting. I’m using the function KeyPressed()  to store any key pressed by the user. The reason I picked KeyPressed() was that, unlike other functions such as KeyTyped() and KeyCode(), it recognizes the action keys such as Shift, Backspace, Control, Enter, Alt, etc.  These action keys are useful for implementing features such as erasing, moving to the next line, typing capital letters, etc. In this program, only the erasing and capitalizing are implemented.

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
let text_array, len_array;
let box_obj, box_x, box_y, box_w, box_h, txt_stroke, txt_size;


function setup () {
  createCanvas(1500, 500);
  background(200);
  text_array = [];
  
  // clear text box
  clear_button = createButton('clear textbox');
  clear_button.position(width/30, height/4);
  clear_button.mousePressed(empty_array);
  clear_button.style('font-size', '18px');
  clear_button.style('background-color', 255);
}

function draw () {
  background(244, 194, 194);
  
  textSize(20);
  fill(255);
  let msg = "CLICK ANYWHERE ON THE TEXTBOX AND START TYPING";
  text(msg, width/30, height/2.5);
  
  box_x = 50;
  box_y = height/2;
  box_h = 100;
  txt_stroke = 7;
  txt_size = 45;
  
  box_obj = text_box(box_x, box_y, box_h, txt_stroke, text_array, txt_size);
}

function text_box (x, y, h, stroke, txt, size) {
    box_w = textWidth(join(txt, "")) + 30;  // width of the rectangle changes
    
    // box
    strokeWeight(stroke);
    fill(255);
    rect(x, y, box_w, h);
  
    // text
    fill(0);
    textSize(size);
    text(join(txt, ""), x + stroke, y + size);
    noFill();
    rect(x, y, box_w, h);
  }

function keyPressed () {
  len_array = text_array.length;
  
  
  if (key == "Backspace") {
    text_array.pop();
  }

  else {
    if (key != "Shift" && key != "Enter" && key != "CapsLock" && key != "Control" && key != "Meta" && key != "Alt") {
      text_array[len_array] = key;
    }
  }
  
  if (len_array > (width * 2)) {
    text_array.splice(0, 1);
  }
}

function empty_array () {
  text_array = [];
}

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 

Embedded sketch:

Reflection and ideas for future work or improvements:

This simple textbox is the foundation for a simple browser text editor. Some natural next steps for improving the above textbox program would be:

  1. Implementing a blinking cursor (like in the text editors)
  2. Implementing the cursor’s move to the next line (using Return/Enter action key)
  3. Implementing a feature where pressing and holding down a key would continuously add that key to the textbox (with the help of keyReleased())
  4. Implementing features to modify the text’s font, size, and style from within the editor itself.

Assignment 3: Sudoku using OOP

Concept

For this assignment, I decided to generate one of my favorite games, Sudoku. The board is generated, styled, and displayed with the help of the ‘Cell’ class and using loops.

Code highlight

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function setup() {
  createCanvas(500, 500);

//populating the board
  board = [];
  
  grid = [ [3, '', 6, 5, '', 8, 4, '', ''], 
         [5, 2, '', '', '', '', '', '', ''], 
         ['', 8, 7, '', '', '', '', 3, 1], 
         ['', '', 3, '', 1, '', '', 8, ''], 
         [9, '', '', 8, 6, 3, '', '', 5], 
         ['', 5, '', '', 9, '', 6, '', ''], 
         [1, 3, '', '', '', '', 2, 5, ''], 
         ['', '', '', '', '', '', '', 7, 4], 
         ['', '', 5, 2, '', 6, 3, '', ''] ]


  for (let i = 0; i < 9; i++) {
    for (let j = 0; j < 9; j++) {
      board.push([]);
      board[i].push(new Cell(i, j, grid[i][j]));
    }
  }

// 9x9 board, text size, and text location
  scl = width / 9;
  textSize(30);
  textAlign(CENTER, CENTER);
}


function draw() {
  for (let i = 0; i < 9; i++) {
    for (let j = 0; j < 9; j++) {
      board[i][j].display();
    }
  }
}

//cell class and display options
class Cell {
  constructor(i, j, value) {
    this.i = i;
    this.j = j;
    this.value = value; //value will be taken later from the grid array
  }

  display() {
    stroke(0);
    fill("#f2eecb");
    rect(scl * this.i, scl * this.j, scl, scl); // dividing the grid 9x9     with rectangles
    fill(0);
    text(this.value, scl * this.i, scl * this.j, scl, scl);
  }
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Embedded sketch:

Reflection and ideas for future work or improvements:

The next step would be modifying the code such that it generates [solvable] Sudoku boards instead of manually placing numbers in the board matrix. And then the next step would be adding another button that actually solves the board. This might be what I’ll be working on for the midterm.