chat with people

This sketch creates an interactive chat interface where users can type messages and receive responses from three AI-powered personas: Momrshell (a coder), Chewr (an artist), and AI (a robot). Each person responds based on keyword matching and topic context, maintaining conversation history and personality-specific expertise.

🧪 Try This!

Experiment with the code by making these changes:

  1. Add a fourth AI person — Duplicate one of the existing people objects and add a new name and topic area to the people array - they'll respond to messages alongside the others.
  2. Change the welcome message — Customize the initial greeting message that appears when the chat loads - set the tone for your conversation.
  3. Make messages not clear between conversations — Comment out the line that clears the chat display on each update - old and new messages will layer together, showing the entire conversation history visually overlapped.
Prefer the full editor? Open it there →

📖 About This Sketch

This sketch creates a fully functional chat interface layered on top of a p5.js canvas, featuring three distinct AI personas that respond intelligently to user messages. The interface uses HTML DOM elements (input field, send button, chat display) styled with CSS and controlled by p5.js, making it an excellent example of how p5.js can power web applications beyond just graphics. The personalities - Momrshell (coder), Chewr (artist), and AI (robot) - each have specialized knowledge areas and maintain context across the conversation.

The code is organized into a setup() function that initializes the DOM elements, a draw() function (minimal for this app), and several helper functions that power the chat logic. By studying this sketch, you'll learn how to detect keywords in user input, store conversation history in arrays of objects, use conditional logic to select appropriate responses, and dynamically update the DOM based on state changes. It combines fundamental coding concepts like loops, conditionals, and data structures with practical web interaction patterns.

⚙️ How It Works

  1. When the sketch loads, setup() creates a p5.js canvas as a background and then builds the chat UI on top of it: a chat display div that shows messages, an input field where the user types, and a send button.
  2. The user types a message and presses Enter or clicks Send, which calls sendMessage() and adds the user's message to the messages array.
  3. For each of the three people (Momrshell, Chewr, AI), generatePersonResponse() searches for keywords in the user's message using the responsesByTopic object, which maps different topics to keyword lists and response functions.
  4. The function first checks if the person has a lastTopic from the previous exchange - if so, it searches that topic's keywords first to maintain conversation continuity.
  5. If no keyword match is found, it searches general topics and person-specific topics (Alice for coding, Bob for art, Charlie for robots) to find the best response.
  6. If still no match, a random generic response is selected as a fallback, and each person's response is added to the messages array with their name and response type.
  7. updateChatDisplay() loops through all messages and creates DOM elements (divs for containers, spans for text) with different styling based on message type (user, AI, or system), then appends them to the chat display. The display auto-scrolls to show the latest message.

🎓 Concepts You'll Learn

DOM manipulation with p5.jsKeyword matching and string searchingArrays of objects for data storageConditional logic and topic trackingEvent handling (input, button click)Dynamic HTML element creationState management (conversation history)

📝 Code Breakdown

setup()

setup() runs exactly once when the sketch loads. It's the perfect place to initialize variables, create DOM elements, and set up event handlers. p5.js provides createElement(), createInput(), and createButton() to build web interfaces directly in your sketch.

function setup() {
  // Create a canvas as a background for the sketch
  createCanvas(windowWidth, windowHeight);
  background(220); // Default background for the canvas

  // Get a reference to the main chat container div from index.html
  chatContainer = select('#chat-app');

  // Create the chat display area (where messages appear)
  chatDisplay = createElement('div');
  chatDisplay.id('chat-display');
  chatContainer.child(chatDisplay); // Append to the chat container

  // Create the input area container
  let inputArea = createElement('div');
  inputArea.id('input-area');
  chatContainer.child(inputArea); // Append to the chat container

  // Create the message input field
  inputField = createInput('');
  inputField.id('message-input');
  inputField.attribute('placeholder', 'Type your message...');
  inputField.changed(sendMessage); // Call sendMessage when Enter is pressed
  inputArea.child(inputField); // Append to the input area

  // Create the send button
  sendButton = createButton('Send');
  sendButton.id('send-button');
  sendButton.mousePressed(sendMessage); // Call sendMessage when button is clicked
  inputArea.child(sendButton); // Append to the input area

  // Add an initial welcome message to the chat
  messages.push({ sender: "System", text: "Welcome to the chat! Say hello!", type: "system" });
  updateChatDisplay(); // Display the initial messages
}
Line-by-line explanation (12 lines)

🔧 Subcomponents:

