SpaceInvaders
This commit is contained in:
parent
aad95e9292
commit
9eb7d17d6f
@ -30,4 +30,4 @@ add_custom_target(
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(Z_DUMMY_TARGET ${SRC_LIST} src/mode/Test/Border.h src/mode/Clock/Clock.h)
|
add_executable(Z_DUMMY_TARGET ${SRC_LIST} src/mode/Test/Border.h src/mode/Clock/Clock.h src/mode/SpaceInvaders/SpaceInvaders.h)
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define X true
|
||||||
|
#define _ false
|
||||||
|
|
||||||
typedef unsigned long millis_t;
|
typedef unsigned long millis_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
17
src/main.cpp
17
src/main.cpp
@ -5,6 +5,7 @@
|
|||||||
#include "mode/Pong/Pong.h"
|
#include "mode/Pong/Pong.h"
|
||||||
#include "mode/Test/Border.h"
|
#include "mode/Test/Border.h"
|
||||||
#include "mode/Clock/Clock.h"
|
#include "mode/Clock/Clock.h"
|
||||||
|
#include "mode/SpaceInvaders/SpaceInvaders.h"
|
||||||
|
|
||||||
enum ModeId {
|
enum ModeId {
|
||||||
NONE,
|
NONE,
|
||||||
@ -14,12 +15,13 @@ enum ModeId {
|
|||||||
GAME_OF_LIFE_WHITE_FADE,
|
GAME_OF_LIFE_WHITE_FADE,
|
||||||
GAME_OF_LIFE_COLOR_FADE,
|
GAME_OF_LIFE_COLOR_FADE,
|
||||||
GAME_OF_LIFE_RANDOM_COLOR,
|
GAME_OF_LIFE_RANDOM_COLOR,
|
||||||
PONG
|
PONG,
|
||||||
|
SPACE_INVADERS,
|
||||||
};
|
};
|
||||||
|
|
||||||
Display display(32, 8);
|
Display display(32, 8);
|
||||||
|
|
||||||
ModeId newModeId = GAME_OF_LIFE_WHITE_FADE;
|
ModeId newModeId = SPACE_INVADERS;
|
||||||
|
|
||||||
ModeId currentModeId = NONE;
|
ModeId currentModeId = NONE;
|
||||||
|
|
||||||
@ -27,6 +29,10 @@ millis_t lastMillis = 0;
|
|||||||
|
|
||||||
Mode *mode = nullptr;
|
Mode *mode = nullptr;
|
||||||
|
|
||||||
|
double speed = 1.0;
|
||||||
|
|
||||||
|
bool connected = false;
|
||||||
|
|
||||||
void checkMode();
|
void checkMode();
|
||||||
|
|
||||||
void stepMode();
|
void stepMode();
|
||||||
@ -47,10 +53,6 @@ void setup() {
|
|||||||
|
|
||||||
void setSpeed(double value);
|
void setSpeed(double value);
|
||||||
|
|
||||||
double speed = 1.0;
|
|
||||||
|
|
||||||
bool connected = false;
|
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
bool hasIp = (uint32_t) WiFi.localIP() != 0;
|
bool hasIp = (uint32_t) WiFi.localIP() != 0;
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
@ -152,6 +154,9 @@ void loadNewMode() {
|
|||||||
case PONG:
|
case PONG:
|
||||||
mode = new Pong(&display);
|
mode = new Pong(&display);
|
||||||
break;
|
break;
|
||||||
|
case SPACE_INVADERS:
|
||||||
|
mode = new SpaceInvaders(&display);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName());
|
Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
#include "mode/Mode.h"
|
#include "mode/Mode.h"
|
||||||
|
|
||||||
#define X true
|
|
||||||
#define _ false
|
|
||||||
|
|
||||||
class Clock : public Mode {
|
class Clock : public Mode {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
241
src/mode/SpaceInvaders/SpaceInvaders.h
Normal file
241
src/mode/SpaceInvaders/SpaceInvaders.h
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
#ifndef SPACEINVADERS_H
|
||||||
|
#define SPACEINVADERS_H
|
||||||
|
|
||||||
|
#define ROCKET_MAX 20
|
||||||
|
|
||||||
|
#include "mode/Mode.h"
|
||||||
|
|
||||||
|
struct Rocket {
|
||||||
|
volatile bool alive;
|
||||||
|
uint8_t x;
|
||||||
|
uint8_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Invader {
|
||||||
|
bool alive;
|
||||||
|
uint8_t x;
|
||||||
|
uint8_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpaceInvaders : public Mode {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
millis_t heroRuntime = 0;
|
||||||
|
uint8_t heroX = 0;
|
||||||
|
bool heroLeft = false;
|
||||||
|
uint8_t heroShoot = 0;
|
||||||
|
|
||||||
|
uint8_t invadersCountX;
|
||||||
|
uint8_t invadersCountY;
|
||||||
|
uint8_t invadersAlive = 0;
|
||||||
|
|
||||||
|
millis_t swarmRuntime = 0;
|
||||||
|
uint8_t swarmY = 0;
|
||||||
|
bool swarmLeft = false;
|
||||||
|
bool swarmDown = false;
|
||||||
|
uint8_t swarmX = 0;
|
||||||
|
Invader *swarmBegin;
|
||||||
|
Invader *swarmEnd;
|
||||||
|
|
||||||
|
millis_t rocketRuntime = 0;
|
||||||
|
Rocket *rocketsBegin;
|
||||||
|
Rocket *rocketsEnd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit SpaceInvaders(Display *display) :
|
||||||
|
Mode(display),
|
||||||
|
invadersCountX(display->width / 3),
|
||||||
|
invadersCountY(display->height / 4) {
|
||||||
|
|
||||||
|
swarmBegin = (Invader *) malloc(sizeof(Invader) * invadersCountX * invadersCountY);
|
||||||
|
swarmEnd = swarmBegin + invadersCountX * invadersCountY;
|
||||||
|
|
||||||
|
rocketsBegin = (Rocket *) malloc(sizeof(Rocket) * ROCKET_MAX);
|
||||||
|
rocketsEnd = rocketsBegin + ROCKET_MAX;
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
~SpaceInvaders() override {
|
||||||
|
free(swarmBegin);
|
||||||
|
free(rocketsBegin);
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *getName() override {
|
||||||
|
return "Space Invaders";
|
||||||
|
}
|
||||||
|
|
||||||
|
void step(millis_t dt) override {
|
||||||
|
stepRockets(dt);
|
||||||
|
stepInvaders(dt);
|
||||||
|
collide();
|
||||||
|
stepHero(dt);
|
||||||
|
if (invadersAlive == 0) {
|
||||||
|
Serial.println("WINNER!");
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
if (swarmY + (invadersCountY - 1) * 2 >= display->height - 1) {
|
||||||
|
Serial.println("GAME OVER");
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stepRockets(millis_t dt) {
|
||||||
|
rocketRuntime += dt;
|
||||||
|
if (rocketRuntime > 200) {
|
||||||
|
rocketRuntime = 0;
|
||||||
|
for (Rocket *rocket = rocketsBegin; rocket < rocketsEnd; rocket++) {
|
||||||
|
if (rocket->alive) {
|
||||||
|
if (rocket->y == 0) {
|
||||||
|
rocket->alive = false;
|
||||||
|
} else {
|
||||||
|
rocket->y -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stepInvaders(millis_t dt) {
|
||||||
|
swarmRuntime += dt;
|
||||||
|
|
||||||
|
if (swarmDown && swarmRuntime > 500) {
|
||||||
|
swarmDown = false;
|
||||||
|
swarmY++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swarmRuntime >= 1000) {
|
||||||
|
swarmRuntime = 0;
|
||||||
|
if (swarmLeft) {
|
||||||
|
swarmX--;
|
||||||
|
if (swarmX == 0) {
|
||||||
|
swarmLeft = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
swarmX++;
|
||||||
|
if (swarmX == 3) {
|
||||||
|
swarmLeft = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (swarmX == 0) {
|
||||||
|
swarmDown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stepHero(millis_t dt) {
|
||||||
|
heroRuntime += dt;
|
||||||
|
if (heroRuntime >= 50) {
|
||||||
|
heroRuntime = 0;
|
||||||
|
if (heroLeft) {
|
||||||
|
heroX--;
|
||||||
|
if (heroX <= 1) {
|
||||||
|
heroLeft = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
heroX++;
|
||||||
|
if (heroX >= display->width - 2) {
|
||||||
|
heroLeft = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heroShoot++;
|
||||||
|
if (heroShoot >= 10) {
|
||||||
|
heroShoot = 0;
|
||||||
|
shoot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shoot() {
|
||||||
|
for (Rocket *rocket = rocketsBegin; rocket < rocketsEnd; rocket++) {
|
||||||
|
if (!rocket->alive) {
|
||||||
|
rocket->alive = true;
|
||||||
|
rocket->x = heroX;
|
||||||
|
rocket->y = display->height - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void collide() {
|
||||||
|
for (Rocket *rocket = rocketsBegin; rocket < rocketsEnd; rocket++) {
|
||||||
|
for (Invader *invader = swarmBegin; invader < swarmEnd; invader++) {
|
||||||
|
if (invader->alive && rocket->alive && collide(rocket, invader)) {
|
||||||
|
rocket->alive = false;
|
||||||
|
invader->alive = false;
|
||||||
|
invadersAlive--;
|
||||||
|
// Serial.printf("Killed invader at (%2u/%2u): %2u/%2u alive.\n", invader->x, invader->y, invadersAlive, invadersCountX * invadersCountY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool collide(const Rocket *rocket, const Invader *invader) const {
|
||||||
|
return swarmY + invader->y * 2 == rocket->y && swarmX + invader->x * 3 <= rocket->x && rocket->x <= swarmX + invader->x * 3 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() {
|
||||||
|
display->clear();
|
||||||
|
drawInvaders();
|
||||||
|
drawRockets();
|
||||||
|
drawHero();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawInvaders() {
|
||||||
|
for (Invader *invader = swarmBegin; invader < swarmEnd; invader++) {
|
||||||
|
if (invader->alive) {
|
||||||
|
display->set(swarmX + invader->x * 3 + 0, swarmY + invader->y * 2, 255, 0, 0);
|
||||||
|
display->set(swarmX + invader->x * 3 + 1, swarmY + invader->y * 2, 255, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawRockets() {
|
||||||
|
for (Rocket *rocket = rocketsBegin; rocket < rocketsEnd; rocket++) {
|
||||||
|
if (!rocket->alive) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
display->set(rocket->x, rocket->y, 255, 255, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawHero() {
|
||||||
|
display->set(heroX - 1, display->height - 1, 0, 0, 255);
|
||||||
|
display->set(heroX + 0, display->height - 1, 0, 0, 255);
|
||||||
|
display->set(heroX + 1, display->height - 1, 0, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
heroRuntime = 0;
|
||||||
|
heroLeft = false;
|
||||||
|
heroShoot = 0;
|
||||||
|
heroX = display->width / 2;
|
||||||
|
|
||||||
|
rocketRuntime = 0;
|
||||||
|
for (Rocket *rocket = rocketsBegin; rocket < rocketsEnd; rocket++) {
|
||||||
|
rocket->alive = false;
|
||||||
|
rocket->x = 0;
|
||||||
|
rocket->y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
swarmRuntime = 0;
|
||||||
|
invadersAlive = invadersCountX * invadersCountY;
|
||||||
|
swarmX = 0;
|
||||||
|
swarmY = 0;
|
||||||
|
swarmLeft = false;
|
||||||
|
swarmDown = false;
|
||||||
|
uint8_t n = 0;
|
||||||
|
for (Invader *invader = swarmBegin; invader < swarmEnd; invader++) {
|
||||||
|
invader->alive = true;
|
||||||
|
invader->x = n % invadersCountX;
|
||||||
|
invader->y = n / invadersCountX;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue
Block a user