משחק מילים

This sketch creates an interactive Hebrew language learning game that displays a question asking for the Hebrew word for "dog." Users type their answer in an input box, click a check button, and receive instant visual feedback in green (correct) or red (incorrect with the right answer shown).

🧪 Try This!

Experiment with the code by making these changes:

  1. Change the quiz answer — The sketch checks for the Hebrew word "כלב" (dog). Change it to "חתול" (cat) to create a new quiz question.
  2. Make success messages blue — Change the green success color to blue, or any CSS color name, to match your design preference.
  3. Change the background to dark mode — Swap the light gray background (220) for a dark color to create a dark mode quiz interface.
  4. Make the input field wider
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch builds a simple but effective Hebrew word quiz that teaches interaction with HTML elements from p5.js. When you type an answer and click the check button, the sketch compares your input to the correct answer and displays feedback in color—green for success, red for failure. The code combines p5.js canvas setup with DOM manipulation (creating input fields and buttons), responsive canvas sizing, and event handling.

The sketch is organized into setup() which creates all the interactive elements, draw() which maintains the canvas background, checkAnswer() which validates user input, and windowResized() which keeps the canvas responsive. By studying this code you will learn how to blend p5.js with native HTML forms, how to capture user input, how to validate answers with string comparison, and how to dynamically update element styles based on whether logic passes or fails.

⚙️ How It Works

  1. When the sketch loads, preload() fetches a Hebrew-compatible font from a CDN so text displays correctly in both Hebrew and Latin characters.
  2. setup() creates a responsive canvas that fills the browser window and positions four HTML elements on top: a question div, an input field, a check button, and a result message div. All elements are styled with right-to-left text direction and absolute positioning.
  3. The user types a Hebrew word into the input field and clicks the check button, which triggers the checkAnswer() function.
  4. checkAnswer() retrieves the user's text, removes whitespace with trim(), and compares it exactly to the constant correctAnswer ("כלב" - the Hebrew word for dog).
  5. If the answer matches, the resultDiv displays "תשובה נכונה!" (Correct answer!) in green. If it does not match, it shows "תשובה שגויה. התשובה הנכונה היא: כלב" (Wrong answer. The correct answer is: dog) in red.
  6. draw() runs every frame and paints a light gray background, keeping the canvas responsive as the window resizes via windowResized().

🎓 Concepts You'll Learn

DOM manipulation (createDiv, createInput, createButton)Event handling (mousePressed)String comparison and validationConditional logic based on user inputDynamic styling with .style()Responsive canvas (windowResized)

📝 Code Breakdown

preload()

preload() runs before setup() and is the place to load files like fonts, images, and sounds that your sketch needs to be ready before drawing starts. If you do not preload fonts, p5.js will use the default browser font, which may not render Hebrew correctly.

function preload() {
  // Cargar una fuente que soporte hebreo desde Fontsource CDN
  // Convertir "Rubik" a slug: "rubik"
  // URL para el archivo hebreo 400 normal:
  // CORRECCIÓN: El archivo rubik-hebrew-400-normal.woff no existe en Fontsource para Rubik.
  // La variante 'latin' de Rubik incluye los caracteres hebreos.
  hebrewFont = loadFont('https://unpkg.com/@fontsource/rubik@latest/files/rubik-latin-400-normal.woff');
}
Line-by-line explanation (1 lines)

🔧 Subcomponents:

calculation Load Hebrew-Compatible Font hebrewFont = loadFont('https://unpkg.com/@fontsource/rubik@latest/files/rubik-latin-400-normal.woff');

Fetches a Rubik font from a CDN that includes Hebrew glyphs so text renders correctly

hebrewFont = loadFont('https://unpkg.com/@fontsource/rubik@latest/files/rubik-latin-400-normal.woff');
Loads a font file from the internet before the sketch runs. This font supports both Hebrew and Latin characters, stored in the hebrewFont variable for later use.

setup()

setup() is where you initialize your sketch. Here we create the canvas once and build all the interactive elements the user will interact with. The .id() method lets us connect HTML elements to CSS styles defined in style.css so they appear in the right place with the right look.

