Refactor ArduBreakout sound and constants

- Use precomputed constant values directly usable by the Beep class
  for tone generation arguments.
  This reduces program size significantly.

- Use the constexpr specifier for all constants.
This commit is contained in:
Scott Allen 2020-07-19 16:35:05 -04:00
parent e0ade6ca99
commit 32d23b7984
1 changed files with 45 additions and 27 deletions

View File

@ -23,9 +23,24 @@
Arduboy2 arduboy; Arduboy2 arduboy;
BeepPin1 beep; BeepPin1 beep;
const unsigned int FRAME_RATE = 40; // Frame rate in frames per second constexpr uint8_t frameRate = 40; // Frame rate in frames per second
const unsigned int COLUMNS = 13; //Columns of bricks
const unsigned int ROWS = 4; //Rows of bricks // Tone frequencies. Converted to count values for the beep class
constexpr uint16_t tonePaddle = beep.freq(200); // Ball hits paddle
constexpr uint16_t toneBrick = beep.freq(261); // Ball hits a brick
constexpr uint16_t toneEdge = beep.freq(523); // Ball hits top or sides
constexpr uint16_t toneMiss = beep.freq(175); // Ball misses paddle, lose life
constexpr uint16_t toneInitialsChange = beep.freq(523); // Change initials
constexpr uint16_t toneInitialsMove = beep.freq(1046); // Select initials
// Tone durations
constexpr uint8_t toneTimeBeep = 250 / (1000 / frameRate); // Game (frames)
constexpr uint16_t toneTimeMiss = 500; // Miss paddle (milliseconds)
constexpr uint16_t toneTimeInitials = 80; // Initials entry (milliseconds)
constexpr unsigned int columns = 13; //Columns of bricks
constexpr unsigned int rows = 4; //Rows of bricks
int dx = -1; //Initial movement of ball int dx = -1; //Initial movement of ball
int dy = -1; //Initial movement of ball int dy = -1; //Initial movement of ball
int xb; //Ball's starting position int xb; //Ball's starting position
@ -33,7 +48,7 @@ int yb; //Ball's starting position
boolean released; //If the ball has been released by the player boolean released; //If the ball has been released by the player
boolean paused = false; //If the game has been paused boolean paused = false; //If the game has been paused
byte xPaddle; //X position of paddle byte xPaddle; //X position of paddle
boolean isHit[ROWS][COLUMNS]; //Array of if bricks are hit or not boolean isHit[rows][columns]; //Array of if bricks are hit or not
boolean bounced=false; //Used to fix double bounce glitch boolean bounced=false; //Used to fix double bounce glitch
byte lives = 3; //Amount of lives byte lives = 3; //Amount of lives
byte level = 1; //Current level byte level = 1; //Current level
@ -64,7 +79,7 @@ void setup()
{ {
arduboy.begin(); arduboy.begin();
beep.begin(); beep.begin();
arduboy.setFrameRate(FRAME_RATE); arduboy.setFrameRate(frameRate);
arduboy.initRandomSeed(); arduboy.initRandomSeed();
} }
@ -117,7 +132,7 @@ void loop()
oldpad = pad; oldpad = pad;
drawBall(); drawBall();
if(brickCount == ROWS * COLUMNS) if(brickCount == rows * columns)
{ {
level++; level++;
newLevel(); newLevel();
@ -192,7 +207,7 @@ void moveBall()
{ {
yb = 2; yb = 2;
dy = -dy; dy = -dy;
playTone(523, 250); playTone(toneEdge, toneTimeBeep);
} }
//Lose a life if bottom edge hit //Lose a life if bottom edge hit
@ -203,7 +218,7 @@ void moveBall()
yb=60; yb=60;
released = false; released = false;
lives--; lives--;
playToneTimed(175, 500); playToneTimed(toneMiss, toneTimeMiss);
if (random(0, 2) == 0) if (random(0, 2) == 0)
{ {
dx = 1; dx = 1;
@ -219,7 +234,7 @@ void moveBall()
{ {
xb = 2; xb = 2;
dx = -dx; dx = -dx;
playTone(523, 250); playTone(toneEdge, toneTimeBeep);
} }
//Bounce off right side //Bounce off right side
@ -227,7 +242,7 @@ void moveBall()
{ {
xb = WIDTH - 4; xb = WIDTH - 4;
dx = -dx; dx = -dx;
playTone(523, 250); playTone(toneEdge, toneTimeBeep);
} }
//Bounce off paddle //Bounce off paddle
@ -240,13 +255,13 @@ void moveBall()
{ {
dx = (random(0, 2) == 1) ? 1 : -1; dx = (random(0, 2) == 1) ? 1 : -1;
} }
playTone(200, 250); playTone(tonePaddle, toneTimeBeep);
} }
//Bounce off Bricks //Bounce off Bricks
for (byte row = 0; row < ROWS; row++) for (byte row = 0; row < rows; row++)
{ {
for (byte column = 0; column < COLUMNS; column++) for (byte column = 0; column < columns; column++)
{ {
if (!isHit[row][column]) if (!isHit[row][column])
{ {
@ -274,7 +289,7 @@ void moveBall()
dy =- dy; dy =- dy;
yb += dy; yb += dy;
bounced = true; bounced = true;
playTone(261, 250); playTone(toneBrick, toneTimeBeep);
} }
} }
@ -287,7 +302,7 @@ void moveBall()
dx =- dx; dx =- dx;
xb += dx; xb += dx;
bounced = true; bounced = true;
playTone(261, 250); playTone(toneBrick, toneTimeBeep);
} }
} }
} }
@ -364,6 +379,8 @@ void drawGameOver()
void pause() void pause()
{ {
paused = true; paused = true;
//Stop tone if playing
beep.noTone();
//Draw pause to the screen //Draw pause to the screen
arduboy.setCursor(52, 45); arduboy.setCursor(52, 45);
arduboy.print("PAUSE"); arduboy.print("PAUSE");
@ -568,7 +585,7 @@ void enterInitials()
if (index > 0) if (index > 0)
{ {
index--; index--;
playToneTimed(1046, 80); playToneTimed(toneInitialsMove, toneTimeInitials);
} }
} }
@ -577,14 +594,14 @@ void enterInitials()
if (index < 2) if (index < 2)
{ {
index++; index++;
playToneTimed(1046, 80); playToneTimed(toneInitialsMove, toneTimeInitials);
} }
} }
if (arduboy.pressed(UP_BUTTON)) if (arduboy.pressed(UP_BUTTON))
{ {
initials[index]++; initials[index]++;
playToneTimed(523, 80); playToneTimed(toneInitialsChange, toneTimeInitials);
// A-Z 0-9 :-? !-/ ' ' // A-Z 0-9 :-? !-/ ' '
if (initials[index] == '0') if (initials[index] == '0')
{ {
@ -607,7 +624,7 @@ void enterInitials()
if (arduboy.pressed(DOWN_BUTTON)) if (arduboy.pressed(DOWN_BUTTON))
{ {
initials[index]--; initials[index]--;
playToneTimed(523, 80); playToneTimed(toneInitialsChange, toneTimeInitials);
if (initials[index] == ' ') if (initials[index] == ' ')
{ {
initials[index] = '?'; initials[index] = '?';
@ -628,7 +645,7 @@ void enterInitials()
if (arduboy.pressed(A_BUTTON)) if (arduboy.pressed(A_BUTTON))
{ {
playToneTimed(1046, 80); playToneTimed(toneInitialsMove, toneTimeInitials);
if (index < 2) if (index < 2)
{ {
index++; index++;
@ -712,18 +729,19 @@ void enterHighScore(byte file)
} }
} }
// Play a tone at the specified frequency for the specified duration. // Play a tone at a frequency coresponding to the specified precomputed count,
void playTone(unsigned int frequency, unsigned int duration) // for the specified number of frames.
void playTone(uint16_t count, uint8_t frames)
{ {
beep.tone(beep.freq(frequency), duration / (1000 / FRAME_RATE)); beep.tone(count, frames);
} }
// Play a tone at the specified frequency for the specified duration using // Play a tone at a frequency coresponding to the specified precomputed count,
// a delay to time the tone. // for the specified duration in milliseconds, using a delay.
// Used when beep.timer() isn't being called. // Used when beep.timer() isn't being called.
void playToneTimed(unsigned int frequency, unsigned int duration) void playToneTimed(uint16_t count, uint16_t duration)
{ {
beep.tone(beep.freq(frequency)); beep.tone(count);
arduboy.delayShort(duration); arduboy.delayShort(duration);
beep.noTone(); beep.noTone();
} }