calculation Canvas initialization createCanvas(windowWidth, windowHeight);

Creates a p5.js canvas that spans the full window, serving as a background for the chat interface

calculation Input field setup inputField = createInput('');

Creates a text input element where users type their messages

calculation Send button setup sendButton = createButton('Send');

Creates a clickable button that triggers message sending

createCanvas(windowWidth, windowHeight);
Creates a p5.js canvas that fills the entire browser window - this will be the background behind the chat UI
background(220);
Fills the canvas with a light gray color (220 is a grayscale value from 0-255)
chatContainer = select('#chat-app');
Finds the div with id 'chat-app' in the HTML and stores a reference to it so we can add elements to it
chatDisplay = createElement('div');
Creates a new div element that will hold all the chat messages
chatDisplay.id('chat-display');
Sets the id of this div to 'chat-display' so CSS can style it
chatContainer.child(chatDisplay);
Adds the chatDisplay div as a child of the chatContainer, making it appear inside the main chat app container
inputField = createInput('');
Creates a text input element with an empty starting value
inputField.changed(sendMessage);
Registers the sendMessage function to run when the user presses Enter in the input field
sendButton = createButton('Send');
Creates a clickable button with the text 'Send'
sendButton.mousePressed(sendMessage);
Registers the sendMessage function to run when the user clicks the button
messages.push({ sender: "System", text: "Welcome to the chat! Say hello!", type: "system" });
Adds an initial welcome message to the messages array as an object with sender, text, and type properties
updateChatDisplay();
Calls the updateChatDisplay function to render all messages in the chatDisplay div

draw()

draw() runs 60 times per second by default, but this chat sketch doesn't need it since the DOM updates are event-driven (only when the user sends a message). This is a common pattern: p5.js can power the background while your interactive logic lives in event handlers.

function draw() {
  // The canvas is primarily a background.
  // No continuous drawing is needed for the chat UI itself, as it's DOM-based.
  // You could add dynamic background animations here if desired!
}
Line-by-line explanation (2 lines)
// The canvas is primarily a background.
This comment explains that the canvas serves as a visual background, not as the primary interactive element
// No continuous drawing is needed for the chat UI itself, as it's DOM-based.
The chat interface uses HTML DOM elements (divs, inputs, buttons) which are updated only when messages arrive, not every frame

sendMessage()

sendMessage() is the heart of the chat logic. It's called whenever the user presses Enter or clicks Send. The function collects the message, validates it isn't empty, adds it to the history, generates responses from all three personas, and updates the display. This is an event-driven function - it only runs when the user acts, not continuously like draw().

function sendMessage() {
  let userMessage = inputField.value().trim(); // Get message and remove leading/trailing whitespace
  if (userMessage === '') {
    return; // Don't send empty messages
  }

  // Add the user's message to our messages array
  messages.push({ sender: "You", text: userMessage, type: "user" });
  inputField.value(''); // Clear the input field

  // Generate and add responses from each "person"
  for (let i = 0; i < people.length; i++) {
    let person = people[i];
    let response = generatePersonResponse(person, userMessage);
    // Removed emoji from the message object here as well
    messages.push({ sender: person.name, text: response, type: "ai" });
    person.lastMessage = response; // Update the person's last message
  }

  updateChatDisplay(); // Refresh the chat display
}
Line-by-line explanation (11 lines)

🔧 Subcomponents:

conditional Empty message check if (userMessage === '') { return; // Don't send empty messages }

Prevents sending blank messages and exits the function early if the user didn't type anything

for-loop Generate all responses for (let i = 0; i < people.length; i++) { let person = people[i]; let response = generatePersonResponse(person, userMessage); messages.push({ sender: person.name, text: response, type: "ai" }); person.lastMessage = response; }

Loops through each person (Momrshell, Chewr, AI) and generates a unique response for each, then stores it in the messages array

let userMessage = inputField.value().trim();
Gets the text the user typed in the input field and removes any spaces at the beginning or end with trim()
if (userMessage === '') {
Checks if the message is empty (length zero) after trimming
return;
Exits the function early without doing anything, so no empty message is added to the chat
messages.push({ sender: "You", text: userMessage, type: "user" });
Creates a message object with the user as the sender and adds it to the messages array
inputField.value('');
Clears the input field by setting its value to an empty string, preparing it for the next message
for (let i = 0; i < people.length; i++) {
Starts a loop that runs once for each person in the people array (3 times: Momrshell, Chewr, AI)
let person = people[i];
Gets the current person object from the array
let response = generatePersonResponse(person, userMessage);
Calls generatePersonResponse to create an appropriate response for this person based on the user's message
messages.push({ sender: person.name, text: response, type: "ai" });
Adds the person's response to the messages array as an AI message
person.lastMessage = response;
Updates the person's lastMessage property so we remember what they just said
updateChatDisplay();
Calls updateChatDisplay to re-render the chat with all the new messages (user message + three AI responses)

generatePersonResponse(person, userMessage)

generatePersonResponse() is the most sophisticated function in this sketch. It implements a three-tier matching strategy: (1) check the person's last conversation topic to maintain context, (2) search general and person-specific topic areas if no last topic match, (3) fall back to random generic responses. It also uses .some() to check if any keyword in an array matches, and uses a switch statement to pick topic-specific follow-up questions. This is how conversational AI fake continuity.

🔬 This section prioritizes the lastTopic. What happens if you delete this entire block? Try it and chat about the same topic twice in a row - the person will search from scratch each time instead of staying focused on the previous topic.

  // 1. Check for responses based on the last topic first
  // This helps maintain context if the user continues the previous conversation
  if (person.lastTopic) {
    const topicResponses = responsesByTopic[person.lastTopic] || responsesByTopic.general;
    for (let resp of topicResponses) {
      if (resp.keywords.some(keyword => userMessage.includes(keyword))) {
        matchedResponse = resp.response(person);
        matchedTopic = person.lastTopic; // Continue with the same topic
        break;
      }
    }
  }
function generatePersonResponse(person, userMessage) {
  userMessage = userMessage.toLowerCase(); // Convert user message to lowercase for easier matching
  let matchedResponse = null;
  let matchedTopic = null;

  // 1. Check for responses based on the last topic first
  // This helps maintain context if the user continues the previous conversation
  if (person.lastTopic) {
    const topicResponses = responsesByTopic[person.lastTopic] || responsesByTopic.general;
    for (let resp of topicResponses) {
      if (resp.keywords.some(keyword => userMessage.includes(keyword))) {
        matchedResponse = resp.response(person);
        matchedTopic = person.lastTopic; // Continue with the same topic
        break;
      }
    }
  }

  // 2. If no response from last topic, check general and person-specific topics
  // This allows the user to shift topics
  if (!matchedResponse) {
    const allTopicLists = [responsesByTopic.general, responsesByTopic[person.name]];
    for (let topicList of allTopicLists) {
      if (topicList) {
        for (let resp of topicList) {
          if (resp.keywords.some(keyword => userMessage.includes(keyword))) {
            matchedResponse = resp.response(person);
            // If a new keyword from a specific person's topic list is found, update the lastTopic
            // This prioritizes new topics over existing ones if the user shifts
            if (topicList === responsesByTopic[person.name]) {
              matchedTopic = person.name; // This person's specific topic
            } else if (resp.keywords.includes("p5.js") || resp.keywords.includes("code") || resp.keywords.includes("algorithm")) {
              matchedTopic = "Alice"; // P5.js/code/algorithms are Alice's domain
            } else if (resp.keywords.includes("art") || resp.keywords.includes("creative") || resp.keywords.includes("design")) {
              matchedTopic = "Bob"; // Art/creativity/design are Bob's domain
            } else if (resp.keywords.includes("robot") || resp.keywords.includes("AI") || resp.keywords.includes("data")) {
              matchedTopic = "Charlie"; // Robots/AI/data are Charlie's domain
            } else {
              matchedTopic = null; // No strong topic detected, reset
            }
            break;
          }
        }
      }
      if (matchedResponse) break;
    }
  }

  // 3. Fallback to a random generic response if no specific keyword is found
  if (!matchedResponse) {
    // If there was a last topic, ask a generic follow-up question related to it
    if (person.lastTopic) {
      switch (person.lastTopic) {
        case "Alice": return `So, anything interesting happening in the world of coding, ${person.name}?`;
        case "Bob": return `What's been inspiring your creativity lately, ${person.name}?`;
        case "Charlie": return `Have you encountered any new data patterns, ${person.name}?`;
        default: return genericResponses[Math.floor(Math.random() * genericResponses.length)];
      }
    } else {
      // If no last topic, use a truly generic response
      return genericResponses[Math.floor(Math.random() * genericResponses.length)];
    }
  }

  person.lastTopic = matchedTopic; // Update the person's last topic for the next turn
  return matchedResponse;
}
Line-by-line explanation (14 lines)

🔧 Subcomponents:

conditional Last topic priority check if (person.lastTopic) { const topicResponses = responsesByTopic[person.lastTopic] || responsesByTopic.general; for (let resp of topicResponses) { if (resp.keywords.some(keyword => userMessage.includes(keyword))) { matchedResponse = resp.response(person); matchedTopic = person.lastTopic; break; } } }

Checks if the person has a previous conversation topic stored, and if so, searches for keywords in that topic first to maintain context

conditional Fallback generic response if (!matchedResponse) { if (person.lastTopic) { switch (person.lastTopic) { case "Alice": return `So, anything interesting happening in the world of coding, ${person.name}?`; case "Bob": return `What's been inspiring your creativity lately, ${person.name}?`; case "Charlie": return `Have you encountered any new data patterns, ${person.name}?`; default: return genericResponses[Math.floor(Math.random() * genericResponses.length)]; } } else { return genericResponses[Math.floor(Math.random() * genericResponses.length)]; } }

If no keyword is matched, selects a random generic response or a topic-specific follow-up question if the person has a conversation history

userMessage = userMessage.toLowerCase();
Converts the user's message to all lowercase so keyword matching isn't case-sensitive (e.g., 'Hello' matches 'hello')
let matchedResponse = null;
Creates a variable to store the response once a keyword match is found; starts as null (no match yet)
let matchedTopic = null;
Creates a variable to track which topic/domain the response belongs to; used to update the person's lastTopic
if (person.lastTopic) {
Checks if this person has a lastTopic from a previous conversation turn
const topicResponses = responsesByTopic[person.lastTopic] || responsesByTopic.general;
Gets the array of responses for the person's last topic, or falls back to general responses if the topic doesn't exist
for (let resp of topicResponses) {
Loops through each response object in the topicResponses array
if (resp.keywords.some(keyword => userMessage.includes(keyword))) {
Uses the some() method to check if ANY keyword in the response's keywords array appears in the user's message
matchedResponse = resp.response(person);
If a keyword match is found, calls the response function (passing in the person object) to generate the actual response text
matchedTopic = person.lastTopic;
Sets matchedTopic to the current topic so we remember to stay on this topic next time
if (!matchedResponse) {
If no keyword was matched from the last topic, this checks whether matchedResponse is still null
const allTopicLists = [responsesByTopic.general, responsesByTopic[person.name]];
Creates an array containing general responses and this person's specific topic responses (e.g., 'Alice' or 'Bob')
if (resp.keywords.includes("p5.js") || resp.keywords.includes("code") || resp.keywords.includes("algorithm")) {
Checks if the matched response's keywords include p5.js, code, or algorithm - if so, assigns 'Alice' as the topic
return genericResponses[Math.floor(Math.random() * genericResponses.length)];
Selects a random index in the genericResponses array and returns that response text
person.lastTopic = matchedTopic;
Updates the person's lastTopic property so the next message will check this topic first, maintaining conversation context

updateChatDisplay()

updateChatDisplay() is responsible for converting the messages array (pure data) into visible DOM elements (visual representation). It's called every time a new message arrives. By completely clearing and rebuilding the display each time, the function ensures all messages are correctly styled and ordered. The scrollTop line at the end is a nice touch - it automatically scrolls the chat to the bottom so users see new messages without manual scrolling.

🔬 User messages only add messageText to the bubble, but AI messages add both senderName and messageText. What happens if you swap these - make user messages show their sender name too, and AI messages show no name?

    if (msg.type === 'user') {
      msgContainer.addClass('user-message');
      msgBubble.child(messageText); // User messages just have the text bubble
    } else if (msg.type === 'ai') {
      msgContainer.addClass('ai-message');
      // Removed emoji display logic here
      msgBubble.child(senderName);
      msgBubble.child(messageText);
function updateChatDisplay() {
  chatDisplay.html(''); // Clear current display

  for (let msg of messages) {
    let msgContainer = createElement('div');
    msgContainer.class('message-container');

    let msgBubble = createElement('div');
    msgBubble.class('message-bubble');

    let senderName = createElement('span');
    senderName.class('sender-name');
    senderName.html(msg.sender + ":");

    let messageText = createElement('span');
    messageText.html(msg.text);

    if (msg.type === 'user') {
      msgContainer.addClass('user-message');
      msgBubble.child(messageText); // User messages just have the text bubble
    } else if (msg.type === 'ai') {
      msgContainer.addClass('ai-message');
      // Removed emoji display logic here
      msgBubble.child(senderName);
      msgBubble.child(messageText);
    } else if (msg.type === 'system') {
      // System messages are centered and styled differently
      msgContainer.addClass('system-message');
      msgBubble.child(messageText);
    }
    msgContainer.child(msgBubble);
    chatDisplay.child(msgContainer);
  }

  // Scroll to the bottom of the chat display to show the latest message
  chatDisplay.elt.scrollTop = chatDisplay.elt.scrollHeight;
}
Line-by-line explanation (18 lines)

🔧 Subcomponents:

for-loop Loop through all messages for (let msg of messages) { let msgContainer = createElement('div'); msgContainer.class('message-container'); // ... create elements and append chatDisplay.child(msgContainer); }

Loops through every message in the messages array and creates DOM elements for each one

conditional Style by message type if (msg.type === 'user') { msgContainer.addClass('user-message'); msgBubble.child(messageText); } else if (msg.type === 'ai') { msgContainer.addClass('ai-message'); msgBubble.child(senderName); msgBubble.child(messageText); } else if (msg.type === 'system') { msgContainer.addClass('system-message'); msgBubble.child(messageText); }

Applies different CSS classes and DOM structure based on whether the message is from the user, an AI person, or the system

chatDisplay.html('');
Clears all HTML content from the chatDisplay div, removing all previously rendered messages
for (let msg of messages) {
Loops through every message object in the messages array using a for-of loop
let msgContainer = createElement('div');
Creates a new div that will hold one complete message (sender, text, and styling)
msgContainer.class('message-container');
Assigns the CSS class 'message-container' to this div so it gets styled with the CSS rules for that class
let msgBubble = createElement('div');
Creates a new div inside the container that represents the actual chat bubble
msgBubble.class('message-bubble');
Assigns the CSS class 'message-bubble' so it gets styled as a chat bubble
let senderName = createElement('span');
Creates a span element to hold the sender's name
senderName.html(msg.sender + ":");
Sets the span's HTML to the sender's name followed by a colon (e.g., 'Momrshell:')
let messageText = createElement('span');
Creates a span element to hold the actual message text
messageText.html(msg.text);
Sets the span's HTML to the message text
if (msg.type === 'user') {
Checks if this message is from the user (as opposed to an AI person or the system)
msgBubble.child(messageText);
For user messages, adds only the message text to the bubble (not the sender name)
} else if (msg.type === 'ai') {
Checks if this message is from one of the AI personas
msgBubble.child(senderName);
For AI messages, adds the sender name span first
msgBubble.child(messageText);
Then adds the message text span
msgContainer.child(msgBubble);
Adds the bubble div as a child of the container div
chatDisplay.child(msgContainer);
Adds the complete container div to the chatDisplay, making it visible in the chat
chatDisplay.elt.scrollTop = chatDisplay.elt.scrollHeight;
Scrolls the chat display to the bottom so the newest message is visible (scrollHeight is the total scroll distance, scrollTop sets the current position)

windowResized()

windowResized() is a p5.js built-in function that runs whenever the browser window is resized. It's important for responsive design. In this sketch, we only need to resize the canvas; the DOM elements handle themselves because they use CSS flexbox, which automatically adjusts to fill available space.

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  // The DOM elements for the chat app are styled with CSS flexbox and absolute positioning,
  // so they will adjust automatically without needing p5.js resizing logic here.
}
Line-by-line explanation (2 lines)
resizeCanvas(windowWidth, windowHeight);
Resizes the p5.js canvas to match the new window size whenever the user resizes their browser
// The DOM elements for the chat app are styled with CSS flexbox and absolute positioning,
This comment explains that the chat UI will automatically reflow because CSS handles responsive layout

📦 Key Variables

inputField p5.Renderer (HTML input element)

Reference to the text input box where users type messages

inputField = createInput('');
sendButton p5.Renderer (HTML button element)

Reference to the Send button that users click to submit messages

sendButton = createButton('Send');
chatDisplay p5.Renderer (HTML div element)

Reference to the div that shows all the chat messages

chatDisplay = createElement('div');
chatContainer p5.Renderer (HTML div element)

Reference to the main #chat-app div from the HTML where all chat elements are placed

chatContainer = select('#chat-app');
messages array of objects

Stores all chat messages (user, AI, and system) with their sender, text, and type properties

let messages = [{ sender: "You", text: "Hello!", type: "user" }];
people array of objects

Stores the three AI personas (Momrshell, Chewr, AI) with their names, lastMessage, and lastTopic properties

let people = [{ name: "Momrshell", lastMessage: "", lastTopic: null }];
genericResponses array of strings

List of fallback responses used when no keyword matches any topic

let genericResponses = ["That's interesting!", "Tell me more.", ...];
responsesByTopic object

Maps conversation topics (general, Alice, Bob, Charlie) to arrays of response objects, each with keywords and a response function

const responsesByTopic = { general: [...], Alice: [...], Bob: [...], Charlie: [...] };

🔧 Potential Improvements (5)

Here are some ways this code could be enhanced:

PERFORMANCE updateChatDisplay()

The entire chat display is rebuilt from scratch every time a new message arrives. For a chat with thousands of messages, this becomes slow.

💡 Instead of clearing and rebuilding the whole display, append only the new message to the DOM. Store a reference to msgContainer for each message and update just what changed.

FEATURE generatePersonResponse()

The topic assignment logic after matching a keyword is complex and somewhat fragile - it guesses which person's domain a keyword belongs to using hardcoded string checks.

💡 Add a 'domain' property to each response object in responsesByTopic (e.g., { keywords: [...], domain: 'Alice', response: ... }) so topic assignment is data-driven instead of logic-driven.

BUG generatePersonResponse()

If a user types a message with no keywords at all, the function picks a random generic response. But for the next identical keyword-less message, it will pick a different random response, making the AI seem flaky.

💡 Add a 'noMatchResponse' property to each person object so they can have consistent fallback personality (e.g., Momrshell always says 'Interesting coding question!' when confused).

STYLE sendMessage()

The response loop doesn't give visual feedback about which person is 'typing' - all three responses appear instantly and simultaneously.

💡 Add setTimeout() delays so each person's response appears with a slight delay, simulating thinking time and making the chat feel more natural and less robotic.

FEATURE setup()

The chat display area has no visual indicator of who you are or how to start - the welcome message is the only guidance.

💡 Add a system message after the welcome that explains the three personas and what topics each one specializes in, so new users know what to expect.

🔄 Code Flow

Code flow showing setup, draw, sendmessage, generatepersonresponse, updatechatdisplay, windowresized

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

graph TD start[Start] --> setup[setup] setup --> canvas-setup[Canvas Initialization] setup --> input-field-creation[Input Field Setup] setup --> button-creation[Send Button Setup] setup --> draw[draw loop] draw -->|Event-Driven| sendmessage[sendMessage] sendmessage --> input-validation[Empty Message Check] input-validation -->|Valid| response-loop[Generate All Responses] response-loop --> last-topic-check[Last Topic Priority Check] last-topic-check -->|Match Found| general-and-specific-search[General and Person-Specific Topic Search] last-topic-check -->|No Match| fallback-response[Fallback Generic Response] response-loop --> updatechatdisplay[Update Chat Display] updatechatdisplay --> message-loop[Loop Through All Messages] message-loop --> message-type-conditional[Style by Message Type] message-loop --> updatechatdisplay click setup href "#fn-setup" click draw href "#fn-draw" click sendmessage href "#fn-sendmessage" click input-validation href "#sub-input-validation" click response-loop href "#sub-response-loop" click last-topic-check href "#sub-last-topic-check" click general-and-specific-search href "#sub-general-and-specific-search" click fallback-response href "#sub-fallback-response" click updatechatdisplay href "#fn-updatechatdisplay" click message-loop href "#sub-message-loop" click message-type-conditional href "#sub-message-type-conditional" setup -->|Responsive| windowresized[windowResized] click windowresized href "#fn-windowresized"

❓ Frequently Asked Questions

What visual elements does the 'chat with people' sketch display?

The sketch features a chat interface that includes a display area for messages, an input field for user text, and a send button to facilitate interactions.

How can users engage with the 'chat with people' sketch?

Users can type messages into the input field and click the send button to communicate with different characters, each responding based on their personality and the context of the conversation.

What creative coding concepts are demonstrated in this p5.js sketch?

This sketch showcases natural language processing concepts by generating responses based on user input and predefined keywords, as well as managing conversation state with dynamic message handling.

Preview

chat with people - p5.js creative coding sketch preview
Sketch Preview
Code flow diagram showing the structure of chat with people - Code flow showing setup, draw, sendmessage, generatepersonresponse, updatechatdisplay, windowresized
Code Flow Diagram