🔬 These lines create and configure four HTML elements. What happens if you duplicate the answerInput lines to create a second input field? Will you be able to check both answers, or will one overwrite the other?

  questionDiv = createDiv("מהי המילה העברית ל'כלב'?"); // What is the Hebrew word for 'dog'?
  questionDiv.id('hebrewQuestion');

  answerInput = createInput('');
  answerInput.id('answerInput');

  checkButton = createButton('בדוק'); // Check
  checkButton.id('checkButton');
  checkButton.mousePressed(checkAnswer);

  resultDiv = createDiv('');
  resultDiv.id('resultMessage');
function setup() {
  createCanvas(windowWidth, windowHeight);
  // Tip: Use windowWidth/windowHeight for responsive canvas
  
  // Establecer la fuente para p5.js drawing functions (aunque no la usaremos para los elementos DOM)
  textFont(hebrewFont);
  textSize(32);
  textAlign(RIGHT); // Establecer alineación a la derecha para hebreo
  
  // Crear elementos HTML para la pregunta y la respuesta
  questionDiv = createDiv("מהי המילה העברית ל'כלב'?"); // What is the Hebrew word for 'dog'?
  questionDiv.id('hebrewQuestion');

  answerInput = createInput('');
  answerInput.id('answerInput');

  checkButton = createButton('בדוק'); // Check
  checkButton.id('checkButton');
  checkButton.mousePressed(checkAnswer);

  resultDiv = createDiv('');
  resultDiv.id('resultMessage');
}
Line-by-line explanation (12 lines)

🔧 Subcomponents:

calculation Create Responsive Canvas createCanvas(windowWidth, windowHeight);

Makes a canvas that fills the entire browser window, which will resize if the window is resized

calculation Configure Text Properties textFont(hebrewFont); textSize(32); textAlign(RIGHT);

Sets the font, size, and alignment for any text drawn directly to the canvas (not used for DOM elements, but good to configure)

calculation Create Interactive HTML Elements questionDiv = createDiv("מהי המילה העברית ל'כלב'?"); questionDiv.id('hebrewQuestion'); answerInput = createInput(''); answerInput.id('answerInput'); checkButton = createButton('בדוק'); checkButton.id('checkButton'); checkButton.mousePressed(checkAnswer); resultDiv = createDiv(''); resultDiv.id('resultMessage');

Creates four HTML elements (a question div, an input field, a button, and a result div) and assigns them CSS ids so the stylesheet can position and style them. The button's mousePressed event is wired to call checkAnswer() when clicked.

createCanvas(windowWidth, windowHeight);
Creates a canvas that is exactly as wide and tall as the browser window, making it responsive to the viewport size.
textFont(hebrewFont);
Tells p5.js to use the Hebrew-compatible font we loaded in preload() for any future text() calls (though this sketch does not draw text directly).
textSize(32);
Sets the size of text to 32 pixels (a convention, not actually used in this sketch since we use HTML divs instead).
textAlign(RIGHT);
Aligns text to the right edge, which is the correct reading direction for Hebrew.
questionDiv = createDiv("מהי המילה העברית ל'כלב'?");
Creates an HTML div element containing the Hebrew question "What is the Hebrew word for 'dog'?" and stores a reference to it in questionDiv.
questionDiv.id('hebrewQuestion');
Assigns the CSS id 'hebrewQuestion' to the div so that the style.css file can position and style it with absolute positioning and padding.
answerInput = createInput('');
Creates an empty text input field where the user can type their answer, stored in the answerInput variable.
answerInput.id('answerInput');
Assigns the CSS id 'answerInput' to the input field so the stylesheet can position it below the question.
checkButton = createButton('בדוק');
Creates a button with the Hebrew text 'בדוק' (Check) and stores it in checkButton.
checkButton.mousePressed(checkAnswer);
Wires the button's click event to the checkAnswer() function, so clicking the button runs that function.
resultDiv = createDiv('');
Creates an empty div element to hold feedback messages (correct or incorrect) after the user submits their answer.
resultDiv.id('resultMessage');
Assigns the CSS id 'resultMessage' to the result div so the stylesheet can position it below the input field.

draw()

draw() runs 60 times per second and is where animation happens in p5.js. In this sketch, draw() just maintains the canvas background while all the interaction logic lives in checkAnswer(). Since the HTML elements sit on top of the canvas, they are not erased by background().

