# Pixel Art Using a Square Class

This was a challenging assignment! Mainly because I had a game I wanted to do in mind, and after spending a lot of time on getting the basics to work I realized it might need more practice and time than what I have now, so I changed the direction of my assignment and decided to go with a more “artwork” focused approach.

Recently I’ve been thinking about the ‘paint by numbers notebooks’ I used to have as a child and how accessible they made creating artwork that is above my artistic skills. This made me want to buy a ‘paint by numbers’ set, but also I asked if I could use the same approach to create artwork on processing.

I realized I can do a similar approach but with pixels! I made a class called “square” which represents each square in a grid, and then used a 2D array list that contains different combinations of numbers of squares to be filled.

My class has a display function, and a fill function that relies on a boolean variable.

For the drawing, I decided to go for a heart that is filling gradually with every number the user inputs from their keyboard. At the final level, when the heart is full, it goes from black to a mix of random shades of red and pink which is controlled by the mouseX movement to a certain extent (to avoid the colors being too random).

After finalizing the logic, which depends on creating an array of square objects and then displaying and referencing them as a grid. I went to figure out the square numbers needed in my 2D array for each heart stage. For this part, I used pixilart.com  and created a grid of the same size as mine then compared the square values.

I settled on bigger pixels, but since the code contains, row, column, and square number variables, it is easy to change the grid appearance and square size.

I think the program has the potential to be more complex or contain more user interaction, I would love any suggestions!

Have a look at my main code:

