#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// =====================
// CONFIG BUTTON
// =====================
#define BTN_UP 2
#define BTN_DOWN 14
#define BTN_LEFT 13
#define BTN_RIGHT 4
// =====================
// ENGINE CORE
// =====================
unsigned long lastTime;
float deltaTime;
void Engine_Init() {
lastTime = millis();
}
void Engine_Update() {
unsigned long now = millis();
deltaTime = (now - lastTime) / 1000.0;
lastTime = now;
}
// =====================
// INPUT SYSTEM
// =====================
bool inputUp, inputDown, inputLeft, inputRight;
void Input_Update() {
inputUp = !digitalRead(BTN_UP);
inputDown = !digitalRead(BTN_DOWN);
inputLeft = !digitalRead(BTN_LEFT);
inputRight = !digitalRead(BTN_RIGHT);
}
// =====================
// GAME DATA
// =====================
int playerX = 64;
int playerY = 32;
int speed = 60; // pixel per second
// =====================
// GAME LOGIC
// =====================
void Game_Update() {
if (inputUp) playerY -= speed * deltaTime;
if (inputDown) playerY += speed * deltaTime;
if (inputLeft) playerX -= speed * deltaTime;
if (inputRight) playerX += speed * deltaTime;
// Boundary check
if (playerX < 0) playerX = 0;
if (playerX > SCREEN_WIDTH-1) playerX = SCREEN_WIDTH-1;
if (playerY < 0) playerY = 0;
if (playerY > SCREEN_HEIGHT-1) playerY = SCREEN_HEIGHT-1;
}
// =====================
// RENDER SYSTEM
// =====================
void Game_Render() {
display.clearDisplay();
display.drawPixel(playerX, playerY, WHITE);
display.display();
}
// =====================
// SETUP & LOOP
// =====================
void setup() {
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_LEFT, INPUT_PULLUP);
pinMode(BTN_RIGHT, INPUT_PULLUP);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while(true); // OLED gagal
}
Engine_Init();
}
void loop() {
Engine_Update();
Input_Update();
Game_Update();
Game_Render();
}