🔬 This draw() function only paints the background and does nothing else. What would happen if you removed the background(220) line entirely? Would the HTML elements disappear, or would the canvas show something underneath?

function draw() {
  background(220); // Debería renderizar un fondo gris claro
  // Puedes añadir más elementos visuales aquí si lo deseas
}
function draw() {
  background(220); // Debería renderizar un fondo gris claro
  // Puedes añadir más elementos visuales aquí si lo deseas
}
Line-by-line explanation (1 lines)

🔧 Subcomponents:

calculation Paint Light Gray Background background(220);

Fills the entire canvas with a light gray color (220 on a 0-255 brightness scale) every frame

background(220);
Paints the canvas light gray (220 is close to white on p5.js's 0-255 grayscale). This runs every frame (60 times per second), keeping the background clean and fresh.

windowResized()

windowResized() is a p5.js callback function that p5 calls whenever the window size changes. By calling resizeCanvas() inside it, we keep our sketch responsive without any extra work. This is called automatically by p5.js, not by us.

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  // Called when preview panel is resized
}
Line-by-line explanation (1 lines)

🔧 Subcomponents:

calculation Resize Canvas to Match Window resizeCanvas(windowWidth, windowHeight);

Updates the canvas dimensions whenever the browser window is resized, keeping the sketch responsive

resizeCanvas(windowWidth, windowHeight);
Automatically updates the canvas size to match the current window width and height, so the sketch adapts if you drag the browser edge or rotate your device.

checkAnswer()

checkAnswer() is called whenever the user clicks the check button. It is the heart of the quiz logic: read the input, compare it to the right answer, and show feedback. The pattern of if-else checking a condition and showing two different results is fundamental to interactive sketches.

🔬 This if-else statement shows green for correct and red for wrong. What happens if you change === to == (loose equality) instead? Or if you add .toLowerCase() to convert both strings to lowercase before comparing?

  if (userAnswer === correctAnswer) {
    resultDiv.html("תשובה נכונה!"); // Correct answer!
    resultDiv.style('color', 'green');
  } else {
    resultDiv.html("תשובה שגויה. התשובה הנכונה היא: " + correctAnswer); // Wrong answer. The correct answer is: Dog
    resultDiv.style('color', 'red');
  }
function checkAnswer() {
  let userAnswer = answerInput.value().trim(); // Obtener la respuesta del usuario y eliminar espacios
  if (userAnswer === correctAnswer) {
    resultDiv.html("תשובה נכונה!"); // Correct answer!
    resultDiv.style('color', 'green');
  } else {
    resultDiv.html("תשובה שגויה. התשובה הנכונה היא: " + correctAnswer); // Wrong answer. The correct answer is: Dog
    resultDiv.style('color', 'red');
  }
}
Line-by-line explanation (6 lines)

🔧 Subcomponents:

calculation Retrieve and Clean User Input let userAnswer = answerInput.value().trim();

Reads the text the user typed into the input field and removes leading/trailing whitespace so accidental spaces do not break the answer

