SpaceInvaders
This commit is contained in:
parent
aad95e9292
commit
9eb7d17d6f
@ -30,4 +30,4 @@ add_custom_target(
|
||||
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>
|
||||
|
||||
#define X true
|
||||
#define _ false
|
||||
|
||||
typedef unsigned long millis_t;
|
||||
|
||||
#endif
|
||||
|
||||
17
src/main.cpp
17
src/main.cpp
@ -5,6 +5,7 @@
|
||||
#include "mode/Pong/Pong.h"
|
||||
#include "mode/Test/Border.h"
|
||||
#include "mode/Clock/Clock.h"
|
||||
#include "mode/SpaceInvaders/SpaceInvaders.h"
|
||||
|
||||
enum ModeId {
|
||||
NONE,
|
||||
@ -14,12 +15,13 @@ enum ModeId {
|
||||
GAME_OF_LIFE_WHITE_FADE,
|
||||
GAME_OF_LIFE_COLOR_FADE,
|
||||
GAME_OF_LIFE_RANDOM_COLOR,
|
||||
PONG
|
||||
PONG,
|
||||
SPACE_INVADERS,
|
||||
};
|
||||
|
||||
Display display(32, 8);
|
||||
|
||||
ModeId newModeId = GAME_OF_LIFE_WHITE_FADE;
|
||||
ModeId newModeId = SPACE_INVADERS;
|
||||
|
||||
ModeId currentModeId = NONE;
|
||||
|
||||
@ -27,6 +29,10 @@ millis_t lastMillis = 0;
|
||||
|
||||
Mode *mode = nullptr;
|
||||
|
||||
double speed = 1.0;
|
||||
|
||||
bool connected = false;
|
||||
|
||||
void checkMode();
|
||||
|
||||
void stepMode();
|
||||
@ -47,10 +53,6 @@ void setup() {
|
||||
|
||||
void setSpeed(double value);
|
||||
|
||||
double speed = 1.0;
|
||||
|
||||
bool connected = false;
|
||||
|
||||
void loop() {
|
||||
bool hasIp = (uint32_t) WiFi.localIP() != 0;
|
||||
if (!connected) {
|
||||
@ -152,6 +154,9 @@ void loadNewMode() {
|
||||
case PONG:
|
||||
mode = new Pong(&display);
|
||||
break;
|
||||
case SPACE_INVADERS:
|
||||
mode = new SpaceInvaders(&display);
|
||||
break;
|
||||
}
|
||||
Serial.printf("Mode: %s\n", mode == nullptr ? "None" : mode->getName());
|
||||
}
|
||||
|
||||
@ -3,9 +3,6 @@
|
||||
|
||||
#include "mode/Mode.h"
|
||||
|
||||
#define X true
|
||||
#define _ false
|
||||
|
||||
class Clock : public Mode {
|
||||
|
||||
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