euclidean_ball — Arduino Uno simulation

An interactive Arduino Uno circuit simulation you can run free in your browser on Velxio, by siteofprojects.

Components

Sketch code

// TFT ILI9341 Display Demo (240x320)
// Library: Adafruit ILI9341 + Adafruit GFX
// Connect: CS=10, DC/RS=9, RST=8, LED=7, MOSI=11(SPI), SCK=13(SPI)

#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>

#define TFT_CS   10
#define TFT_DC    9
#define TFT_RST   8
#define TFT_LED   7

Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);

// Background color: blue (visible on dark simulator canvas)
#define BG_COLOR 0x0000
#define Ball_COLOR 0xf800
// --- Physics Variables ---
float ballX = 160.0; // Start center screen
float ballY = 200.0;
float ballDX = 1.0;  // X speed
float ballDY = -5.0; // Y speed
int ballRadius = 10;

// For erasing the previous frame without clearing the whole screen (prevents flickering)
float oldBallX = ballX;
float oldBallY = ballY;

// --- Spatial Grid Variables ---
bool boxes[9];                // Array to store active/inactive state of the 9 steps
const int boxSize = 40;       // 40x40 pixel boxes
const int gridStartX = 100;   // Centers the 120px grid on a 320px screen
const int gridStartY = 60;    // Centers the 120px grid on a 240px screen

void setup() {
 

 tft.begin();
  tft.setRotation(1); // Set to Landscape (320x240)
  //tft.fillScreen(0x0000);

  // Initialize and draw the 3x3 sequencer grid
  for (int i = 0; i < 9; i++) {
    boxes[i] = true; // Set all boxes to active (1)
    
    // Calculate grid coordinates based on index (0-8)
    int col = i % 3;
    int row = i / 3;
    int x = gridStartX + (col * boxSize);
    int y = gridStartY + (row * boxSize);
    
    // Draw the box (leaving a 1px gap for visual padding)
    // -> SWAP THIS if you want to draw a base sprite for the sequencer pads
    tft.drawRect(x + 1, y + 1, boxSize - 2, boxSize - 2, Ball_COLOR);
  }
}

void loop() {
  // 1. ERASE OLD BALL (Draw black over the last position)
  // -> If using sprites, draw a black square over old pos, or redraw background
  tft.fillRect(ballX, ballY, ballRadius+1,ballRadius+1, BG_COLOR);
  
  // 2. UPDATE POSITION
  ballX += ballDX;
  ballY += ballDY;

  // 3. WALL BOUNDARY COLLISIONS (Screen is 320x240)
  if (ballX - ballRadius <= 0 || ballX + ballRadius >= 320) {
    ballDX = -ballDX; // Flip X velocity
    ballX += ballDX;  // Push out of wall to prevent sticking
  }
  if (ballY - ballRadius <= 0 || ballY + ballRadius >= 240) {
    ballDY = -ballDY; // Flip Y velocity
    ballY += ballDY; 
  }

  // 4. 3x3 GRID COLLISION MATH
  // First check: Is the ball inside the grid zone?
  if (ballX > gridStartX && ballX < gridStartX + (boxSize * 3) &&
      ballY > gridStartY && ballY < gridStartY + (boxSize * 3)) {
      
      // Calculate which specific row and column the ball is in
      int col = (ballX - gridStartX) / boxSize;
      int row = (ballY - gridStartY) / boxSize;
      
      // Convert to 1D array index (0-8)
      int index = col + (row * 3);

      // If the calculated index is valid and the box is still active
      if (index >= 0 && index < 9 && boxes[index]) {