TTGO T CALL 1.4 ESP 32

kalitka800

✩✩✩✩✩✩✩
10 Мар 2025
1
0
Оформи код соответствующим тэгом, см. Правила
Всем прив: типа я хочу оч сделать дум 93 года, недавно добавил врагов и.... Часть карты норм, другая — черная, проходишь рядом и все ок. И еще, как сделать так, чтобы некоторые объекты на фоне стены становились черными, чтобы их было всегда видно. Короч, в чем может быть проблема и как ее решить?
Ниже полный код






#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <math.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_ADDR 0x3C

#define JOY_X_PIN 34
#define JOY_Y_PIN 35
#define JOY_BTN_PIN 32
#define SAMPLES 5
#define DEADZONE 300
#define CENTER 2048

#define FOV 1.047f
#define MOVE_SPEED 0.08f
#define ROT_SPEED 0.05f
#define PLAYER_SIZE 0.2f
#define PI 3.1415926535f
#define INVERSION -1
#define FLASH_DURATION 5
#define ACTION_DURATION 1000

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);

struct Player {
float x = 1.5f;
float y = 1.5f;
float angle = 0.0f;
int health = 100;
int ammo = 30;
float score = 0.0f;
String lastAction = "";
unsigned long actionTimer = 0;
} player;

struct Enemy {
float x;
float y;
bool alive;
};

Enemy enemies[] = {
{3.5f, 3.5f, true},
{7.5f, 5.5f, true},
{12.5f, 7.5f, true}
};

byte maze[9][16] = {
{1,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,0,1},
{1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1},
{1,0,1,0,0,0,2,0,0,1,0,0,0,2,0,1},
{1,0,0,0,1,1,1,1,0,1,1,1,1,0,0,1},
{1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1},
{1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
};

int xCenter, yCenter;
int fps = 0;
uint8_t flash_alpha = 0;

void setup() {
Serial.begin(115200);
pinMode(JOY_BTN_PIN, INPUT_PULLUP);

Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("Display error");
while(1);
}
display.setTextColor(SSD1306_WHITE);

xCenter = analogRead(JOY_X_PIN);
yCenter = analogRead(JOY_Y_PIN);
}

void loop() {
unsigned long start = millis();

int joyX = analogRead(JOY_X_PIN);
int joyY = analogRead(JOY_Y_PIN);
bool btn = digitalRead(JOY_BTN_PIN);

handleInput(joyX, joyY);
handleFlash(btn);
checkActionTimeout();

display.clearDisplay();
render3D();
drawStatusPanel();
drawGun();
drawFlash();
display.display();

updateFPS();

unsigned long elapsed = millis() - start;
if(elapsed < 16) delay(16 - elapsed);
}

void handleInput(int x, int y) {
static float lastX = player.x;
static float lastY = player.y;

int xVal = x - xCenter;
if(abs(xVal) > DEADZONE) {
player.angle += INVERSION * (xVal / 2048.0f) * ROT_SPEED;
player.angle = fmod(player.angle, 2*PI);
return;
}

int yVal = yCenter - y;
if(yVal > DEADZONE) {
float move = (yVal / 2048.0f) * MOVE_SPEED;
float newX = player.x + cos(player.angle) * move;
float newY = player.y + sin(player.angle) * move;

if(maze[(int)newY][(int)newX] == 0) {
player.x = newX;
player.y = newY;

if(hypot(player.x - lastX, player.y - lastY) > 0.05) {
player.score += 0.1f;
player.lastAction = "+walking";
player.actionTimer = millis();
}
lastX = player.x;
lastY = player.y;
}
}
}

void handleFlash(bool btn) {
static bool last_btn = false;

if(btn && !last_btn && player.ammo > 0) {
flash_alpha = FLASH_DURATION;
player.ammo--;
player.score += 1.0f;
player.lastAction = "+shot";
player.actionTimer = millis();

for(auto &e : enemies) {
if(e.alive && fabs(player.x - e.x) < 1.0f && fabs(player.y - e.y) < 1.0f) {
e.alive = false;
player.score += 10.0f;
player.lastAction = "+kill";
player.actionTimer = millis();
}
}
}
last_btn = btn;

if(flash_alpha > 0) flash_alpha--;
}

void checkActionTimeout() {
if(millis() - player.actionTimer > ACTION_DURATION) {
player.lastAction = "";
}
}