```Square[] allSquares; //declaring an array of objects that consists of the squares that will be in the grid

// 2D Array of the different heart level drawings, each inner list contains the number of the pixel that should be filled
int[][] heartLevels = { {2,3,4,11,15,21,26,32,37,43,48,53,58,62,67,71,76,81,85,92,93,94}, //empty heart
{2,3,4,11,15,21,26,32,37,43,47,48,53,57,58,62,67,71,76,81,85,92,93,94}, //initially filled heart (Level 1)
{2,3,4,11,15,21,25,26,32,35,36,37,43,45,46,47,48,53,55,56,57,58,62,65,66,67,71,75,76,81,85,92,93,94}, // medium full heart (Level 2)
{2,3,4,11,13,14,15,21,23,24,25,26,32,33,34,35,36,37,43,44,45,46,47,48,53,54,55,56,57,58,62,63,64,65,66,67,71,73,74,75,76,81,83,84,85,92,93,94},
// almost full heart (Level 3)
{2,3,4,11,12,13,14,15,21,22,23,24,25,26,32,33,34,35,36,37,43,44,45,46,47,48,53,54,55,56,57,58,62,63,64,65,66,67,71,72,73,74,75,76,81,82,83,84,85,92,93,94}}; // full heart

// a boolean to create the color effect for the full heart
boolean fullHeart;

// declaring and initializing the column and row number for the grid
int cols = 10;
int rows = 10;

void setup(){
size(500,500);
background(255);
//creating the grid array, the array size corresponds to the dimension of the grid
allSquares = new Square[cols*rows];
//initializing and declaring an index variable to create different objects every time the  nested loop runs
int index = 0;
//a nested loop that goes through each column and row to create a grid of objects
for (int c = 0; c < cols; c++){
for (int r = 0; r < rows; r++){
// creating the objects, the arguments of the class are X location, Y location, Width, Height, and index

//we multiply c and r by 50 because it corresponds to the square dimension, so if my x is 2 and y is 2, the square will be at 100,100.
allSquares[index] = new Square(c*50,r*50,50,50,index);

index+=1;

}
}
fullHeart = false; //initializing the color effect variable with false
}

void draw(){
//a loop that displays the grid
for(int i = 0; i < cols*rows; i++){
allSquares[i].display();

//an if statement that checks which heart we are creating by checking if the fullHeart bool is true, it is changed to true below, when the key is pressed.
if (fullHeart == true){
for (int j = 0; j < heartLevels[4].length; j++){

//accessing the heart color variable defined in the square class, and altering it for the color effect

//using random within a small range to generate the different shades of red, and applying interaction through mouseX
allSquares[heartLevels[4][j]].heartColor = color(random(mouseX,255), random(0,90),random(90,100));  //interacting with user through changing the R random bottom range using mouseX.

//filling the squares, it keeps changing because it is in the draw function
allSquares[heartLevels[4][j]].fillingSquare(true);

}
}
}
}

void keyPressed(){
//key pressed function that displays different heart shapes based on the number pressed

if (key == '0'){ //zero gives an empty screen
for(int i = 0; i < cols*rows; i++){
fullHeart = false; //this boolean is set to false for every key that does not correspond to a full heart

allSquares[i].fillingSquare(false); //First loop goes through all the squares in the object list and unfills them to remove the effect of other shapes, this loop is repeated for all the other keys

}
}
if (key == '1'){
for(int i = 0; i < cols*rows; i++){ //same loop
allSquares[i].fillingSquare(false);
}
for (int i = 0; i < heartLevels[0].length; i++){
fullHeart = false;
allSquares[heartLevels[0][i]].heartColor = color(0); //sets the color variable from the class to black

allSquares[heartLevels[0][i]].fillingSquare(true); ////fills every pixel that corresponds to values in the first heart shape list with black

}
}

//the same repeats for the next if conditions
else if (key == '2'){
for(int i = 0; i < cols*rows; i++){
allSquares[i].fillingSquare(false);
}
for (int i = 0; i < heartLevels[1].length; i++){
fullHeart = false;
allSquares[heartLevels[1][i]].heartColor = color(0);
allSquares[heartLevels[1][i]].fillingSquare(true);
}

}
else if(key=='3'){
for(int i = 0; i < cols*rows; i++){
allSquares[i].fillingSquare(false);
}
for (int i = 0; i < heartLevels[2].length; i++){
fullHeart = false;
allSquares[heartLevels[2][i]].heartColor = color(0);
allSquares[heartLevels[2][i]].fillingSquare(true);

}
}
else if(key=='4'){
for(int i = 0; i < cols*rows; i++){
allSquares[i].fillingSquare(false);
}
for (int i = 0; i < heartLevels[3].length; i++){
fullHeart = false;
allSquares[heartLevels[3][i]].heartColor = color(0);
allSquares[heartLevels[3][i]].fillingSquare(true);

}
}
else if(key=='5'){
for(int i = 0; i < cols*rows; i++){
allSquares[i].fillingSquare(false);
}
for (int i = 0; i < heartLevels[4].length; i++){
fullHeart = true; //this turns on the random color fill in the draw function
allSquares[heartLevels[4][i]].fillingSquare(true); //and based on those colors fills the squares

}
}
}```

and my Square Class:

```class Square{
//initializing variables that will be used throughout the class
int squareX , squareY;  //square x and y location
int squareW , squareH;
int squareNo; //the number of the pixel on the grid
boolean filled; //the boolean that determines which pixels on the screen are filled
color heartColor; //a color variable to control the color of the pixel
color gridStroke = color(203,197,197); // color of grid lines

Square(int tempX, int tempY, int tempW, int tempH, int tempSquareNoMinus1){ //constructor, takes X location, Y location, Width, Height, and the index as arguments
//setting the constructor arguments to permanent variables
squareX = tempX;
squareY = tempY;
squareW = tempW;
squareH = tempH;
squareNo = tempSquareNoMinus1 + 1; // 1 is added to the index as the counting of squares starts at 1, not zero.

}

void display(){
//function that displays the square on the screen
stroke(gridStroke);
strokeWeight(0.25);
noFill();
rect(squareX , squareY , squareW , squareH);

}

void fillingSquare(boolean filled){
//a function that fills the pixels based on a filled? boolean
if (filled == true){

fill(heartColor);
}
else{
//if the boolean is false the square is filled with white and redrawn
fill(255);
}
rect(squareX,squareY,squareW,squareH);
}
}```