Compare commits
2 Commits
a11da1b3d8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8c6a01422 | ||
|
|
9bf87677a4 |
@@ -4,24 +4,29 @@
|
|||||||
class Particle
|
class Particle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Spawn(int pos);
|
void Spawn(int pos, int life, int aging_speed, const int color[3]);
|
||||||
void Tick(int USE_GRAVITY);
|
void Tick(int USE_GRAVITY);
|
||||||
void Kill();
|
void Kill();
|
||||||
bool Alive();
|
bool Alive();
|
||||||
int _pos;
|
int _pos;
|
||||||
int _power;
|
int _power;
|
||||||
|
int _color[3];
|
||||||
private:
|
private:
|
||||||
int _life;
|
int _life;
|
||||||
int _alive;
|
int _alive;
|
||||||
int _sp;
|
int _sp;
|
||||||
|
int _aging;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Particle::Spawn(int pos){
|
void Particle::Spawn(int pos, int life, int aging_speed, const int color[3]){
|
||||||
_pos = pos;
|
_pos = pos;
|
||||||
_sp = random(-200, 200);
|
_sp = random(-life, life);
|
||||||
_power = 255;
|
_power = 255;
|
||||||
_alive = 1;
|
_alive = 1;
|
||||||
_life = 220 - abs(_sp);
|
_life = life - abs(_sp);
|
||||||
|
_aging = aging_speed;
|
||||||
|
|
||||||
|
for (int i = 0; i< 3; i++) _color[i] = color[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Particle::Tick(int USE_GRAVITY){
|
void Particle::Tick(int USE_GRAVITY){
|
||||||
@@ -33,7 +38,7 @@ void Particle::Tick(int USE_GRAVITY){
|
|||||||
_sp += _life/10;
|
_sp += _life/10;
|
||||||
}
|
}
|
||||||
if(USE_GRAVITY && _pos > 500) _sp -= 10;
|
if(USE_GRAVITY && _pos > 500) _sp -= 10;
|
||||||
_power = 100 - _life;
|
_power = 100 - _aging*_life;
|
||||||
if(_power <= 0){
|
if(_power <= 0){
|
||||||
Kill();
|
Kill();
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -93,8 +93,13 @@ void Player::Kill(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Player::Spawn(int pos){
|
void Player::Spawn(int pos){
|
||||||
captured = false;
|
if (_lives <= 0) {
|
||||||
moveto(pos);
|
// Serial.printf("Player %d has no life. Not Spawning\n", _id);
|
||||||
|
captured = true;
|
||||||
|
} else {
|
||||||
|
captured = false;
|
||||||
|
moveto(pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Player::Lives() const{
|
int Player::Lives() const{
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "wifi_ap.h"
|
#include "wifi_ap.h"
|
||||||
|
#include "colors.h"
|
||||||
|
|
||||||
#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
|
#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
|
||||||
#error "Requires FastLED 3.1 or later; check github for latest code."
|
#error "Requires FastLED 3.1 or later; check github for latest code."
|
||||||
@@ -89,6 +90,7 @@ int attack_width = DEFAULT_ATTACK_WIDTH;
|
|||||||
#define STARTUP_WIPEUP_DUR 200
|
#define STARTUP_WIPEUP_DUR 200
|
||||||
#define STARTUP_SPARKLE_DUR 1300
|
#define STARTUP_SPARKLE_DUR 1300
|
||||||
#define STARTUP_FADE_DUR 1500
|
#define STARTUP_FADE_DUR 1500
|
||||||
|
#define COLOR_SELECT_DUR 1000
|
||||||
|
|
||||||
#define GAMEOVER_SPREAD_DURATION 1000
|
#define GAMEOVER_SPREAD_DURATION 1000
|
||||||
#define GAMEOVER_FADE_DURATION 1500
|
#define GAMEOVER_FADE_DURATION 1500
|
||||||
@@ -157,6 +159,7 @@ enum stages {
|
|||||||
long stageStartTime; // Stores the time the stage changed for stages that are time based
|
long stageStartTime; // Stores the time the stage changed for stages that are time based
|
||||||
long killTime;
|
long killTime;
|
||||||
bool lastLevel = false;
|
bool lastLevel = false;
|
||||||
|
int killPos = 0;
|
||||||
|
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
@@ -256,8 +259,7 @@ void setup() {
|
|||||||
player[0].setColor(0,255,0);
|
player[0].setColor(0,255,0);
|
||||||
player[1].setColor(127,2,255);
|
player[1].setColor(127,2,255);
|
||||||
for (Player& p : player)
|
for (Player& p : player)
|
||||||
p.Lives ( 2 );
|
p.Lives ( user_settings.lives_per_level );
|
||||||
//p.Lives ( user_settings.lives_per_level );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,10 +271,15 @@ void loop() {
|
|||||||
checkSerialInput();
|
checkSerialInput();
|
||||||
|
|
||||||
if(stage == PLAY){
|
if(stage == PLAY){
|
||||||
if(player[0].attacking){
|
bool attacking = false;
|
||||||
|
for (const Player& p: player) attacking = attacking || p.attacking;
|
||||||
|
|
||||||
|
if(attacking){
|
||||||
SFXattacking();
|
SFXattacking();
|
||||||
}else{
|
}else{
|
||||||
SFXtilt(joystickTilt[0]);
|
int tilt = -1000;
|
||||||
|
for (int i=0; i<NUM_PLAYERS; i++) tilt = max(joystickTilt[i], tilt);
|
||||||
|
SFXtilt(tilt);
|
||||||
}
|
}
|
||||||
}else if(stage == DEAD){
|
}else if(stage == DEAD){
|
||||||
SFXdead();
|
SFXdead();
|
||||||
@@ -284,12 +291,12 @@ void loop() {
|
|||||||
long frameTimer = mm;
|
long frameTimer = mm;
|
||||||
previousMillis = mm;
|
previousMillis = mm;
|
||||||
|
|
||||||
// check activity of any player
|
// check activity of any player, used to stop screensaver
|
||||||
bool isMoving = false;
|
bool isMoving = false;
|
||||||
for (int i=0; i < NUM_PLAYERS; i++) {
|
for (int i=0; i < NUM_PLAYERS; i++) {
|
||||||
isMoving = isMoving &&
|
isMoving = isMoving ||
|
||||||
(abs(joystickTilt[i]) > user_settings.joystick_deadzone) ||
|
((abs(joystickTilt[i]) > user_settings.joystick_deadzone) ||
|
||||||
(abs(joystickWobble[i]) >= user_settings.attack_threshold);
|
(abs(joystickWobble[i]) >= user_settings.attack_threshold));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isMoving)
|
if(isMoving)
|
||||||
@@ -321,7 +328,22 @@ void loop() {
|
|||||||
}else if(stage == PLAY){
|
}else if(stage == PLAY){
|
||||||
// PLAYING
|
// PLAYING
|
||||||
|
|
||||||
|
// allow selecting player color during first sec of first level
|
||||||
|
if (levelNumber == 0) {
|
||||||
|
if ((stageStartTime + COLOR_SELECT_DUR) > mm) {
|
||||||
|
for (Player& p : player) {
|
||||||
|
if (joystickWobble[p.Id()] >= user_settings.attack_threshold) {
|
||||||
|
random_player_color(p);
|
||||||
|
stageStartTime = mm;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// real action here
|
||||||
for (Player& p : player) {
|
for (Player& p : player) {
|
||||||
|
|
||||||
if (p.captured) continue;
|
if (p.captured) continue;
|
||||||
|
|
||||||
if (joystickWobble[p.Id()] >= user_settings.attack_threshold) p.startAttack(mm);
|
if (joystickWobble[p.Id()] >= user_settings.attack_threshold) p.startAttack(mm);
|
||||||
@@ -360,25 +382,26 @@ void loop() {
|
|||||||
|
|
||||||
// Ticks and draw calls
|
// Ticks and draw calls
|
||||||
FastLED.clear();
|
FastLED.clear();
|
||||||
|
|
||||||
|
// exploding players during PLAY stage
|
||||||
|
tickParticles();
|
||||||
|
|
||||||
for (Player& p : player)
|
for (Player& p : player)
|
||||||
tickConveyors(p);
|
tickConveyors(p);
|
||||||
|
|
||||||
tickSpawners();
|
tickSpawners();
|
||||||
tickBoss();
|
tickBoss();
|
||||||
tickLava();
|
tickLava();
|
||||||
for (Player& p : player)
|
|
||||||
if (!p.captured) tickEnemies(p);
|
for (Player& p : player) if (!p.captured) tickEnemies(p);
|
||||||
for (const Player& p : player) {
|
for (const Player& p : player) if (!p.captured) drawAttack(p);
|
||||||
if (p.Alive()) {
|
for (const Player& p : player) if (!p.captured) drawPlayer(p);
|
||||||
drawPlayer(p);
|
|
||||||
drawAttack(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawExit();
|
drawExit();
|
||||||
}else if(stage == DEAD){
|
}else if(stage == DEAD){
|
||||||
// DEAD
|
// DEAD
|
||||||
FastLED.clear();
|
FastLED.clear();
|
||||||
tickDie(player[0], mm); // TODO: fix me! Add whoDied function!
|
tickDie(mm);
|
||||||
if(!tickParticles()){
|
if(!tickParticles()){
|
||||||
loadLevel();
|
loadLevel();
|
||||||
}
|
}
|
||||||
@@ -702,8 +725,7 @@ void nextLevel(){
|
|||||||
for (Player& p : player)
|
for (Player& p : player)
|
||||||
p.Lives ( user_settings.lives_per_level );
|
p.Lives ( user_settings.lives_per_level );
|
||||||
|
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for (Player& p : player) {
|
for (Player& p : player) {
|
||||||
if (!p.Alive()) p.Lives ( user_settings.lives_per_level );
|
if (!p.Alive()) p.Lives ( user_settings.lives_per_level );
|
||||||
}
|
}
|
||||||
@@ -732,6 +754,11 @@ void die(Player& p){
|
|||||||
allDead &= !pp.Alive();
|
allDead &= !pp.Alive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(int ip = 0; ip < PARTICLE_COUNT; ip++){
|
||||||
|
if(stillPlaying>0) particlePool[ip].Spawn(p.position, 25, 3, p.color);
|
||||||
|
else particlePool[ip].Spawn(p.position, 200, 1, p.color); // final explosion
|
||||||
|
}
|
||||||
|
|
||||||
// someone is still playing the level, continue (an animation for the dead player should be added)
|
// someone is still playing the level, continue (an animation for the dead player should be added)
|
||||||
if(stillPlaying>0) return;
|
if(stillPlaying>0) return;
|
||||||
|
|
||||||
@@ -743,13 +770,11 @@ void die(Player& p){
|
|||||||
}
|
}
|
||||||
else // some still have lifes to live, go to DEAD stage and repat the level
|
else // some still have lifes to live, go to DEAD stage and repat the level
|
||||||
{
|
{
|
||||||
for(int ip = 0; ip < PARTICLE_COUNT; ip++){
|
|
||||||
particlePool[ip].Spawn(p.position);
|
|
||||||
}
|
|
||||||
stageStartTime = millis();
|
stageStartTime = millis();
|
||||||
stage = DEAD;
|
stage = DEAD;
|
||||||
}
|
}
|
||||||
killTime = millis();
|
killTime = millis();
|
||||||
|
killPos = p.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
@@ -924,19 +949,24 @@ void tickLava(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool tickParticles(){
|
bool tickParticles(){
|
||||||
|
// TODO: the new version of this function is a bit stupid. Should be rewritten.
|
||||||
bool stillActive = false;
|
bool stillActive = false;
|
||||||
uint8_t brightness;
|
float brightness;
|
||||||
|
uint8_t r, g, b;
|
||||||
|
|
||||||
|
// loop over particles
|
||||||
for(int p = 0; p < PARTICLE_COUNT; p++){
|
for(int p = 0; p < PARTICLE_COUNT; p++){
|
||||||
if(particlePool[p].Alive()){
|
if(particlePool[p].Alive()){
|
||||||
particlePool[p].Tick(USE_GRAVITY);
|
particlePool[p].Tick(USE_GRAVITY);
|
||||||
|
|
||||||
if (particlePool[p]._power < 5)
|
if (particlePool[p]._power < 5) brightness = (float) (5 - particlePool[p]._power) * 10 / 255;
|
||||||
{
|
else brightness = (float) particlePool[p]._power / 255;
|
||||||
brightness = (5 - particlePool[p]._power) * 10;
|
|
||||||
leds[getLED(particlePool[p]._pos)] += CRGB(brightness, brightness/2, brightness/2);\
|
r = (uint8_t) ( particlePool[p]._color[0] * brightness);
|
||||||
}
|
g = (uint8_t) ( particlePool[p]._color[1] * brightness);
|
||||||
else
|
b = (uint8_t) ( particlePool[p]._color[2] * brightness);
|
||||||
leds[getLED(particlePool[p]._pos)] += CRGB(particlePool[p]._power, 0, 0);
|
|
||||||
|
leds[getLED(particlePool[p]._pos)] += CRGB(r, g, b);
|
||||||
|
|
||||||
stillActive = true;
|
stillActive = true;
|
||||||
}
|
}
|
||||||
@@ -1033,7 +1063,7 @@ void tickBossKilled(long mm) // boss funeral
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tickDie(const Player& p, long mm) { // a short bright explosion...particles persist after it.
|
void tickDie(long mm) { // a short bright explosion...particles persist after it.
|
||||||
const int duration = 200; // milliseconds
|
const int duration = 200; // milliseconds
|
||||||
const int width = 20; // half width of the explosion
|
const int width = 20; // half width of the explosion
|
||||||
|
|
||||||
@@ -1042,14 +1072,14 @@ void tickDie(const Player& p, long mm) { // a short bright explosion...particles
|
|||||||
int brightness = map((mm-stageStartTime), 0, duration, 255, 150); // this allows a fade from white to red
|
int brightness = map((mm-stageStartTime), 0, duration, 255, 150); // this allows a fade from white to red
|
||||||
|
|
||||||
// fill up
|
// fill up
|
||||||
int n = _max(map(((mm-stageStartTime)), 0, duration, getLED(p.position), getLED(p.position)+width), 0);
|
int n = _max(map(((mm-stageStartTime)), 0, duration, getLED(killPos), getLED(killPos)+width), 0);
|
||||||
for(int i = getLED(p.position); i<= n; i++){
|
for(int i = getLED(killPos); i<= n; i++){
|
||||||
leds[i] = CRGB(255, brightness, brightness);
|
leds[i] = CRGB(255, brightness, brightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill to down
|
// fill to down
|
||||||
n = _max(map(((mm-stageStartTime)), 0, duration, getLED(p.position), getLED(p.position)-width), 0);
|
n = _max(map(((mm-stageStartTime)), 0, duration, getLED(killPos), getLED(killPos)-width), 0);
|
||||||
for(int i = getLED(p.position); i>= n; i--){
|
for(int i = getLED(killPos); i>= n; i--){
|
||||||
leds[i] = CRGB(255, brightness, brightness);
|
leds[i] = CRGB(255, brightness, brightness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1226,6 +1256,9 @@ void getInput(){
|
|||||||
// if(digitalRead(leftButtonPinNumber) == HIGH) joystickTilt = -90;
|
// if(digitalRead(leftButtonPinNumber) == HIGH) joystickTilt = -90;
|
||||||
// if(digitalRead(rightButtonPinNumber) == HIGH) joystickTilt = 90;
|
// if(digitalRead(rightButtonPinNumber) == HIGH) joystickTilt = 90;
|
||||||
// if(digitalRead(attackButtonPinNumber) == HIGH) joystickWobble = ATTACK_THRESHOLD;
|
// if(digitalRead(attackButtonPinNumber) == HIGH) joystickWobble = ATTACK_THRESHOLD;
|
||||||
|
|
||||||
|
// NB: This is not multiplayer yet
|
||||||
|
|
||||||
int16_t ax, ay, az;
|
int16_t ax, ay, az;
|
||||||
int16_t gx, gy, gz;
|
int16_t gx, gy, gz;
|
||||||
|
|
||||||
@@ -1273,6 +1306,8 @@ void getInput() {
|
|||||||
//bool right = digitalRead(rightButtonPinNumber) == LOW;
|
//bool right = digitalRead(rightButtonPinNumber) == LOW;
|
||||||
bool right = left;
|
bool right = left;
|
||||||
|
|
||||||
|
// Player 1
|
||||||
|
|
||||||
joystickTilt[0] = 0;
|
joystickTilt[0] = 0;
|
||||||
if (up) {
|
if (up) {
|
||||||
joystickTilt[0] = 90 ;
|
joystickTilt[0] = 90 ;
|
||||||
@@ -1287,7 +1322,7 @@ void getInput() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Player 2
|
||||||
|
|
||||||
up = digitalRead(upButtonPinNumber2) == LOW;
|
up = digitalRead(upButtonPinNumber2) == LOW;
|
||||||
down = digitalRead(downButtonPinNumber2) == LOW;
|
down = digitalRead(downButtonPinNumber2) == LOW;
|
||||||
|
|||||||
23
TWANG32/colors.h
Normal file
23
TWANG32/colors.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
void random_player_color(Player& p)
|
||||||
|
{
|
||||||
|
float h = (float)random(0, 100000) / 100000.0;
|
||||||
|
float s = 0.95f; // high saturation
|
||||||
|
float v = 1.0f; // max brightness
|
||||||
|
|
||||||
|
float c = v * s;
|
||||||
|
float x = c * (1 - fabsf(fmodf(h * 6.0f, 2) - 1));
|
||||||
|
float m = v - c;
|
||||||
|
|
||||||
|
float r1=0, g1=0, b1=0;
|
||||||
|
|
||||||
|
if (h < 1.0/6) { r1=c; g1=x; }
|
||||||
|
else if (h < 2.0/6) { r1=x; g1=c; }
|
||||||
|
else if (h < 3.0/6) { g1=c; b1=x; }
|
||||||
|
else if (h < 4.0/6) { g1=x; b1=c; }
|
||||||
|
else if (h < 5.0/6) { r1=x; b1=c; }
|
||||||
|
else { r1=c; b1=x; }
|
||||||
|
|
||||||
|
p.setColor( (unsigned char)((r1 + m) * 255),
|
||||||
|
(unsigned char)((g1 + m) * 255),
|
||||||
|
(unsigned char)((b1 + m) * 255));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user