Skip to content
This repository has been archived by the owner on Dec 30, 2024. It is now read-only.

Commit

Permalink
Koodi korjauksia segmentit, painikkeet ja peli motoriikka
Browse files Browse the repository at this point in the history
Korjasin painikkeiden, segmenttien toiminnallisuutta vastaamaan vuokaavion suunitelmaa. Nyt segmentisä näkyy highscore oikein, sekä secore. Peli käynistyy mitä tahansa painiketta painamalla.
Todo pelinopeus säädettävä.
  • Loading branch information
vem882 committed Oct 7, 2024
1 parent fa9414b commit 95aeeaf
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 136 deletions.
111 changes: 73 additions & 38 deletions Kooditoteutus/SpedenSpelit/SpedenSpelit.ino
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
volatile int buttonNumber = -1; // for buttons interrupt handler
volatile bool newTimerInterrupt = false; // for timer interrupt handler
int currentScore = 0; // Oletusarvo voi olla 0, tai muu alkuarvo

int highScore = 0; // Korkein pistemäärä, joka tallennetaan EEPROMiin

// Peliin liittyvät muuttujat
byte randomLed = 0;
int timerInterruptCount = 0;
int gameSpeed = 5000; // Alustava pelin nopeus
bool gameStarted = false; // Pelin tila
unsigned long buttonPressTime = 0; // Painikkeen painalluksen aloitusaika

