#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include "Color.h"
#include "Position.h"
#include "Lightcore.h"
#include "Wall.h"
#include "Player.h"
#ifndef PSTR
#define PSTR // Make Arduino Due happy
#endif
// INPUT: arcade-button data pins
#define SPECIALA 4 // Special Button A (Up)
#define SPECIALB 3 // Special Button B (Mid)
#define SPECIALC 2 // Special Button C (Down)
// INPUT: arcade-button data pins
#define SWITCH1 14 // switch/select (player 1)
#define CHECK1 15 // check/confirm (player 1)
#define YELLOW1 16 // yellow (player 1)
#define ROSE1 17 // rose (player 1)
#define GREEN1 18 // green (player 1)
#define SWITCH2 8 // switch/select (player 2)
#define CHECK2 9 // check/confirm (player 2)
#define YELLOW2 10 // yellow (player 2)
#define ROSE2 11 // rose (player 2)
#define GREEN2 12 // green (player 2)
// OUTPUT: led-matrix data pins, size and number
#define PIN1LED 5 // led-matrix bottom
#define PIN2LED 6 // led-matrix middle
#define PIN3LED 7 // led-matrix top
#define MATRIX_H 8 // height of single matrix layer
#define MATRIX_W 32 // width of single matrix layer
#define MATRIX_NUM 3 // number of led-matrix layers
Adafruit_NeoMatrix matrices[] = {
Adafruit_NeoMatrix(MATRIX_W, MATRIX_H, PIN1LED,
NEO_MATRIX_RIGHT + NEO_MATRIX_RIGHT +
NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800),
Adafruit_NeoMatrix(MATRIX_W, MATRIX_H, PIN2LED,
NEO_MATRIX_RIGHT + NEO_MATRIX_RIGHT +
NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800),
Adafruit_NeoMatrix(MATRIX_W, MATRIX_H, PIN3LED,
NEO_MATRIX_RIGHT + NEO_MATRIX_RIGHT +
NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800)
};
const bool ledMatrixOn = true;
bool activeInput = true;
// Input
bool pressedS[2] = {false, false};
bool pressedC[2] = {false, false};
bool pressedY[2] = {false, false};
bool pressedR[2] = {false, false};
bool pressedG[2] = {false, false};
// State 0: player1, State 1: player2, State 2: both
int playerStateId;
int gameState = 0;
int animationSpeed = 1;
// rgb-values for game colors (0: rose, 1 :green, 2: yellow)
const Color colors[5] = {Color(230, 0, 116), Color(82, 204, 200), Color(250, 230, 142), Color(0, 0, 0), Color(255, 255, 255)};
// define zero and full matrix-color values for quick access (matrices[0].Color(0, 0, 0))
const uint16_t matrixBlack = colors[3].forMatrix(matrices[0]);
const uint16_t matrixWhite = colors[4].forMatrix(matrices[0]);
// Lightcore
const uint8_t colorChangeStep = 25;
// current matrix-layer (0, 1 or 2)
int currentLayer = 1;
int activeLayer[2] = {1, 1};
int currentPlayerAnimCount[2] = {0, 0};
int currentPlayerAnimOffset[2] = {0, 0};
// current wall id to draw
int wallId = 0;
// Pixel-Offset from the left side of the matrix to the first placeable wall
const int viewOffsetX = 5;
// 2* - - - - - - - - - - - - - - - - (16)
// 2* - - - - - - - ● ● - - - - - - - (16)
// 2* - - - | | | ● ● ● ● | | | - - - (16)
// 2* - - - | | | ● ● ● ● | | | - - - (16)
// 2* - - - - - - - ● ● - - - - - - - (16)
// 2* - - - - - - - - - - - - - - - - (16)
Player players[2] = {
Player(
Lightcore(colors[4], 1, Position(viewOffsetX + 2, viewOffsetX + 3, MATRIX_H/2 - 1)),
Wall(colors[4], 1, Position(viewOffsetX, viewOffsetX + 5, 1), false),
Wall(colors[4], 1, Position(viewOffsetX - 1, viewOffsetX + 6, 1), false),
Wall(colors[4], 1, Position(viewOffsetX - 2, viewOffsetX + 7, 1), false)
),
Player(
Lightcore(colors[4], 1, Position(MATRIX_W/2 + viewOffsetX + 2, MATRIX_W/2 + viewOffsetX + 3, MATRIX_H/2 - 1)),
Wall(colors[4], 1, Position(MATRIX_W/2 + viewOffsetX, MATRIX_W/2 + viewOffsetX + 5, 1), false),
Wall(colors[4], 1, Position(MATRIX_W/2 + viewOffsetX - 1, MATRIX_W/2 + viewOffsetX + 6, 1), false),
Wall(colors[4], 1, Position(MATRIX_W/2 + viewOffsetX - 2, MATRIX_W/2 + viewOffsetX + 7, 1), false)
)
};
// Fight
Color attackColor = colors[4];
// attack (animation) position (updated in game)
int attackPosY = 0;
Position attackAnimPos(0, 0, MATRIX_W/2 - 1);
int currentAttackAnimAddY = 0; // attack animation Y: move up/down
int prevAttackAnimAddY = 1; // last move down (+1), start with up (-1)
int attackPlayer = 0;
int otherPlayer = attackPlayer == 0 ? 1 : 0;
// conter at same color (attack & defense)
bool isConter = false;
int conterCounter = 3;
// use only one gamepad mode
bool oneGamepadMode = false;
void setup() {
Serial.begin(9600);
Serial.println("SETUP");
// put your setup code here, to run once:
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].begin();
// max brigthness 255 only for simulator, else near 10
matrices[matrixId].setBrightness(255);
}
pinMode(SPECIALA, INPUT_PULLUP);
pinMode(SPECIALB, INPUT_PULLUP);
pinMode(SPECIALC, INPUT_PULLUP);
pinMode(13, OUTPUT);
// buttons player 1
pinMode(SWITCH1, INPUT_PULLUP);
pinMode(CHECK1, INPUT_PULLUP);
pinMode(YELLOW1, INPUT_PULLUP);
pinMode(ROSE1, INPUT_PULLUP);
pinMode(GREEN1, INPUT_PULLUP);
// buttons player 2
pinMode(SWITCH2, INPUT_PULLUP);
pinMode(CHECK2, INPUT_PULLUP);
pinMode(YELLOW2, INPUT_PULLUP);
pinMode(ROSE2, INPUT_PULLUP);
pinMode(GREEN2, INPUT_PULLUP);
// set player state to both
if (!oneGamepadMode) playerStateId = 2;
if (oneGamepadMode) playerStateId = 0;
}
int animMoveX = 0;
int animMoveXPos = 0;
// MAIN Game Loop
void loop() {
if (!ledMatrixOn) {
clearScreen();
}
else {
// turn on test led on arduino on button pressed
if (digitalRead(SPECIALA) == HIGH) {
digitalWrite(13, LOW);
} else {
// reset game
resetWin();
Serial.println("A");
digitalWrite(13, HIGH);
}
if (digitalRead(SPECIALB) == HIGH) {
digitalWrite(13, LOW);
} else {
randomGame();
Serial.println("B");
digitalWrite(13, HIGH);
}
if (digitalRead(SPECIALC) == HIGH) {
digitalWrite(13, LOW);
} else {
// toggle one gamepad mode in title screen
if (gameState == 0) oneGamepadMode = !oneGamepadMode;
if (!oneGamepadMode) Serial.println("TWO Gamepad Mode");
if (oneGamepadMode) Serial.println("ONE Gamepad Mode");
Serial.println("C");
digitalWrite(13, HIGH);
}
// Controller
inputController();
// Model
inputToAction();
// View
updateLights();
}
delay(100 * animationSpeed);
}
void clearScreen() {
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
matrices[matrixId].show();
}
}
void resetButtons() {
// buttons player 1
digitalWrite(SWITCH1, LOW);
digitalWrite(CHECK1, LOW);
digitalWrite(ROSE1, LOW);
digitalWrite(GREEN1, LOW);
digitalWrite(YELLOW1, LOW);
// buttons player 2
digitalWrite(SWITCH2, LOW);
digitalWrite(CHECK2, LOW);
digitalWrite(ROSE2, LOW);
digitalWrite(GREEN2, LOW);
digitalWrite(YELLOW2, LOW);
for (int i = 0; i < 2; i++) {
pressedS[i] = false;
pressedC[i] = false;
pressedR[i] = false;
pressedG[i] = false;
pressedY[i] = false;
}
}
void inputController() {
resetButtons();
// playerState == 2 -> two player input at the same time
if (activeInput) {
if (playerStateId == 0 || playerStateId == 2) {
if (digitalRead(SWITCH1) == HIGH) pressedS[0] = true;
if (digitalRead(CHECK1) == HIGH) pressedC[0] = true;
if (digitalRead(ROSE1) == HIGH) pressedR[0] = true;
if (digitalRead(GREEN1) == HIGH) pressedG[0] = true;
if (digitalRead(YELLOW1) == HIGH) pressedY[0] = true;
}
if (playerStateId == 1 || playerStateId == 2) {
if (digitalRead(SWITCH2) == HIGH) pressedS[1] = true;
if (digitalRead(CHECK2) == HIGH) pressedC[1] = true;
if (digitalRead(ROSE2) == HIGH) pressedR[1] = true;
if (digitalRead(GREEN2) == HIGH) pressedG[1] = true;
if (digitalRead(YELLOW2) == HIGH) pressedY[1] = true;
}
}
}
void inputToAction() {
// Layer Switch/Select Button Action (for current single player or both)
if (playerStateId != 2) {
if (pressedS[playerStateId] && gameState < 4) {
if (currentLayer >= MATRIX_NUM - 1) {
currentLayer = 0;
} else {
currentLayer++;
}
// reset animation
animMoveX = 0;
}
}
else {
for (int playerId = 0; playerId < 2; playerId++) {
if (pressedS[playerId] && gameState < 4) {
if (activeLayer[playerId] >= MATRIX_NUM - 1) {
activeLayer[playerId] = 0;
} else {
activeLayer[playerId]++;
}
}
}
}
switch (gameState) {
case 0:
// TITLE: Game Start at Button Pressed
startGameRound();
break;
case 1:
// BUILD: Change Core Position (Layer) with Select-Button and change Color with Color-Buttons
placeBase();
break;
case 2:
// FIGHT
selectAttackLayer();
break;
case 3:
attackOnLayer();
break;
case 4:
// WIN
if (pressedC[0] || pressedC[1]) {
gameState = 5;
}
break;
case 5:
// RESET
// delay(500);
resetWin();
break;
}
}
// build up random lightcore & wall setup.
// At the end of building skip to fight game phase
void randomGame() {
// deactivate input for ramdom game creation
activeInput = false;
// create random data & update screen
clearScreen();
gameState = 1;
// reset core (not placed)
if (!oneGamepadMode) {
players[0].core.isPlaced = false;
players[1].core.isPlaced = false;
}
for (int i = 0; i < 2; i++) {
players[i].core.color = Color(random(30, 256), random(30, 256), random(30, 256));
players[i].core.layer = random(0, 3);
// set layer and current playerId to draw the core at random layer
activeLayer[i] = players[i].core.layer;
if (oneGamepadMode) currentLayer = players[i].core.layer;
if (oneGamepadMode) updateLights();
}
if (!oneGamepadMode) updateLights();
delay(180);
for (int i = 0; i < 2; i++) {
players[i].core.isPlaced = true;
// permutation: fisher-yates-shuffle to create random color order
int colorOrder[3] = {0, 1, 2};
for (int i = 2; i > 0; i--) {
int j = random(0, i + 1);
int temp = colorOrder[i];
colorOrder[i] = colorOrder[j];
colorOrder[j] = temp;
}
for (int w = 0; w < 3; w++) {
int wallColorid = colorOrder[w];
players[i].setWallColor(w, colors[wallColorid]);
players[i].setWallLayer(w, random(0, 3));
players[i].placeWall(w);
delay(120);
activeLayer[i] = players[i].getWall(w).layer;
players[i].placedWalls = w;
updateLights();
}
delay(20);
}
// reset game parameters & skip to fight
attackColor = colors[4];
currentLayer = 1;
playerStateId = 0;
gameState = 2;
activeInput = true;
}
void redrawBuild() {
clearScreen();
gameState = 1;
for (int i = 0; i < 2; i++) {
players[i].core.isPlaced = false;
playerStateId = i;
currentLayer = players[i].core.layer;
updateLights();
}
for (int i = 0; i < 2; i++) {
players[i].core.isPlaced = true;
playerStateId = i;
for (int w = 0; w < 3; w++) {
currentLayer = players[i].getWall(w).layer;
players[i].placedWalls = w;
updateLights();
}
}
// reset game parameters
attackColor = colors[4];
currentLayer = 1;
playerStateId = 0;
}
// RESET game
void resetWin() {
currentLayer = 1;
playerStateId = 2; // both players
animationSpeed = 1;
activeInput = false;
attackColor = colors[4];
wallId = 0;
// reset lightcore & walls
for (int id = 0; id < 2; id++) {
players[id].core.color = colors[4];
players[id].core.layer = 1;
players[id].setWallColor(0, colors[4]);
players[id].setWallColor(1, colors[4]);
players[id].setWallColor(2, colors[4]);
players[id].placedWalls = 0;
players[id].wallColorPlaced = {false, false, false};
}
// reset fight values
isConter = false;
conterCounter = 3;
// reset matrix pixels
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
matrices[matrixId].show();
}
delay(100);
activeInput = true;
gameState = 0;
Serial.println("*** RESTART Game ***");
}
void startGameRound() {
// start game round
if (pressedC[0] || pressedC[1]) {
Serial.println("START GAME");
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].setTextSize(1);
}
// drawTextIntro("textOnLayers", 800);
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
}
matrices[0].setTextColor(matrices[0].Color(255, 255, 255));
matrices[0].setCursor(1, 0);
matrices[0].print(F("-----"));
matrices[0].show();
matrices[1].setTextColor(matrices[1].Color(255, 255, 255));
matrices[1].setCursor(1, 0);
matrices[1].print(F("BUILD"));
matrices[1].show();
matrices[2].setTextColor(matrices[2].Color(255, 255, 255));
matrices[2].setCursor(1, 0);
matrices[2].print(F("------"));
matrices[2].show();
delay(700);
/*
Serial.println("3 Layer");
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
}
// --- intro Animation ---
activeInput = false;
matrices[0].setTextColor(matrices[0].Color(colors[3].red, colors[3].green, colors[3].blue));
matrices[0].setCursor(MATRIX_W/2 - 2, 0);
matrices[0].print(F("3"));
matrices[0].show();
matrices[1].setTextColor(matrices[0].Color(colors[0].red, colors[0].green, colors[0].blue));
matrices[1].setCursor(1, 0);
matrices[1].print(F("Layer"));
matrices[1].show();
delay(1500);
Serial.println("2 Player");
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
}
matrices[0].setTextColor(matrices[0].Color(colors[3].red, colors[3].green, colors[3].blue));
matrices[0].setCursor(MATRIX_W/2 - 2, 0);
matrices[0].print(F("2"));
matrices[0].show();
matrices[1].setTextColor(matrices[1].Color(colors[1].red, colors[1].green, colors[1].blue));
matrices[1].setCursor(1, 0);
matrices[1].print(F("Player"));
matrices[1].show();
delay(1500);
Serial.println("1 Light");
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
}
matrices[0].setTextColor(matrices[0].Color(colors[3].red, colors[3].green, colors[3].blue));
matrices[0].setCursor(MATRIX_W/2 - 2, 0);
matrices[0].print(F("1"));
matrices[0].show();
matrices[1].setTextColor(matrices[1].Color(colors[2].red, colors[2].green, colors[2].blue));
matrices[1].setCursor(1, 0);
matrices[1].print(F("Light"));
matrices[1].show();
delay(1500);
Serial.println("Let's Fight");
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
}
matrices[0].setTextColor(matrices[0].Color(colors[2].red, colors[2].green, colors[2].blue));
matrices[0].setCursor(1, 0);
matrices[0].print(F("LET'S"));
matrices[0].show();
matrices[1].setTextColor(matrices[1].Color(colors[0].red, colors[0].green, colors[0].blue));
matrices[1].setCursor(1, 0);
matrices[1].print(F("Fight"));
matrices[1].show();
delay(3000);
*/
Serial.println("--------------- And the game begins ---------------");
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
matrices[matrixId].show();
}
activeInput = true;
currentLayer = 1;
inputController();
// coreBlinkFeedback();
gameState++;
}
}
void drawTextIntro(String text, int showTime) {
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
}
activeInput = false;
// --- draw text ---
String textT = "1 1 1 1 1 1 1 1 1 1";
matrices[0].setTextColor(matrices[0].Color(255, 255, 255));
matrices[0].setCursor(1, 0);
matrices[0].print(F("1"));
matrices[0].show();
/*
matrices[1].setTextColor(matrices[0].Color(textColors[1].red, textColors[1].green, textColors[1].blue));
matrices[1].setCursor(1, 0);
matrices[1].print(text);
matrices[1].show();
matrices[2].setTextColor(matrices[0].Color(textColors[2].red, textColors[2].green, textColors[2].blue));
matrices[2].setCursor(1, 0);
matrices[2].print(text);
matrices[2].show();
*/
delay(showTime);
activeInput = true;
}
bool inRange(int val, int minimum, int maximum) {
return ((minimum <= val) && (val <= maximum));
}
void coreBlinkFeedback() {
// reset current layer after player change (anti-cheat)
currentLayer = 1;
// get current player lightcore data
int corePosXl = players[playerStateId].core.pos.xl;
int corePosY = players[playerStateId].core.pos.y;
int coreLayer = players[playerStateId].core.layer;
Color coreColor = players[playerStateId].core.color;
currentPlayerAnimOffset[0] = 0;
currentPlayerAnimOffset[1] = 0;
currentPlayerAnimCount[0] = 0;
currentPlayerAnimCount[1] = 0;
if (gameState == 0) {
matrices[currentLayer].drawRoundRect(corePosXl - 1, corePosY - 1, 4, 4, 1, matrices[currentLayer].Color(coreColor.red, coreColor.green, coreColor.blue));
matrices[currentLayer].show();
}
// reset up and down lines of current player indicator
matrices[0].drawLine(0, 0, MATRIX_W - 1, 0, matrixBlack);
matrices[2].drawLine(0, MATRIX_H - 1, MATRIX_W - 1, MATRIX_H - 1, matrixBlack);
// blink animation
int repetition = 3;
for (int num = 0; num < repetition; num++) {
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].drawRoundRect(corePosXl, corePosY, 2, 2, 0, matrixBlack);
matrices[matrixId].show();
}
delay(225 * 0.4);
matrices[coreLayer].drawRoundRect(corePosXl, corePosY, 2, 2, 0, matrices[coreLayer].Color(coreColor.red, coreColor.green, coreColor.blue));
matrices[coreLayer].show();
delay(300 * 0.4);
}
}
// function to convert custom Color struct to NeoPixel Color
void placeBase() {
if (!oneGamepadMode) {
for (int playerId = 0; playerId < 2; playerId++) {
if (!players[playerId].core.isPlaced) {
placeLightCore(playerId);
}
else {
placeDefenseWall(playerId);
}
}
}
else {
// start: player 1, next: player 2
if (players[0].placedWalls >= 3) {
playerStateId = 1;
}
if (!players[playerStateId].core.isPlaced) {
placeLightCore(playerStateId);
}
else {
placeDefenseWall(playerStateId);
}
}
// All Walls (player 1 and 2) placed? Go to Fight
if(players[0].placedWalls >= 3 && players[1].placedWalls >= 3) {
// finished - go to next game state
Serial.println("next game state");
updateLights();
playerStateId = 0;
/*
// go to FIGHT phase
delay(200);
clearScreen();
matrices[0].setTextColor(matrices[0].Color(255, 255, 255));
matrices[0].setCursor(1, 0);
matrices[0].print(F("-----"));
matrices[0].show();
matrices[1].setTextColor(matrices[1].Color(255, 255, 255));
matrices[1].setCursor(1, 0);
matrices[1].print(F("FIGHT"));
matrices[1].show();
matrices[2].setTextColor(matrices[2].Color(255, 255, 255));
matrices[2].setCursor(1, 0);
matrices[2].print(F("------"));
matrices[2].show();
delay(1400);
redrawBuild();
*/
coreBlinkFeedback();
// finished placement - go to fight
gameState++;
// prevent matrixBlack attack draw overwrite for first attack
attackPosY = currentLayer;
attackColor = colors[4];
updateLights();
}
}
// -------------- Gameplay --------------
void placeLightCore(int playerId) {
// overwrite core on layer, when deactivated (no light)
if (players[playerId].core.layer != activeLayer[playerId]) {
matrices[players[playerId].core.layer].drawRoundRect(
players[playerId].core.pos.xr - 1, MATRIX_H/2 - 1, 2, 2, 0, matrixBlack
);
matrices[players[playerId].core.layer].drawRoundRect(
players[playerId].core.pos.xr - 2, MATRIX_H/2 - 2, 4, 4, 1, matrixBlack
);
}
// update current core layer
if (pressedS[playerId]) {
players[playerId].core.layer = activeLayer[playerId];
}
// Change Color Value of Core
if (pressedR[playerId]) {
// Rose Button
players[playerId].core.color.red += colorChangeStep;
players[playerId].core.color.green -= colorChangeStep;
players[playerId].core.color.blue -= colorChangeStep;
}
else if (pressedG[playerId]) {
// Green Button
players[playerId].core.color.red -= colorChangeStep;
players[playerId].core.color.green += colorChangeStep;
players[playerId].core.color.blue += colorChangeStep;
}
else if (pressedY[playerId]) {
// Yellow Button
players[playerId].core.color.red += colorChangeStep;
players[playerId].core.color.green += colorChangeStep;
players[playerId].core.color.blue -= colorChangeStep;
}
// reset colors, if not in range
if (!inRange(int(players[playerId].core.color.red - colorChangeStep), 0, 255)) players[playerId].core.color.red = 255;
if (!inRange(int(players[playerId].core.color.green - colorChangeStep), 0, 255)) players[playerId].core.color.green = 255;
if (!inRange(int(players[playerId].core.color.blue - colorChangeStep), 0, 255)) players[playerId].core.color.blue = 255;
if (pressedC[playerId]) {
if (!players[playerId].core.isPlaced) {
players[playerId].core.isPlaced = true;
}
}
}
void placeDefenseWall(int playerId) {
// set current wall number
wallId = players[playerId].placedWalls;
// get players current wall
Wall playerWall = players[playerId].getWall(wallId);
// overwrite last layer wall draw (from layer selection)
if (playerWall.layer != activeLayer[playerId]) {
matrices[playerWall.layer].drawLine(playerWall.pos.xl, playerWall.pos.y, playerWall.pos.xl, playerWall.pos.y + 5, matrixBlack);
matrices[playerWall.layer].drawLine(playerWall.pos.xr, playerWall.pos.y, playerWall.pos.xr, playerWall.pos.y + 5, matrixBlack);
}
if (pressedR[playerId]) {
// Rose Button
// *************
if (players[playerId].placedWalls < 3 && !players[playerId].wallColorPlaced.rose) {
players[playerId].setWallColor(wallId, colors[0]);
}
}
else if (pressedG[playerId]) {
// Green Button
// *************
if (players[playerId].placedWalls < 3 && !players[playerId].wallColorPlaced.green) {
players[playerId].setWallColor(wallId, colors[1]);
}
}
else if (pressedY[playerId]) {
// Yellow Button
// *************
if (players[playerId].placedWalls < 3 && !players[playerId].wallColorPlaced.yellow) {
players[playerId].setWallColor(wallId, colors[2]);
}
}
if (pressedC[playerId]) {
// Check/Confirm Button
// *************
updateLights();
players[playerId].placeWall(wallId);
}
}
void selectAttackLayer() {
if (attackPosY != currentLayer) {
const Position attackStartPos = players[playerStateId].getAttackStartPos();
// delete select attack placeholder
matrices[attackPosY].drawLine(attackStartPos.xl, attackStartPos.y, attackStartPos.xl, attackStartPos.y + 1, matrixBlack);
matrices[attackPosY].drawLine(attackStartPos.xr, attackStartPos.y, attackStartPos.xr, attackStartPos.y + 1, matrixBlack);
}
// Animations -----------------------------------
if (currentLayer == 0) {
// delete last select animation after layer switch (first layer)
// matrices[MATRIX_NUM - 1].drawLine(0, 0, MATRIX_W - 1, 0, matrixBlack);
// matrices[MATRIX_NUM - 1].drawLine(0, MATRIX_H - 1, MATRIX_W - 1, MATRIX_H - 1, matrixBlack);
// matrices[MATRIX_NUM - 1].drawLine(attackStartPosX[playerStateId][0], MATRIX_H/2 - 1, attackStartPosX[playerStateId][0], MATRIX_H/2, matrixBlack);
// matrices[MATRIX_NUM - 1].drawLine(attackStartPosX[playerStateId][1], MATRIX_H/2 - 1, attackStartPosX[playerStateId][1], MATRIX_H/2, matrixBlack);
} else {
// delete last select animation after layer switch
// matrices[currentLayer - 1].drawLine(0, 0, MATRIX_W - 1, 0, matrixBlack);
// matrices[currentLayer - 1].drawLine(0, MATRIX_H - 1, MATRIX_W - 1, MATRIX_H - 1, matrixBlack);
}
// int length = MATRIX_W * 0.4;
// if (animMoveXPos - length + 1 > MATRIX_W) {
// animMoveXPos = 0;
// }
// if (animMoveX + 1 > MATRIX_W) {
// animMoveX = 0;
// }
// delete old pixels
// if (animMoveXPos - length >= 0) {
// matrices[currentLayer].drawPixel(animMoveXPos - length, 0, matrixBlack);
// matrices[currentLayer].drawPixel(animMoveXPos - length, MATRIX_H - 1, matrixBlack);
// } else {
// matrices[currentLayer].drawPixel(MATRIX_W + length, 0, matrixBlack);
// matrices[currentLayer].drawPixel(MATRIX_W + length, MATRIX_H - 1, matrixBlack);
// }
// if (animMoveX - length >= 0) {
// matrices[currentLayer].drawPixel(animMoveX - length, 0, matrixBlack);
// matrices[currentLayer].drawPixel(animMoveX - length, MATRIX_H - 1, matrixBlack);
// } else {
// matrices[currentLayer].drawPixel(MATRIX_W + length, 0, matrixBlack);
// matrices[currentLayer].drawPixel(MATRIX_W + length, MATRIX_H - 1, matrixBlack);
// }
// animMoveX++;
// animMoveXPos++;
// Animations -----------------------------------
if (pressedR[playerStateId]) {
attackColor = colors[0];
}
else if (pressedG[playerStateId]) {
attackColor = colors[1];
}
else if (pressedY[playerStateId]) {
attackColor = colors[2];
}
if (pressedC[playerStateId]) {
// Check/Confirm Button
// *************
if (attackColor.red != 255 && attackColor.green != 255 && attackColor.blue != 255) {
// attack, if color is not white (color is set)
updateLights();
resetAttackPos(playerStateId);
// deactivate input for attack animation
activeInput = false;
gameState++;
}
}
}
// reset attack animation position to prevent pos change bug
void resetAttackPos(int attackPlayer) {
const Position attackStartPos = players[attackPlayer].getAttackStartPos();
attackAnimPos = attackStartPos;
}
// return true, if two colors are the same
bool compareColor(Color a, Color b) {
return (a.red == b.red) && (a.green == b.green) && (a.blue == b.blue);
}
// return stronger color (if attack and attacked color are not the same)
// colors (0: rose, 1 :green, 2: yellow)
bool strongerColor(Color attackColor, Color b) {
bool attackColorIsStronger = false;
if (compareColor(attackColor, colors[0])) {
// attack color is rose (green is weaker, yellow is stronger)
if (compareColor(b, colors[1])) {
attackColorIsStronger = true;
}
else if (compareColor(b, colors[2])) {
attackColorIsStronger = false;
}
}
else if (compareColor(attackColor, colors[1])) {
// attack color is green (yellow is weaker, rose is stronger)
if (compareColor(b, colors[2])) {
attackColorIsStronger = true;
}
else if (compareColor(b, colors[0])) {
attackColorIsStronger = false;
}
}
else if (compareColor(attackColor, colors[2])) {
// attack color is yellow (rose is weaker, green is stronger)
if (compareColor(b, colors[0])) {
attackColorIsStronger = true;
}
else if (compareColor(b, colors[1])) {
attackColorIsStronger = false;
}
}
return attackColorIsStronger;
}
int toggleAttackAnimY(int current, int previous) {
if (current == 1) {
current = 0;
} else if (current == 0 && previous == 1) {
current = -1;
} else if (current == -1) {
current = 0;
} else if (current == 0 && previous == -1) {
current = 1;
} else {
current = 1;
}
return current;
}
void attackOnLayer() {
bool gameStateBack = false;
// inversed attack, conter
if (isConter && conterCounter > 0) {
attackPlayer = playerStateId == 0 ? 1 : 0;
otherPlayer = attackPlayer == 0 ? 1 : 0;
}
else if (conterCounter <= 0) {
// reset conter
isConter = false;
conterCounter = 0;
// enough conter, next game state
gameStateBack = true;
}
else {
// no conter
attackPlayer = playerStateId == 0 ? 0 : 1;
otherPlayer = attackPlayer == 0 ? 1 : 0;
}
if (!gameStateBack) {
// attack animation
if (attackAnimPos.xl - 1 < 0) {
attackAnimPos.xl = MATRIX_W - 1;
}
else {
attackAnimPos.xl--;
}
if (attackAnimPos.xr + 1 >= MATRIX_W) {
attackAnimPos.xr = 0;
}
else {
attackAnimPos.xr++;
}
// update attack animation Y add number: move up/down
int nextAttackAnimAddY = toggleAttackAnimY(currentAttackAnimAddY, prevAttackAnimAddY);
prevAttackAnimAddY = currentAttackAnimAddY;
currentAttackAnimAddY = nextAttackAnimAddY;
attackAnimPos.y = (MATRIX_H/2 - 1) + currentAttackAnimAddY;
// draw attack
matrices[currentLayer].drawLine(attackAnimPos.xl, attackAnimPos.y, attackAnimPos.xl, attackAnimPos.y + 1, matrices[currentLayer].Color(attackColor.red, attackColor.green, attackColor.blue));
matrices[currentLayer].drawLine(attackAnimPos.xr, attackAnimPos.y, attackAnimPos.xr, attackAnimPos.y + 1, matrices[currentLayer].Color(attackColor.red, attackColor.green, attackColor.blue));
// delete old attack line
if (attackAnimPos.xl + 1 >= MATRIX_W) {
matrices[attackPosY].drawLine(0, MATRIX_H/2 - 2, 0, MATRIX_H/2 + 1, matrixBlack);
}
else {
matrices[attackPosY].drawLine(attackAnimPos.xl + 1, MATRIX_H/2 - 2, attackAnimPos.xl + 1, MATRIX_H/2 + 1, matrixBlack);
}
if (attackAnimPos.xr - 1 < 0) {
matrices[attackPosY].drawLine(MATRIX_W - 1, MATRIX_H/2 - 2, MATRIX_W - 1, MATRIX_H/2 + 1, matrixBlack);
}
else {
matrices[attackPosY].drawLine(attackAnimPos.xr - 1, MATRIX_H/2 - 2, attackAnimPos.xr - 1, MATRIX_H/2 + 1, matrixBlack);
}
matrices[currentLayer].show();
// compare for collision test, loop all walls from other player (opponent)
bool wallHitted = false;
for (int wall = 0; wall < 3; wall++) {
if (players[otherPlayer].getWall(wall).layer == currentLayer) {
// check if wall overlaps and still exists (only test x right position)
if (attackAnimPos.xl == players[otherPlayer].getWall(wall).pos.xr && players[otherPlayer].getWall(wall).isActive) {
// find hitted wall and its color
Serial.println("××× Hit Wall Event ×××");
wallHitted = true;
attackAnswer(wall, attackPlayer);
break;
}
}
}
if (!wallHitted) {
// final core detection
if (players[otherPlayer].core.layer == currentLayer) {
// compare core x-position, win condition
if (attackAnimPos.xr == players[otherPlayer].core.pos.xr) {
Serial.println("game won, next game state");
// reset attack for player 0
resetAttackPos(0);
// set attack player as winner
playerStateId = attackPlayer;
// player has won, next game State
delay(500);
animationSpeed = 8;
gameState++;
}
}
else {
// special case: no wall hitted after attack or after other player conter (empty attack)
const Position attackPosP0 = players[0].getAttackStartPos();
const Position attackPosP1 = players[1].getAttackStartPos();
// compare attack position (xr) from current attack player with
// attack start position (xr) from other player (Cross/X-Attack-Animation)
if (attackPlayer == 0 && attackAnimPos.xr == attackPosP1.xr) gameStateBack = true;
if (attackPlayer == 1 && attackAnimPos.xr == attackPosP0.xr) gameStateBack = true;
}
}
}
if (gameStateBack) {
// delete last attack line
matrices[currentLayer].drawLine(attackAnimPos.xl, attackAnimPos.y, attackAnimPos.xl, attackAnimPos.y + 1, matrixBlack);
matrices[currentLayer].drawLine(attackAnimPos.xr, attackAnimPos.y, attackAnimPos.xr, attackAnimPos.y + 1, matrixBlack);
matrices[currentLayer].show();
// last game State: reset all conter data
resetAttackPos(playerStateId);
isConter = false;
conterCounter = 3;
Serial.println("back to Action Selection from conter or empty atatck");
playerStateId = playerStateId == 0 ? 1 : 0;
// activate input for attack selection
activeInput = true;
gameState--;
}
}
void attackAnswer(int hittedWallId, int attackPlayer) {
bool gameStateBack = false;
int otherPlayer = attackPlayer == 0 ? 1 : 0;
// Compare Hitted Wall (A: same color, B: successful attack, C: lost attack)
Wall hittedWall = players[otherPlayer].getWall(hittedWallId);
Color hittedColor = hittedWall.color;
if (compareColor(attackColor, hittedColor)) {
// A: same color
Serial.println("A: Same Color");
// reset Start Position to other Player
resetAttackPos(otherPlayer);
isConter = !isConter;
conterCounter--;
}
else {
if (strongerColor(attackColor, hittedColor)) {
// B: successful attack
Serial.println("B: successful attack");
// delete hitted wall (view & logic)
players[otherPlayer].setWallActive(hittedWallId, false);
matrices[currentLayer].drawLine(hittedWall.pos.xl, hittedWall.pos.y, hittedWall.pos.xl, hittedWall.pos.y + 5, matrixBlack);
matrices[currentLayer].drawLine(hittedWall.pos.xr, hittedWall.pos.y, hittedWall.pos.xr, hittedWall.pos.y + 5, matrixBlack);
// blink feedback
int repetition = 2;
for (int num = 0; num < repetition; num++) {
matrices[currentLayer].drawLine(0, 0, MATRIX_W - 1, 0, matrices[currentLayer].Color(attackColor.red, attackColor.green, attackColor.blue));
matrices[currentLayer].drawLine(0, MATRIX_H - 1, MATRIX_W - 1, MATRIX_H - 1, matrices[currentLayer].Color(attackColor.red, attackColor.green, attackColor.blue));
matrices[currentLayer].show();
delay(225);
matrices[currentLayer].drawLine(0, 0, MATRIX_W - 1, 0, matrixBlack);
matrices[currentLayer].drawLine(0, MATRIX_H - 1, MATRIX_W - 1, MATRIX_H - 1, matrixBlack);
matrices[currentLayer].show();
delay(300);
}
// reset attack animation Y Add & go to next attack
currentAttackAnimAddY = 0;
prevAttackAnimAddY = 1;
gameStateBack = true;
}
else {
// C: lost attack
Serial.println("C: lost attack");
// remove lost attack -> reset wall (line color)
matrices[currentLayer].drawLine(hittedWall.pos.xl, hittedWall.pos.y, hittedWall.pos.xl, hittedWall.pos.y + 5, matrices[currentLayer].Color(hittedColor.red, hittedColor.green, hittedColor.blue));
matrices[currentLayer].drawLine(hittedWall.pos.xr, hittedWall.pos.y, hittedWall.pos.xr, hittedWall.pos.y + 5, matrices[currentLayer].Color(hittedColor.red, hittedColor.green, hittedColor.blue));
// reset attack animation Y Add & go to next attack
currentAttackAnimAddY = 0;
prevAttackAnimAddY = 1;
gameStateBack = true;
}
}
// isConter = false;
updateLights();
if (gameStateBack) {
// reset all conter data
resetAttackPos(playerStateId);
isConter = false;
conterCounter = 3;
Serial.println("back to Action Selection");
playerStateId = playerStateId == 0 ? 1 : 0;
// activate input for attack selection
activeInput = true;
gameState--;
}
}
// Graphics
void playAnimation(String name) {}
int x = MATRIX_W;
// Text Length + Width of a char
int titleChars = 5; // number of chars
int charWidth = 5; // in Pixel, default 5
int charGap = 1; // in Pixel
int titleLength = titleChars * charWidth + (titleChars - 1) * charGap;
// move start position to the right
int x2 = MATRIX_W + titleLength - (charWidth * 2 + charGap);
int x3 = x2 + titleLength - (charWidth * 2 + charGap);
int y = MATRIX_H - 1;
uint16_t winColor = matrixBlack;
void animatePlayerIndicator(int playerId, bool removeLast) {
Lightcore currentCore = players[playerId].core;
// *** Current Player Indicator ***
// remove last current player indicator
int CoreOff = 7; // 7 + 2 + 7 | 7 + 2 + 7 = 32 Pixel (2 Pixel Core)
// fill matrixBlack line in the matrix half of the current player
if (removeLast) {
Lightcore otherCore = players[playerId == 0 ? 1 : 0].core;
matrices[0].drawLine(otherCore.pos.xr - (CoreOff + 1), 0, otherCore.pos.xr + CoreOff, 0, matrixBlack);
matrices[2].drawLine(otherCore.pos.xr - (CoreOff + 1), MATRIX_H - 1, otherCore.pos.xr + CoreOff, MATRIX_H - 1, matrixBlack);
}
// trigger blink animation evry X-times
if (playerId == 0) {
if (currentPlayerAnimOffset[playerId] > currentCore.pos.xr + CoreOff) currentPlayerAnimOffset[playerId] = 0;
} else {
if (MATRIX_W/2 + currentPlayerAnimOffset[playerId] > currentCore.pos.xr + CoreOff) currentPlayerAnimOffset[playerId] = 0;
}
if (currentPlayerAnimCount[playerId] > 1) {
// overwrite current player indicator
currentPlayerAnimCount[playerId] = 0;
// add some randomness to create different animations every time
currentPlayerAnimOffset[playerId]++;
// add matrixBlack holes in animation (dashed line effect)
matrices[0].drawLine(currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 1, 0, currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 1, 0, matrixBlack);
matrices[2].drawLine(currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 1, MATRIX_H - 1, currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 1, MATRIX_H - 1, matrixBlack);
// add more depth to animation with shifted matrixBlack holes
matrices[0].drawLine(currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 3, 0, currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 3, 0, matrixBlack);
matrices[2].drawLine(currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 3, MATRIX_H - 1, currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId] - 3, MATRIX_H - 1, matrixBlack);
}
if (gameState < 4) {
// draw current player indicator (with player core posXr)
matrices[0].drawLine(currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId], 0, currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId], 0, matrices[currentLayer].Color(currentCore.color.red, currentCore.color.green, currentCore.color.blue));
matrices[2].drawLine(currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId], MATRIX_H - 1, currentCore.pos.xr - (CoreOff + 1) + currentPlayerAnimOffset[playerId], MATRIX_H - 1, matrices[currentLayer].Color(currentCore.color.red, currentCore.color.green, currentCore.color.blue));
currentPlayerAnimCount[playerId]++;
}
currentPlayerAnimOffset[playerId]++;
}
// draw lightcore and walls
void drawBuildPhase(int playerId) {
if (!players[playerId].core.isPlaced) {
Lightcore currentCore = players[playerId].core;
matrices[activeLayer[playerId]].drawRoundRect(currentCore.pos.xr - 1, MATRIX_H/2 - 1, 2, 2, 0, matrices[activeLayer[playerId]].Color(currentCore.color.red, currentCore.color.green, currentCore.color.blue));
matrices[activeLayer[playerId]].drawRoundRect(currentCore.pos.xr - 2, MATRIX_H/2 - 2, 4, 4, 1, matrices[activeLayer[playerId]].Color(currentCore.color.red, currentCore.color.green, currentCore.color.blue));
}
else {
int currentWallId = players[playerId].placedWalls;
// Update Walls
Wall pWall = players[playerId].getWall(currentWallId);
// draw wall left and right in this order
matrices[activeLayer[playerId]].drawLine(pWall.pos.xl, pWall.pos.y, pWall.pos.xl, pWall.pos.y + 5, matrices[activeLayer[playerId]].Color(pWall.color.red, pWall.color.green, pWall.color.blue));
matrices[activeLayer[playerId]].drawLine(pWall.pos.xr, pWall.pos.y, pWall.pos.xr, pWall.pos.y + 5, matrices[activeLayer[playerId]].Color(pWall.color.red, pWall.color.green, pWall.color.blue));
// save current wall position (x left, x right and y)
if (!oneGamepadMode) players[playerId].setWallLayer(currentWallId, activeLayer[playerId]);
if (oneGamepadMode) players[playerId].setWallLayer(currentWallId, currentLayer);
}
}
void updateLights() {
Lightcore playerCore = players[playerStateId].core;
if (gameState == 0) {
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].fillScreen(0);
// matrices[matrixId].setFont(&Picopixel); // 22, 26, 30
}
matrices[0].setTextColor(matrices[0].Color(colors[2].red, colors[2].green, colors[2].blue));
matrices[0].setCursor(x, 0);
matrices[0].print(F("LIGHT"));
if (--x < -titleLength) {
x = MATRIX_W - charWidth - charGap; // next start point
}
matrices[1].setTextColor(matrices[1].Color(colors[0].red, colors[0].green, colors[0].blue));
matrices[1].setCursor(x2, 0);
matrices[1].print(F("FIGHT"));
if (--x2 < -titleLength) {
x2 = MATRIX_W - charWidth - charGap; // next start point
}
matrices[2].setTextColor(matrices[1].Color(colors[1].red, colors[1].green, colors[1].blue));
matrices[2].setCursor(x3, 0);
matrices[2].print(F("PLAY>"));
if (--x3 < -titleLength) {
x3 = MATRIX_W - charWidth - charGap; // next start point
}
}
else {
int CoreOff = 7;
animatePlayerIndicator(0, false);
if (playerStateId == 2 && !oneGamepadMode) {
if (players[0].placedWalls < 3) {
animatePlayerIndicator(0, false);
}
else {
// remove indicator for player 1 (everything was placed)
Lightcore otherCore = players[0].core;
matrices[0].drawLine(otherCore.pos.xr - (CoreOff + 1), 0, otherCore.pos.xr + CoreOff, 0, matrixBlack);
matrices[2].drawLine(otherCore.pos.xr - (CoreOff + 1), MATRIX_H - 1, otherCore.pos.xr + CoreOff, MATRIX_H - 1, matrixBlack);
}
if (players[1].placedWalls < 3) {
animatePlayerIndicator(1, false);
}
else {
// remove indicator for player 2 (everything was placed)
Lightcore otherCore = players[1].core;
matrices[0].drawLine(otherCore.pos.xr - (CoreOff + 1), 0, otherCore.pos.xr + CoreOff, 0, matrixBlack);
matrices[2].drawLine(otherCore.pos.xr - (CoreOff + 1), MATRIX_H - 1, otherCore.pos.xr + CoreOff, MATRIX_H - 1, matrixBlack);
}
}
else {
animatePlayerIndicator(playerStateId, true);
}
}
// Update Core: Set matrixWhite Core to middle Layer & add color circle with selected color
if (gameState == 1) {
if (!oneGamepadMode) {
for (int playerId = 0; playerId < 2; playerId++) {
drawBuildPhase(playerId);
}
}
else {
drawBuildPhase(playerStateId);
}
}
// Update Attack Select
if (gameState == 2) {
const Position attackStartPos = players[playerStateId].getAttackStartPos();
// attack on start position
matrices[currentLayer].drawLine(attackStartPos.xl, attackStartPos.y, attackStartPos.xl, attackStartPos.y + 1, matrices[currentLayer].Color(attackColor.red, attackColor.green, attackColor.blue));
matrices[currentLayer].drawLine(attackStartPos.xr, attackStartPos.y, attackStartPos.xr, attackStartPos.y + 1, matrices[currentLayer].Color(attackColor.red, attackColor.green, attackColor.blue));
attackPosY = currentLayer;
}
// game end, player wins
if (gameState == 4) {
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
winColor = matrices[matrixId].Color(players[playerStateId].core.color.red, players[playerStateId].core.color.green, players[playerStateId].core.color.blue);
matrices[matrixId].drawLine(0, y, MATRIX_W - 1, y, winColor);
matrices[matrixId].drawLine(0, y, MATRIX_W - 1, y, matrixBlack);
matrices[matrixId].drawLine(0, y - 2, MATRIX_W - 1, y - 2, matrixBlack);
matrices[matrixId].drawLine(0, y - 4, MATRIX_W - 1, y - 4, matrixBlack);
matrices[matrixId].drawLine(0, y - 6, MATRIX_W - 1, y - 6, matrixBlack);
//matrices[matrixId].fillScreen(matrices[matrixId].Color(coreColor[playerStateId].red, coreColor[playerStateId].green, coreColor[playerStateId].blue));
}
if (--y < 6) {
y = MATRIX_H;
}
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
winColor = matrices[matrixId].Color(players[playerStateId].core.color.red, players[playerStateId].core.color.green, players[playerStateId].core.color.blue);
matrices[matrixId].drawLine(0, y, MATRIX_W - 1, y, winColor);
matrices[matrixId].drawLine(0, y, MATRIX_W - 1, y, winColor);
matrices[matrixId].drawLine(0, y - 2, MATRIX_W - 1, y - 2, winColor);
matrices[matrixId].drawLine(0, y - 4, MATRIX_W - 1, y - 4, winColor);
matrices[matrixId].drawLine(0, y - 6, MATRIX_W - 1, y - 6, winColor);
}
// for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
// matrices[matrixId].fillScreen(matrices[matrixId].Color(coreColor[playerStateId].red, coreColor[playerStateId].green, coreColor[playerStateId].blue));
// }
}
for (int matrixId = 0; matrixId <= MATRIX_NUM - 1; matrixId++) {
matrices[matrixId].show();
}
}