void render3D() {
for(int col = 0; col < SCREEN_WIDTH; col++) {
float rayAngle = player.angle - FOV/2 + (col * FOV/SCREEN_WIDTH);
float dist = 0;

while(dist < 15) {
float rx = player.x + cos(rayAngle) * dist;
float ry = player.y + sin(rayAngle) * dist;

if(rx < 0 || rx >= 16 || ry < 0 || ry >= 9) break;

if(maze[(int)ry][(int)rx] == 1) {
dist *= cos(rayAngle - player.angle);
int h = SCREEN_HEIGHT / (dist + 0.001);
display.drawLine(col, (64-h)/2, col, (64+h)/2, SSD1306_WHITE);
break;
}
else if(maze[(int)ry][(int)rx] == 2) {
drawEnemy(rx + 0.5f, ry + 0.5f, dist);
break;
}
dist += 0.1;
}
}
}

void drawEnemy(float ex, float ey, float dist) {
float screenX = SCREEN_WIDTH/2 + (atan2(ey - player.y, ex - player.x) - player.angle) * (SCREEN_WIDTH/2)/tan(FOV/2);
int size = 20/(dist + 0.1f);

if(size > 3) {
// Туловище
drawEnemyPart(screenX - size/4, SCREEN_HEIGHT/2 - size/3, size/2, size*0.8, size/8, true);

// Голова
int headSize = size/3;
drawEnemyPart(screenX - headSize/2, SCREEN_HEIGHT/2 - size/3 - headSize, headSize, headSize, headSize/2, false);

// Рот
for(int i = -headSize/3; i <= headSize/3; i++) {
int px = screenX + i;
int py = SCREEN_HEIGHT/2 - size/3 - headSize/2;
if(display.getPixel(px, py)) {
display.drawPixel(px, py, SSD1306_BLACK);
} else {
display.drawPixel(px, py, SSD1306_WHITE);
}
}

// Ноги
drawEnemyLeg(screenX - size/6, SCREEN_HEIGHT/2 + size/3, size/4);
drawEnemyLeg(screenX + size/6, SCREEN_HEIGHT/2 + size/3, size/4);
}
}

void drawEnemyPart(int x, int y, int w, int h, int r, bool checkBg) {
for(int i = x; i < x + w; i++) {
for(int j = y; j < y + h; j++) {
if(checkBg && display.getPixel(i, j) == SSD1306_WHITE) continue;
float dx = (i - x) / (float)w;
float dy = (j - y) / (float)h;
if(powf(dx - 0.5f, 2) + powf(dy - 0.5f, 2) < 0.25f) {
display.drawPixel(i, j, SSD1306_WHITE);
}
}
}
}

void drawEnemyLeg(int x, int y, int h) {
for(int i = 0; i < h; i++) {
if(display.getPixel(x, y + i) == SSD1306_BLACK) {
display.drawPixel(x, y + i, SSD1306_WHITE);
}
}
}

void drawStatusPanel() {
display.drawRect(SCREEN_WIDTH - 62, 2, 60, 32, SSD1306_WHITE);

display.setCursor(SCREEN_WIDTH - 58, 5);
display.print("SCORE:");
display.print(player.score, 1);

display.setCursor(SCREEN_WIDTH - 58, 15);
display.print("AMMO:");
display.print(player.ammo);

display.setCursor(SCREEN_WIDTH - 58, 25);
display.print(player.lastAction);
}

void drawGun() {
const int gun_x = 64;
const int gun_y = 54;

display.fillRect(gun_x - 12, gun_y - 2, 24, 4, SSD1306_WHITE);
display.fillRoundRect(gun_x - 4, gun_y + 4, 8, 10, 2, SSD1306_WHITE);
display.fillRect(gun_x - 2, gun_y + 14, 4, 6, SSD1306_WHITE);
}

void drawFlash() {
if(flash_alpha == 0) return;

int flash_size = map(flash_alpha, 0, FLASH_DURATION, 2, 8);
for(int i = 0; i < 10; i++) {
display.drawPixel(64 + random(-flash_size, flash_size),
48 + random(-flash_size, flash_size),
SSD1306_WHITE);
}
}

void updateFPS() {
static unsigned long last = 0;
static int count = 0;

count++;
if(millis() - last >= 1000) {
fps = count;
count = 0;
last = millis();
}
}