void setup() {
/*
Expand All @@ -30,40 +32,59 @@ void setup() {
initButtonsAndButtonInterrupts();
initializeTimer();

// Ladataan korkein pistemäärä EEPROMista
highScore = EEPROM.read(0);

// Näytetään korkein pistemäärä alussa
updateDisplay(highScore);

// Aloitetaan peli
initializeGame();
}

void loop() {
if (buttonNumber >= 0) {
// start the game if buttonNumber == 4 (pin 6)
if (buttonNumber == 4) {
if (!gameStarted) {
startTheGame();
}
// check the game if 0 <= buttonNumber < 4
else if (buttonNumber >= 0 && buttonNumber < 4) {
checkGame(buttonNumber);
gameStarted = true;
} else {
// check the game if 0 <= buttonNumber < 4
if (buttonNumber >= 0 && buttonNumber < 4) {
checkGame(buttonNumber);
}
}

buttonNumber = -1; // Reset button state after processing
}

if (newTimerInterrupt == true) {
// Generate a new random number for LED
clearAllLeds();
randomLed = random(0, 4); // Random LED between 0 and 3
setLed(randomLed); // Sytytetään sattumanvarainen LED

// Lisätään pelin nopeutta joka 10. keskeytyksessä
timerInterruptCount++;
if (timerInterruptCount >= 10) {
gameSpeed = max(200, gameSpeed - 100); // Peli nopeutuu, mutta ei alle 200 ms
OCR1A = gameSpeed * 16; // Asetetaan uusi nopeus
timerInterruptCount = 0; // Nollataan laskuri
if (gameStarted) {
// Generate a new random number for LED
clearAllLeds();
randomLed = random(0, 4); // Random LED between 0 and 3
setLed(randomLed); // Sytytetään sattumanvarainen LED
} else {
// Näytetään korkein pistemäärä, kun peli ei ole käynnissä
updateDisplay(highScore);
}

newTimerInterrupt = false; // Nollataan keskeytyksen tilamuuttuja
}

// Tarkistetaan, onko kahta painiketta painettu 2 sekuntia high scoren nollaamiseksi
if (digitalRead(2) == LOW && digitalRead(3) == LOW) {
if (buttonPressTime == 0) {
buttonPressTime = millis();
} else if (millis() - buttonPressTime >= 2000) {
highScore = 0;
EEPROM.write(0, highScore);
updateDisplay(highScore);
Serial.println("High score reset!");
buttonPressTime = 0;
}
} else {
buttonPressTime = 0;
}
}

void initializeTimer(void) {
Expand All @@ -82,28 +103,42 @@ ISR(TIMER1_COMPA_vect) {
newTimerInterrupt = true; // Ilmoitetaan, että on aika luoda uusi satunnaisluku
}

void checkGame(byte nbrOfButtonPush) {
// Tarkistetaan, onko painettu nappi oikea (sama kuin sattumanvarainen LED)
if (nbrOfButtonPush == randomLed) {
Serial.println("Oikea nappi painettu! Piste!");
showResult(10); // Esimerkiksi näytetään tulos 10
} else {
Serial.println("Väärä nappi! Peli ohi.");
showResult(0); // Näytetään nolla, peli ohi
initializeGame(); // Aloitetaan peli uudelleen
}
}

void initializeGame() {
Serial.println("Pelin alustus.");
clearAllLeds(); // Sammutetaan kaikki LEDit
showResult(currentScore); // Näytetään alussa 0
gameSpeed = 5000; // Resetoi pelin nopeus
timerInterruptCount = 0; // Nollaa keskeytyslaskuri
currentScore = 0;
gameSpeed = 5000;
timerInterruptCount = 0;
gameStarted = false;
clearAllLeds();
updateDisplay(highScore); // Näytetään korkein pistemäärä alussa
Serial.println("Game initialized!");
}

void startTheGame() {
Serial.println("Peli alkaa!");
randomLed = random(0, 4); // Valitaan satunnainen LED
setLed(randomLed); // Sytytetään satunnainen LED
currentScore = 0;
gameSpeed = 5000;
timerInterruptCount = 0;
gameStarted = true;
updateDisplay(currentScore); // Näytetään 0, kun peli alkaa
Serial.println("Game started!");
}

void checkGame(int button) {
if (button == randomLed) {
currentScore++;
Serial.print("Correct button! Score: ");
Serial.println(currentScore);
updateDisplay(currentScore); // Päivitetään näyttö
if (currentScore % 5 == 0) {
gameSpeed = gameSpeed * 0.9; // Peli nopeutuu 10%
OCR1A = (gameSpeed * 16) / 1000; // Asetetaan uusi nopeus
}
} else {
Serial.println("Wrong button! Game over.");
gameStarted = false;
if (currentScore > highScore) {
highScore = currentScore;
EEPROM.write(0, highScore); // Tallennetaan uusi korkein pistemäärä EEPROMiin
}
updateDisplay(currentScore); // Näytetään pelin tulos
}
}
38 changes: 15 additions & 23 deletions Kooditoteutus/SpedenSpelit/buttons.cpp
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
#include "buttons.h"

const int buttonPins[] = {5, 6, 7, 8};

static unsigned long lastInterruptTimestamp = 0;

void initButtonsAndButtonInterrupts(void) // Initializes all buttons
{
void initButtonsAndButtonInterrupts(void) {
PCICR |= (1 << PCIE0); // Enable pin change interrupt for PCINT0
PCMSK0 |= (1 << PCINT0) | (1 << PCINT1) | (1 << PCINT2) | (1 << PCINT3); // Enable interrupts for pins 8, 9, 10, 11

Serial.println("Ititializing buttons");
for (int i = 0; i < sizeof(buttonPins) / sizeof(buttonPins[0]); i++)
{
Serial.print("Button pin: ");
Serial.println(buttonPins[i]);
pinMode(buttonPins[i], INPUT_PULLUP);
}
Serial.println("Initializing buttons");

for (int i = 0; i < sizeof(buttonPins) / sizeof(buttonPins[0]); i++) {
Serial.print("Button pin: ");
Serial.println(buttonPins[i]);
pinMode(buttonPins[i], INPUT_PULLUP);
}
}

ISR(PCINT0_vect) // got a button interrupt
{
ISR(PCINT0_vect) {
// Sources: https://docs.arduino.cc/built-in-examples/digital/Debounce/
// Allows button presses every 50 ms to get rid of button debounce

unsigned long thisInterruptTimestamp = millis();

if (thisInterruptTimestamp - lastInterruptTimestamp > 200) // over 50 ms since last interrupt
{
for (int i = 0; i < sizeof(buttonPins) / sizeof(buttonPins[0]); i++)
{
if (digitalRead(buttonPins[i]) == LOW) // checks if any pins in buttonPins is LOW
{
buttonNumber = i; // buttonNumber will be 0-3
lastInterruptTimestamp = thisInterruptTimestamp; // Updates the timestamp to be current interrupt time

if (thisInterruptTimestamp - lastInterruptTimestamp > 200) { // over 50 ms since last interrupt
for (int i = 0; i < sizeof(buttonPins) / sizeof(buttonPins[0]); i++) {
if (digitalRead(buttonPins[i]) == LOW) { // checks if any pins in buttonPins is LOW
buttonNumber = i; // buttonNumber will be 0-3
lastInterruptTimestamp = thisInterruptTimestamp; // Updates the timestamp to be current interrupt time
break;
}
}
Expand Down
42 changes: 18 additions & 24 deletions Kooditoteutus/SpedenSpelit/display.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "display.h"
#include <Arduino.h>

// Define pins for 7-segment display control
const int shiftClockPin = 3;
Expand All @@ -22,7 +23,7 @@ const uint8_t digitBits[] = {

void initializeDisplay(void) {
// Initialize all the control pins as outputs
Serial.println("Ititializing displays");
Serial.println("Initializing displays");
pinMode(shiftClockPin, OUTPUT);
pinMode(latchClockPin, OUTPUT);
pinMode(outEnablePin, OUTPUT);
Expand All @@ -36,31 +37,24 @@ void initializeDisplay(void) {
digitalWrite(outEnablePin, LOW); // Enable output
}

void writeByte(uint8_t number, bool last) {
void writeByte(uint8_t number) {
// Send the byte corresponding to the 7-segment digit
shiftOut(serialInputPin, shiftClockPin, MSBFIRST, digitBits[number]);

// If this is the last byte, latch the data
if (last) {
digitalWrite(latchClockPin, HIGH); // Pulse the latch to make the output visible
delayMicroseconds(100); // Short delay for stability
digitalWrite(latchClockPin, LOW); // Bring the latch low again
}
shiftOut(serialInputPin, shiftClockPin, MSBFIRST, number);
}

void writeHighAndLowNumber(uint8_t tens, uint8_t ones) {
// Write the tens first without latching
writeByte(tens, false);

// Write the ones and latch it
writeByte(ones, true); // Latch this one
}
void updateDisplay(int score) {
int tens = score / 10;
int units = score % 10;

void showResult(byte result) {
// Calculate the tens and ones from the result
uint8_t tens = result / 10;
uint8_t ones = result % 10;

// Write the result to the display
writeHighAndLowNumber(tens, ones);
digitalWrite(latchClockPin, LOW);
writeByte(digitBits[units]); // Write units first
writeByte(digitBits[tens]); // Write tens second
digitalWrite(latchClockPin, HIGH);
}

void clearDisplay() {
digitalWrite(latchClockPin, LOW);
writeByte(0);
writeByte(0);
digitalWrite(latchClockPin, HIGH);
}
55 changes: 4 additions & 51 deletions Kooditoteutus/SpedenSpelit/display.h
Original file line number Diff line number Diff line change
@@ -1,57 +1,10 @@
#ifndef DISPLAY_H
#define DISPLAY_H

#include <Arduino.h> // Sisältää tarvittavat Arduino-kirjastot
#include <Arduino.h>

// Funktioiden otsikot:

/*
initializeDisplay subroutine initializes 5 pins needed for controlling 7-segment
displays in a cascade as follows:
Arduino pin 12 = serial to parallel component reset
Arduino pin 11 = serial to parallel component shiftClock
Arduino pin 10 = serial to parallel component latchClock
Arduino pin 9 = serial to parallel component outEnable
Arduino pin 8 = serial to parallel component serialInput
*/
void initializeDisplay(void);
void updateDisplay(int score);
void clearDisplay(void);

/*
WriteByte subroutine writes number 0,1,...,9 to
7-segment display. If there are many 7-segment
displays cascaded, last parameter can be used to
control when number is actually shown at the outputs of
display element.
Parameters:
uint8_t number: accepts values 0,1,..,9
bool last: either true or false. True = number is displayed
at the output, false is used if this function is called
multiple times to write all cascaded numbers to 7-segment
displays.
*/
void writeByte(uint8_t number, bool last);

/*
writeHighAndLowNumber subroutine writes a number 0,1,..,99
to 2 cascaded 7-segment displays. This subroutine uses
WriteByte subroutine to write 2 numbers to the display.
Parameters:
uint8_t tens: number 0,1,..,9
uint8_t ones: number 0,1,..,9
*/
void writeHighAndLowNumber(uint8_t tens,uint8_t ones);

/*
showResuts(byte result) This function separates tens and ones
from a result number and calls writeHighAndLowNumber subroutine
to actually write the number to 7-segment display.
Parameters:
byte result: A number between 0,1,..,99. This function
*/
void showResult(byte result);

#endif // DISPLAY_H
#endif

0 comments on commit 95aeeaf

Please sign in to comment.