Compare commits
2 Commits
a11da1b3d8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8c6a01422 | ||
|
|
9bf87677a4 |
@@ -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{
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
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