For many days I've been trying to make a raycasting engine for Arduino in which 3 steps are essential -making a 3d environment (done👍) -making the player move (pending) -hand the player a assault rifle (pending) So,here I have problem with the movement of player which I have no I idea with ,I have tried dozens of ways to make the player move but it just glued to one place.If anyone can help then it will be just amazing.I have made this project on wokwi btw.If anyone knows about wokwi then you can also help me there
Raycast engine - Wokwi ESP32, STM32, Arduino Simulator. AND This is gonna run on a esp32 ,display the game in tft display and inputs by 5 push buttons ......Here's the code
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>
#define TFT_CS 15
#define TFT_RST -1
#define TFT_DC 33
#define BUTTON_UP 4
#define BUTTON_DOWN 36
#define BUTTON_LEFT 34
#define BUTTON_RIGHT 35
#define TFT_WIDTH 320
#define TFT_HEIGHT 240
#define MAP_WIDTH 15
#define MAP_HEIGHT 15
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
int worldMap[MAP_WIDTH][MAP_HEIGHT] = {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,1,0,0,0,0,0,0,1},
{1,0,0,1,0,0,0,0,0,0,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};
double posX = 13.0, posY = 7.0, posZ = 0;
double dirX = -1.0, dirY = 0.0, planeX = 0.0, planeY = 0.66;
double speedVar = 0.50, rotSpeedVar = 0.1;
void setup() {
tft.begin();
tft.setRotation(1);
Serial.begin(115200);
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_LEFT, INPUT_PULLUP);
pinMode(BUTTON_RIGHT, INPUT_PULLUP);
}
void loop() {
handleInput();
movePlayer(1);
renderWalls();
}
// Button states
bool upPressed = false, downPressed = false, leftPressed = false, rightPressed = false;
void handleInput() {
// Read button states
upPressed = !digitalRead(BUTTON_UP);
downPressed = !digitalRead(BUTTON_DOWN);
leftPressed = !digitalRead(BUTTON_LEFT);
rightPressed = !digitalRead(BUTTON_RIGHT);
// Update player position based on button presses
if (upPressed) {
posY -= speedVar;
dirY = cos(rotSpeedVar) * dirY - sin(rotSpeedVar) * dirX;
dirX = sin(rotSpeedVar) * dirY + cos(rotSpeedVar) * dirX;
}
if (downPressed) {
posY += speedVar;
dirY = cos(-rotSpeedVar) * dirY - sin(-rotSpeedVar) * dirX;
dirX = sin(-rotSpeedVar) * dirY + cos(-rotSpeedVar) * dirX;
}
if (leftPressed) {
posX -= speedVar;
dirX = cos(rotSpeedVar) * dirX - sin(rotSpeedVar) * dirY;
dirY = sin(rotSpeedVar) * dirX + cos(rotSpeedVar) * dirY;
}
if (rightPressed) {
posX += speedVar;
dirX = cos(-rotSpeedVar) * dirX - sin(-rotSpeedVar) * dirY;
dirY = sin(-rotSpeedVar) * dirX + cos(-rotSpeedVar) * dirY;
}
}
void movePlayer(double deltaTime) {
//Ensure the player stays within the map boundaries
posX = constrain(posX, 0.0, double(MAP_WIDTH - 1));
posY = constrain(posY, 0.0, double(MAP_HEIGHT - 1));
}
void renderWalls() {
tft.fillScreen(ILI9341_BLACK);
for (int x = 0; x < TFT_WIDTH; ++x) {
double cameraX = 2 * x / double(TFT_WIDTH) - 1;
double rayDirX = dirX + planeX * cameraX;
double rayDirY = dirY + planeY * cameraX;
int mapX = int(posX);
int mapY = int(posY);
double deltaDistX = abs(1 / rayDirX);
double deltaDistY = abs(1 / rayDirY);
int stepX, stepY;
double sideDistX, sideDistY;
if (rayDirX < 0) {
stepX = -1;
sideDistX = (posX - mapX) * deltaDistX;
} else {
stepX = 1;
sideDistX = (mapX + 1.0 - posX) * deltaDistX;
}
if (rayDirY < 0) {
stepY = -1;
sideDistY = (posY - mapY) * deltaDistY;
} else {
stepY = 1;
sideDistY = (mapY + 1.0 - posY) * deltaDistY;
}
bool hit = false;
int side;
while (!hit) {
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
} else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
if (worldMap[mapX][mapY] > 0) hit = true;
}
// Calculate perpendicular distance to wall
double perpWallDist;
if (side == 0) {
perpWallDist = fabs((mapX - posX + (1 - stepX) / 2) / rayDirX);
} else {
perpWallDist = fabs((mapY - posY + (1 - stepY) / 2) / rayDirY);
}
// Calculate wall height
int lineHeight = int(TFT_HEIGHT / perpWallDist);
// Calculate draw start and draw end
int drawStart = max(0, -lineHeight / 2 + TFT_HEIGHT / 2);
int drawEnd = min(TFT_HEIGHT - 1, lineHeight / 2 + TFT_HEIGHT / 2);
// Draw the wall slice
int color = (worldMap[mapX][mapY] == 1) ? ILI9341_RED : ILI9341_WHITE;
tft.drawFastVLine(x, drawStart, drawEnd - drawStart + 1, color);
}
}