Compare commits

...

2 Commits

4 changed files with 111 additions and 43 deletions

View File

@@ -4,24 +4,29 @@
class Particle
{
public:
void Spawn(int pos);
void Spawn(int pos, int life, int aging_speed, const int color[3]);
void Tick(int USE_GRAVITY);
void Kill();
bool Alive();
int _pos;
int _power;
int _color[3];
private:
int _life;
int _alive;
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;
_sp = random(-200, 200);
_sp = random(-life, life);
_power = 255;
_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){
@@ -33,7 +38,7 @@ void Particle::Tick(int USE_GRAVITY){
_sp += _life/10;
}
if(USE_GRAVITY && _pos > 500) _sp -= 10;
_power = 100 - _life;
_power = 100 - _aging*_life;
if(_power <= 0){
Kill();
}else{

View File

@@ -93,8 +93,13 @@ void Player::Kill(){
}
void Player::Spawn(int pos){
captured = false;
moveto(pos);
if (_lives <= 0) {
// Serial.printf("Player %d has no life. Not Spawning\n", _id);
captured = true;
} else {
captured = false;
moveto(pos);
}
}
int Player::Lives() const{

View File

@@ -53,6 +53,7 @@
#include "sound.h"
#include "settings.h"
#include "wifi_ap.h"
#include "colors.h"
#if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000)
#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_SPARKLE_DUR 1300
#define STARTUP_FADE_DUR 1500
#define COLOR_SELECT_DUR 1000
#define GAMEOVER_SPREAD_DURATION 1000
#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 killTime;
bool lastLevel = false;
int killPos = 0;
int score = 0;
@@ -256,8 +259,7 @@ void setup() {
player[0].setColor(0,255,0);
player[1].setColor(127,2,255);
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();
if(stage == PLAY){
if(player[0].attacking){
bool attacking = false;
for (const Player& p: player) attacking = attacking || p.attacking;
if(attacking){
SFXattacking();
}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){
SFXdead();
@@ -284,12 +291,12 @@ void loop() {
long frameTimer = mm;
previousMillis = mm;
// check activity of any player
// check activity of any player, used to stop screensaver
bool isMoving = false;
for (int i=0; i < NUM_PLAYERS; i++) {
isMoving = isMoving &&
(abs(joystickTilt[i]) > user_settings.joystick_deadzone) ||
(abs(joystickWobble[i]) >= user_settings.attack_threshold);
isMoving = isMoving ||
((abs(joystickTilt[i]) > user_settings.joystick_deadzone) ||
(abs(joystickWobble[i]) >= user_settings.attack_threshold));
}
if(isMoving)
@@ -321,7 +328,22 @@ void loop() {
}else if(stage == PLAY){
// 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) {
if (p.captured) continue;
if (joystickWobble[p.Id()] >= user_settings.attack_threshold) p.startAttack(mm);
@@ -360,25 +382,26 @@ void loop() {
// Ticks and draw calls
FastLED.clear();
// exploding players during PLAY stage
tickParticles();
for (Player& p : player)
tickConveyors(p);
tickSpawners();
tickBoss();
tickLava();
for (Player& p : player)
if (!p.captured) tickEnemies(p);
for (const Player& p : player) {
if (p.Alive()) {
drawPlayer(p);
drawAttack(p);
}
}
for (Player& p : player) if (!p.captured) tickEnemies(p);
for (const Player& p : player) if (!p.captured) drawAttack(p);
for (const Player& p : player) if (!p.captured) drawPlayer(p);
drawExit();
}else if(stage == DEAD){
// DEAD
FastLED.clear();
tickDie(player[0], mm); // TODO: fix me! Add whoDied function!
tickDie(mm);
if(!tickParticles()){
loadLevel();
}
@@ -702,8 +725,7 @@ void nextLevel(){
for (Player& p : player)
p.Lives ( user_settings.lives_per_level );
}
else {
} else {
for (Player& p : player) {
if (!p.Alive()) p.Lives ( user_settings.lives_per_level );
}
@@ -732,6 +754,11 @@ void die(Player& p){
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)
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
{
for(int ip = 0; ip < PARTICLE_COUNT; ip++){
particlePool[ip].Spawn(p.position);
}
stageStartTime = millis();
stage = DEAD;
}
killTime = millis();
killPos = p.position;
}
// ----------------------------------
@@ -924,19 +949,24 @@ void tickLava(){
}
bool tickParticles(){
// TODO: the new version of this function is a bit stupid. Should be rewritten.
bool stillActive = false;
uint8_t brightness;
float brightness;
uint8_t r, g, b;
// loop over particles
for(int p = 0; p < PARTICLE_COUNT; p++){
if(particlePool[p].Alive()){
particlePool[p].Tick(USE_GRAVITY);
if (particlePool[p]._power < 5)
{
brightness = (5 - particlePool[p]._power) * 10;
leds[getLED(particlePool[p]._pos)] += CRGB(brightness, brightness/2, brightness/2);\
}
else
leds[getLED(particlePool[p]._pos)] += CRGB(particlePool[p]._power, 0, 0);
if (particlePool[p]._power < 5) brightness = (float) (5 - particlePool[p]._power) * 10 / 255;
else brightness = (float) particlePool[p]._power / 255;
r = (uint8_t) ( particlePool[p]._color[0] * brightness);
g = (uint8_t) ( particlePool[p]._color[1] * brightness);
b = (uint8_t) ( particlePool[p]._color[2] * brightness);
leds[getLED(particlePool[p]._pos)] += CRGB(r, g, b);
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 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
// fill up
int n = _max(map(((mm-stageStartTime)), 0, duration, getLED(p.position), getLED(p.position)+width), 0);
for(int i = getLED(p.position); i<= n; i++){
int n = _max(map(((mm-stageStartTime)), 0, duration, getLED(killPos), getLED(killPos)+width), 0);
for(int i = getLED(killPos); i<= n; i++){
leds[i] = CRGB(255, brightness, brightness);
}
// fill to down
n = _max(map(((mm-stageStartTime)), 0, duration, getLED(p.position), getLED(p.position)-width), 0);
for(int i = getLED(p.position); i>= n; i--){
n = _max(map(((mm-stageStartTime)), 0, duration, getLED(killPos), getLED(killPos)-width), 0);
for(int i = getLED(killPos); i>= n; i--){
leds[i] = CRGB(255, brightness, brightness);
}
}
@@ -1226,6 +1256,9 @@ void getInput(){
// if(digitalRead(leftButtonPinNumber) == HIGH) joystickTilt = -90;
// if(digitalRead(rightButtonPinNumber) == HIGH) joystickTilt = 90;
// if(digitalRead(attackButtonPinNumber) == HIGH) joystickWobble = ATTACK_THRESHOLD;
// NB: This is not multiplayer yet
int16_t ax, ay, az;
int16_t gx, gy, gz;
@@ -1273,6 +1306,8 @@ void getInput() {
//bool right = digitalRead(rightButtonPinNumber) == LOW;
bool right = left;
// Player 1
joystickTilt[0] = 0;
if (up) {
joystickTilt[0] = 90 ;
@@ -1287,7 +1322,7 @@ void getInput() {
}
// Player 2
up = digitalRead(upButtonPinNumber2) == LOW;
down = digitalRead(downButtonPinNumber2) == LOW;

23
TWANG32/colors.h Normal file
View 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));
}