conditional Check if Answer is Correct if (userAnswer === correctAnswer) {

Compares the user's answer exactly to the stored correct answer string

calculation Display Success Message resultDiv.html("תשובה נכונה!"); resultDiv.style('color', 'green');

If the answer matches, updates the result div with a green success message

calculation Display Failure Message with Correct Answer resultDiv.html("תשובה שגויה. התשובה הנכונה היא: " + correctAnswer); resultDiv.style('color', 'red');

If the answer is wrong, shows a red error message and reveals the correct answer

let userAnswer = answerInput.value().trim();
.value() reads what the user typed into the input field. .trim() removes any spaces at the start or end, preventing typos like " כלב " from being marked wrong.
if (userAnswer === correctAnswer) {
Uses === (strict equality) to check if the user's text exactly matches the correctAnswer string "כלב". This comparison is case-sensitive and requires exact spelling.
resultDiv.html("תשובה נכונה!");
.html() sets the text content of the result div to the success message "Correct answer!" in Hebrew.
resultDiv.style('color', 'green');
.style() changes the CSS color property to green, making the success message appear in green text to signal success.
resultDiv.html("תשובה שגויה. התשובה הנכונה היא: " + correctAnswer);
If the answer is wrong, this sets the result message to "Wrong answer. The correct answer is: " followed by the actual answer. The + operator concatenates strings.
resultDiv.style('color', 'red');
.style() changes the text color to red to signal an error and grab the user's attention.

📦 Key Variables

hebrewFont object

Stores the loaded font file that supports Hebrew characters, used to render text with proper glyphs

let hebrewFont;
questionDiv object

A reference to the HTML div element displaying the quiz question, allowing us to modify it if needed

let questionDiv;
answerInput object

A reference to the HTML text input field where the user types their answer

let answerInput;
checkButton object

A reference to the HTML button element; when clicked, it triggers the checkAnswer() function

let checkButton;
resultDiv object

A reference to the HTML div element that displays feedback (correct or incorrect) after the user submits an answer

let resultDiv;
correctAnswer string

Stores the Hebrew word "כלב" (dog) that the user must type to pass the quiz

const correctAnswer = "כלב";

🔧 Potential Improvements (4)

Here are some ways this code could be enhanced:

BUG checkAnswer()

The function does not check for diacritical marks or vowel variations in Hebrew (e.g., שׁוא vs שוא). A user typing a valid variant may be marked wrong.

💡 Consider using a normalized comparison: let normalized = userAnswer.normalize('NFD'); or accept multiple valid answers in an array and check includes().

STYLE setup()

The textFont(), textSize(), and textAlign() calls configure p5.js text drawing, but the sketch never calls text() or textSize() functions—all text is in HTML elements. These lines are unnecessary.

💡 Remove lines 11-13 (textFont, textSize, textAlign) since HTML elements are styled via CSS, not p5.js drawing functions.

FEATURE checkAnswer()

Users must click the check button every time they want to verify an answer. There is no way to submit by pressing Enter on the keyboard.

💡 Add keyboard support: listen for keyCode === ENTER in the answerInput using answerInput.elt.addEventListener('keypress', function(e) { if (e.key === 'Enter') checkAnswer(); });

FEATURE setup()

The quiz has only one question. If the user answers correctly, there is no next question or game progression.

💡 Create an array of questions and answers: const questions = [{q: "...", a: "כלב"}, ...]; then cycle through them or randomize the order to create a full quiz.

🔄 Code Flow

Code flow showing preload, setup, draw, windowresized, checkanswer

💡 Click on function names in the diagram to jump to their code

graph TD start[Start] --> preload[preload] preload --> setup[setup] click preload href "#fn-preload" click setup href "#fn-setup" setup --> draw[draw loop] click draw href "#fn-draw" draw --> background-paint[background-paint] click background-paint href "#sub-background-paint" draw --> canvas-resize[canvas-resize] click canvas-resize href "#sub-canvas-resize" draw --> rowloop[Row Loop] rowloop --> checkanswer[checkAnswer] click checkanswer href "#fn-checkanswer" checkanswer --> get-input[get-input] click get-input href "#sub-get-input" get-input --> correct-check[correct-check] click correct-check href "#sub-correct-check" correct-check -->|Correct| show-success[show-success] click show-success href "#sub-show-success" correct-check -->|Incorrect| show-failure[show-failure] click show-failure href "#sub-show-failure" setup --> font-load[font-load] click font-load href "#sub-font-load" setup --> canvas-creation[canvas-creation] click canvas-creation href "#sub-canvas-creation" setup --> text-setup[text-setup] click text-setup href "#sub-text-setup" setup --> dom-elements[dom-elements] click dom-elements href "#sub-dom-elements" windowresized[windowResized] --> canvas-resize click windowresized href "#fn-windowresized"

❓ Frequently Asked Questions

What visual elements are present in the Hebrew word game sketch?

The sketch features a clean, light-gray canvas displaying a Hebrew question about the word 'dog', along with an input box and a check button for user interaction.

How can users participate in the Hebrew word game?

Users can type their answer into the input box and click the check button to receive immediate feedback on whether their response is correct.

What creative coding concept does this sketch illustrate?

This sketch demonstrates interactive text input and real-time feedback using p5.js, showcasing how to integrate HTML elements with canvas for educational purposes.

Preview

משחק מילים - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of משחק מילים - Code flow showing preload, setup, draw, windowresized, checkanswer
Code Flow Diagram