//Torch + RayCasting
//@stepko
//2021
/* Focus on diagram (e.g. by clicking on the matrix)
w p
a s o
d i
*/
#include "FastLED.h"
// Matrix size
#define HEIGHT 24
#define WIDTH 40
// Define pins
#define DATA_PIN 3
#define BUTTON_UP 9
#define BUTTON_DOWN 10
#define BUTTON_LEFT 11
#define BUTTON_RIGHT 12
#define BUTTON_C 5
#define BUTTON_B 6
#define BUTTON_A 7
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
#define NUM_LEDS HEIGHT * WIDTH
CRGB leds[NUM_LEDS];
byte pressed = 0;
void setup() {
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_LEFT, INPUT_PULLUP);
pinMode(BUTTON_RIGHT, INPUT_PULLUP);
pinMode(BUTTON_C, INPUT_PULLUP);
pinMode(BUTTON_B, INPUT_PULLUP);
pinMode(BUTTON_A, INPUT_PULLUP);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
}
void loop() {
// Read the button inputs
pressed = 0;
if (digitalRead(BUTTON_UP) == LOW) {
pressed = 1;
} else if (digitalRead(BUTTON_DOWN) == LOW) {
pressed = 2;
} else if (digitalRead(BUTTON_LEFT) == LOW) {
pressed = 3;
} else if (digitalRead(BUTTON_RIGHT) == LOW) {
pressed = 4;
} else if (digitalRead(BUTTON_C) == LOW) {
pressed = 5;
} else if (digitalRead(BUTTON_B) == LOW) {
pressed = 6;
} else if (digitalRead(BUTTON_A) == LOW) {
pressed = 7;
}
draw();
FastLED.show();
delay(16);
}
#define MAP_W WIDTH
#define MAP_H HEIGHT
#define RAY_LENGHT_M MAP_W + MAP_H
int lightersPosY = 10;
int lightersPosX = 10;
byte PosX;
byte PosY;
byte lightersSpeed = 4;
int alpha = 0;
float angle;
byte rot = 10;
bool ThreeD = false;
bool mape[MAP_W][MAP_H] = {
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
byte POV = WIDTH;
byte PoV = POV / 2;
bool loadingFlag = true;
void draw() {
if (loadingFlag) {
loadingFlag = false;
}
FastLED.clear();
if (pressed == 1) {
lightersPosX += sin(angle) * lightersSpeed;
lightersPosY += cos(angle) * lightersSpeed;
if (lightersPosX < 0) lightersPosX = (MAP_W - 1) * 4;
if (lightersPosX > (MAP_W - 1) * 4) lightersPosX = 0;
if (lightersPosY < 0) lightersPosY = (MAP_H - 1) * 4;
if (lightersPosY > (MAP_H - 1) * 4) lightersPosY = 0;
PosX = lightersPosX / 4;
PosY = lightersPosY / 4;
}
else if (pressed == 2) {
float angle = radians(alpha);
lightersPosX -= sin(angle) * lightersSpeed;
lightersPosY -= cos(angle) * lightersSpeed;
if (lightersPosX < 0) lightersPosX = (MAP_W - 1) * 4;
if (lightersPosX > (MAP_W - 1) * 4) lightersPosX = 0;
if (lightersPosY < 0) lightersPosY = (MAP_H - 1) * 4;
if (lightersPosY > (MAP_H - 1) * 4) lightersPosY = 0;
PosX = lightersPosX / 4;
PosY = lightersPosY / 4;
}
if (pressed == 3) {
alpha += rot;
angle = radians(alpha);
}
else if (pressed == 4) {
alpha -= rot;
angle = radians(alpha);
}
if (pressed == 5) {
POV ++;
if (POV >= 180) POV = 180;
PoV = POV / 2;
}
else if (pressed == 6) {
POV --;
if (POV <= 0) POV = 1;
PoV = POV / 2;
}
if (pressed == 7) {
ThreeD = !ThreeD;
delay(100);
}
for (byte pov = 0; pov < POV+1; pov++) {
byte dist = 0;
byte hdist = 0;
float angleR = radians(alpha + pov - PoV - 1);
float angle_a = sin(angleR);
float angle_b = cos(angleR);
byte ENDPosX = PosX;
byte ENDPosY = PosY;
for (byte i = 0; i < (RAY_LENGHT_M); i++) {
byte ENDPosX = PosX + (i * angle_a);
byte ENDPosY = PosY + (i * angle_b);
if (mape[ENDPosX][ENDPosY] || ENDPosX < 0 || ENDPosX >= MAP_W || ENDPosY < 0 || ENDPosY >= MAP_H) {
if (ThreeD) {
dist = map(i, 0, RAY_LENGHT_M, 255, 0);
hdist = map(i, 0, RAY_LENGHT_M, HEIGHT / 2, 1);
} else {
leds[XY(PosX + ((i - 1) * angle_a), PosY + ((i - 1) * angle_b))] += CHSV(0, 0, 100);
} break;
}
else if (!ThreeD) {
leds[XY(ENDPosX, ENDPosY)] += CHSV(50, 200, 100);
}
}
if (ThreeD) {
for (byte y = 0; y < HEIGHT / 2 - hdist; y++) {
leds[XY((pov * (WIDTH - 1)) / POV, y)] = CHSV(50, 100, ~(y * (256 / HEIGHT * 2)));
} for (byte y = HEIGHT / 2 - hdist; y < HEIGHT / 2 + hdist; y++) {
leds[XY((pov * (WIDTH - 1)) / POV, y)] = CHSV(50, 200, dist);
}
}
}
}
uint16_t XY (uint8_t x, uint8_t y) {
return (y * WIDTH + x);
}