Last active
June 25, 2020 19:28
-
-
Save jnrdrgz/33daa6897dc5e13830c6438d1000eb9f to your computer and use it in GitHub Desktop.
arduino 4_1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////// | |
//Proyecto: (1000/250) juegos en 1 | |
//////////////////////////////////////////////////// | |
//Autor: Juan Ignacio Rodríguez | |
//Materia: Lab III | |
//////////////////////////////////////////////////// | |
//Descripcion: el proyecto consta de 4 juegos | |
//en la pantalla LCD 16x2 con un menu de selección | |
//y 4 botones: arriba(pin 6), abajo(pin 9), | |
//derecha(pin 8) e izquierda(pin 7). | |
// | |
//////////////////////////////////////////////////// | |
// | |
//Los juegos son: | |
//GunGame: se controla una pistola y el objectivo es | |
//disparar a las '@' que aparece desde la derecha | |
//de la pantalla, en caso de que alguna llegue a la | |
//linea de la pistola, el jugador pierde | |
//Controles: | |
//arriba/abajo: controla la pistola | |
//derecha: dispara | |
// | |
//////////////////////////////////////////////////// | |
// | |
//JumpGame: se controla a la personaje en la esquina | |
//inferior izquierda de la pantalla, el objetivo es | |
//salta la mayor cantidad de 'T' posible mientras | |
//el personaje avanza automaticamente hacía la derecha | |
//Controles: | |
//arriba: salto | |
// | |
//////////////////////////////////////////////////// | |
// | |
//DirectionsGame: el jugador debe presionar el boton | |
//arriba/abajo/izquierda/derecha en el orden que van | |
//apareciendo las letras U,D,R o L desde la derecha | |
//de la pantalla | |
//Controles: | |
//arriba:U(up) | |
//abajo:D(down) | |
//right:R(right) | |
//left:L(left) | |
// | |
//////////////////////////////////////////////////// | |
// | |
//EscapeGame: el personaje debe llegar a la puerta | |
//en la esquina inferior derecha de la pantalla, sin | |
//chocar con ninguno de los fantasmas que se mueven | |
//aleatoriamente por la pantalla. | |
//Controles: | |
//arriba/abajo/derecha/izquierda: | |
//mueven al personaje | |
// | |
//////////////////////////////////////////////////// | |
//////////////////////////////////////////////////// | |
#include <LiquidCrystal.h> | |
////////////// | |
//CONSTANTES// | |
////////////// | |
//ENV | |
#define DEBUG 0 | |
#define BUTTON_UP 6 | |
#define BUTTON_LEFT 7 | |
#define BUTTON_RIGHT 8 | |
#define BUTTON_DOWN 9 | |
#define UP 0 | |
#define LEFT 1 | |
#define RIGHT 2 | |
#define DOWN 3 | |
#define GUN_SPRITE 0 | |
#define BULLET_SPRITE 1 | |
#define PERSON_SPRITE 2 | |
#define ARROW_UP_SPRITE 3 | |
#define ARROW_DOWN_SPRITE 4 | |
#define PHANTOM_SPRITE 5 | |
#define DOOR_SPRITE 6 | |
//LCD | |
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); | |
/////////// | |
//SPRITES// | |
/////////// | |
byte gun[8] = { | |
B11111, | |
B10100, | |
B11100, | |
B10000, | |
B10000, | |
B00000, | |
B00000, | |
}; | |
byte bullet[8] = { | |
B00000, | |
B11110, | |
B10001, | |
B10001, | |
B11110, | |
B00000, | |
B00000, | |
}; | |
byte person[8] = { | |
B11111, | |
B10001, | |
B11111, | |
B00100, | |
B00100, | |
B01010, | |
B10001, | |
}; | |
byte arrow_up[8] = { | |
B00100, | |
B01010, | |
B10001, | |
B00000, | |
B00000, | |
B00000, | |
B00000, | |
}; | |
byte arrow_down[8] = { | |
B00000, | |
B00000, | |
B00000, | |
B00000, | |
B10001, | |
B01010, | |
B00100, | |
}; | |
byte phantom[8] = { | |
B11111, | |
B11011, | |
B10001, | |
B10001, | |
B10001, | |
B11111, | |
B10101, | |
}; | |
byte door[8] = { | |
B00000, | |
B01110, | |
B10001, | |
B11001, | |
B10001, | |
B10001, | |
B11111, | |
}; | |
////////////////// | |
//CLASES COMUNES// | |
////////////////// | |
struct Score | |
{ | |
Score() : points{0} {} | |
void draw(){ | |
lcd.setCursor(13, 0); | |
if(points < 100) lcd.setCursor(14, 0); | |
if(points < 10) lcd.setCursor(15, 0); | |
lcd.print(points); | |
} | |
unsigned int points; | |
}; | |
struct GameObject | |
{ | |
GameObject(int x, int y, char sprite) | |
: x{x},y{y},sprite{sprite},active{true} | |
{} | |
void clean(){ | |
lcd.setCursor(x, y); | |
lcd.print(" "); | |
} | |
void move(int dir){ | |
if(dir == LEFT){ | |
if(x > 0){ | |
clean(); | |
x--; | |
} | |
} | |
if(dir == RIGHT){ | |
if(x < 16){ | |
clean(); | |
x++; | |
} | |
} | |
if(dir == DOWN){ | |
if(y < 1){ | |
clean(); | |
y++; | |
} | |
} | |
if(dir == UP){ | |
if(y > 0){ | |
clean(); | |
y--; | |
} | |
} | |
} | |
void draw(){ | |
lcd.setCursor(x, y); | |
lcd.print(sprite); | |
} | |
int x, y; | |
bool active; | |
char sprite; | |
}; | |
struct SpriteGameObject : GameObject | |
{ | |
SpriteGameObject(int x, int y, int byte_sprite_id) | |
: GameObject(x,y,'x') | |
{ | |
this->byte_sprite_id = byte_sprite_id; | |
} | |
void draw(){ | |
lcd.setCursor(x, y); | |
lcd.write(byte(byte_sprite_id)); | |
} | |
int byte_sprite_id; | |
}; | |
////////////////// | |
/////INTERFACE//// | |
////////////////// | |
struct Game | |
{ | |
virtual void handle_input() = 0; | |
virtual void update() = 0; | |
virtual void draw() = 0; | |
virtual void show_lose_message() = 0; | |
bool ended; | |
}; | |
////////////////// | |
//////GAMES/////// | |
////////////////// | |
struct GunGame : Game | |
{ | |
GunGame() : player{SpriteGameObject(0,0,GUN_SPRITE)}, | |
enemy{GameObject(15,0,'@')}, | |
arrow{SpriteGameObject(0,0,BULLET_SPRITE)}, | |
enemy_has_to_respawn{false} | |
{ | |
ended = false; | |
arrow.active = false; | |
} | |
void handle_input() override{ | |
if(digitalRead(BUTTON_UP)){ | |
#if DEBUG | |
Serial.println("up in Gun"); | |
#endif | |
player.move(UP); | |
} | |
if(digitalRead(BUTTON_LEFT)){ | |
#if DEBUG | |
Serial.println("left in Gun"); | |
#endif | |
} | |
if(digitalRead(BUTTON_RIGHT)){ | |
#if DEBUG | |
Serial.println("right in Gun"); | |
#endif | |
arrow.clean(); | |
arrow.x = player.x+1; | |
arrow.y = player.y; | |
arrow.active = true; | |
} | |
if(digitalRead(BUTTON_DOWN)){ | |
#if DEBUG | |
Serial.println("down in Arrow"); | |
#endif | |
player.move(DOWN); | |
} | |
} | |
void update() override{ | |
if(enemy.active) enemy.move(LEFT); | |
if(arrow.active) arrow.move(RIGHT); | |
if(enemy_has_to_respawn){ | |
enemy.active = true; | |
} | |
if((arrow.x == enemy.x || arrow.x == enemy.x-1) | |
&& arrow.y == enemy.y && arrow.active){ | |
enemy.clean(); | |
arrow.clean(); | |
enemy.active = false; | |
arrow.active = false; | |
enemy_has_to_respawn = true; | |
score.points++; | |
enemy.x = 15; | |
enemy.y = random(0, 2); | |
} | |
if(enemy.x <= player.x){ | |
ended = true; | |
} | |
if(enemy.x == 0){ | |
enemy.x = 15; | |
enemy.y = random(0, 2); | |
} | |
} | |
void draw() override { | |
player.draw(); | |
if(enemy.active) enemy.draw(); | |
if(arrow.active) arrow.draw(); | |
} | |
void show_lose_message() override { | |
lcd.clear(); | |
lcd.setCursor(0, 0); | |
lcd.print("Perdiste D:"); | |
lcd.setCursor(0, 1); | |
lcd.print("Puntos: "); | |
lcd.setCursor(8, 1); | |
lcd.print(score.points); | |
delay(5000); | |
} | |
SpriteGameObject player; | |
GameObject enemy; | |
SpriteGameObject arrow; | |
Score score; | |
bool enemy_has_to_respawn; | |
}; | |
struct JumpGame : Game | |
{ | |
JumpGame() : player({2,1,PERSON_SPRITE}), | |
enemies({{16,1,'T'}, | |
{random(20,25),1,'T'}, | |
{random(27,33),1,'T'}} | |
), | |
player_is_flying(false), | |
flying_turns(0) | |
{ | |
ended = false; | |
} | |
void show_lose_message() override { | |
lcd.clear(); | |
lcd.setCursor(0, 0); | |
lcd.print("Perdiste D:"); | |
lcd.setCursor(0, 1); | |
lcd.print("Puntos: "); | |
lcd.setCursor(8, 1); | |
lcd.print(score.points); | |
delay(5000); | |
} | |
void handle_input() override{ | |
if(digitalRead(BUTTON_UP)){ | |
if(!player_is_flying){ | |
player.move(UP); | |
player_is_flying = true; | |
} | |
} | |
} | |
void update() override{ | |
for(int i = 0; i < 3; i++){ | |
if(enemies[i].active) enemies[i].move(LEFT); | |
if(enemies[i].x == 0) enemies[i].x = random(16,25); | |
if(enemies[i].x == player.x){ | |
if(player.y == 1) ended = true; | |
if(player.y == 0) score.points++; | |
} | |
} | |
if(player_is_flying){ | |
flying_turns++; | |
if(flying_turns > 3){ | |
flying_turns = 0; | |
player.move(DOWN); | |
player_is_flying = false; | |
} | |
} | |
} | |
void draw() override { | |
player.draw(); | |
for(int i = 0; i < 3; i++){ | |
if(enemies[i].active) enemies[i].draw(); | |
} | |
} | |
SpriteGameObject player; | |
GameObject enemies[3]; | |
bool player_is_flying; | |
unsigned short flying_turns; | |
Score score; | |
}; | |
struct DirectionsGame : Game | |
{ | |
DirectionsGame() : directions{'U','D','L','R'}, | |
dirtargets({{15,0,directions[random(0,4)]}, | |
{18,1,directions[random(0,4)]}, | |
{21,0,directions[random(0,4)]}, | |
{24,1,directions[random(0,4)]}, | |
{27,0,directions[random(0,4)]}, | |
{30,1,directions[random(0,4)]}, | |
{33,0,directions[random(0,4)]}, | |
{36,1,directions[random(0,4)]} | |
} | |
) | |
{ | |
ended = false; | |
current_target = 0; | |
dif_level = 3; | |
selected_dir = 'N'; | |
} | |
void show_lose_message() override { | |
lcd.clear(); | |
lcd.setCursor(0, 0); | |
lcd.print("Perdiste D:"); | |
lcd.setCursor(0, 1); | |
lcd.print("Tandas: "); | |
lcd.setCursor(8, 1); | |
lcd.print(score.points); | |
delay(5000); | |
} | |
void handle_input() override{ | |
if(digitalRead(BUTTON_UP)){ | |
selected_dir = 'U'; | |
} | |
if(digitalRead(BUTTON_DOWN)){ | |
selected_dir = 'D'; | |
} | |
if(digitalRead(BUTTON_LEFT)){ | |
selected_dir = 'L'; | |
} | |
if(digitalRead(BUTTON_RIGHT)){ | |
selected_dir = 'R'; | |
} | |
} | |
void restart(){ | |
int base_x = 15; | |
for(int i = 0; i < 8; i++){ | |
dirtargets[i].sprite = directions[random(0,4)]; | |
dirtargets[i].x = base_x; | |
dirtargets[i].active = true; | |
base_x += dif_level; | |
} | |
current_target = 0; | |
} | |
void update() override{ | |
for(int i = 0; i < 8; i++){ | |
if(dirtargets[i].active){ | |
dirtargets[i].move(LEFT); | |
if(dirtargets[i].x == 0){ | |
ended = true; | |
} | |
} | |
} | |
if(selected_dir != 'N'){ | |
if(dirtargets[current_target].sprite == selected_dir){ | |
dirtargets[current_target].active = false; | |
current_target++; | |
selected_dir = 'N'; | |
if(current_target >= 8){ | |
score.points++; | |
restart(); | |
//nivel de dificultad menor == menos tiempo == mas dificil | |
if(dif_level > 1) dif_level--; | |
} | |
} | |
} | |
} | |
void draw() override { | |
for(int i = 0; i < 8; i++){ | |
if(dirtargets[i].active) dirtargets[i].draw(); | |
} | |
} | |
char directions[4]; | |
char selected_dir; | |
GameObject dirtargets[8]; | |
int current_target; | |
int dif_level; | |
Score score; | |
}; | |
struct EscapeGame : Game | |
{ | |
EscapeGame(): player({0,1,PERSON_SPRITE}), | |
phantoms({ {random(2,5), random(0,2),PHANTOM_SPRITE}, | |
{random(4,7), random(0,2),PHANTOM_SPRITE}, | |
{random(6,9), random(0,2),PHANTOM_SPRITE}, | |
{random(8,11), random(0,2),PHANTOM_SPRITE}, | |
{random(10,13),random(0,2),PHANTOM_SPRITE}, | |
{random(13,14),random(0,2),PHANTOM_SPRITE} | |
} | |
), | |
escape_door(SpriteGameObject(15,1,DOOR_SPRITE)) | |
{ | |
ended = false; | |
player_move = false; | |
escapes = 0; | |
} | |
void show_lose_message() override { | |
lcd.clear(); | |
lcd.setCursor(0, 0); | |
lcd.print("Perdiste D:"); | |
lcd.setCursor(0, 1); | |
lcd.print("Escapes: "); | |
lcd.setCursor(8, 1); | |
lcd.print(escapes); | |
delay(5000); | |
} | |
void show_win_message(){ | |
lcd.clear(); | |
lcd.setCursor(0, 0); | |
lcd.print("Escapaste!"); | |
delay(4000); | |
} | |
void restart(){ | |
show_win_message(); | |
lcd.clear(); | |
escapes++; | |
player.x = 0; | |
player.y = 0; | |
for(int i = 0; i < 6; i++){ | |
phantoms[i].x = random(3,14); | |
phantoms[i].y = random(0,2); | |
} | |
} | |
void handle_input() override{ | |
if(digitalRead(BUTTON_UP)){ | |
player.move(UP); | |
player_move = true; | |
} | |
if(digitalRead(BUTTON_DOWN)){ | |
player.move(DOWN); | |
player_move = true; | |
} | |
if(digitalRead(BUTTON_LEFT)){ | |
player.move(LEFT); | |
player_move = true; | |
} | |
if(digitalRead(BUTTON_RIGHT)){ | |
player.move(RIGHT); | |
player_move = true; | |
} | |
} | |
void update() override{ | |
if(player_move){ | |
player_move = false; | |
for(int i = 0; i < 6; i++){ | |
phantoms[i].move(random(0,4)); | |
if(player.x == phantoms[i].x && player.y == phantoms[i].y){ | |
ended = true; | |
} | |
} | |
if(player.x >= escape_door.x && player.y == escape_door.y){ | |
restart(); | |
} | |
} | |
} | |
void draw() override { | |
player.draw(); | |
for(int i = 0; i < 6; i++){ | |
phantoms[i].draw(); | |
} | |
escape_door.draw(); | |
} | |
bool player_move; | |
int escapes; | |
SpriteGameObject player; | |
SpriteGameObject phantoms[6]; | |
SpriteGameObject escape_door; | |
}; | |
////////////////// | |
///////MAIN/////// | |
////////////////// | |
struct MainGame | |
{ | |
MainGame() : currentGame(NULL), menu(true){} | |
~MainGame(){ | |
delete currentGame; | |
} | |
void handle_input(){ | |
if(menu){ | |
if(digitalRead(BUTTON_UP)) change_game(1); | |
if(digitalRead(BUTTON_LEFT)) change_game(2); | |
if(digitalRead(BUTTON_RIGHT)) change_game(3); | |
if(digitalRead(BUTTON_DOWN)) change_game(4); | |
} else { | |
currentGame->handle_input(); | |
} | |
} | |
void change_game(int j){ | |
if(currentGame){ | |
delete currentGame; | |
currentGame = NULL; | |
} | |
lcd.clear(); | |
menu = false; | |
if(j == 1) currentGame = new GunGame(); | |
else if(j == 2) currentGame = new JumpGame(); | |
else if(j == 3) currentGame = new DirectionsGame(); | |
else currentGame = new EscapeGame(); | |
} | |
void update(){ | |
if(!menu){ | |
currentGame->update(); | |
if(currentGame->ended){ | |
currentGame->show_lose_message(); | |
menu = true; | |
} | |
} | |
} | |
void draw(){ | |
if(menu){ | |
lcd.setCursor(0, 0); | |
lcd.print("Elegir un juego:"); | |
lcd.setCursor(0, 1); | |
lcd.print("<g1 vg2 ^g3 >g4"); | |
} else { | |
currentGame->draw(); | |
} | |
} | |
Game* currentGame = NULL; | |
bool menu; | |
}; | |
void test_tomando_bien_inputs(){ | |
if(digitalRead(BUTTON_UP)){ | |
Serial.println("up"); | |
} | |
if(digitalRead(BUTTON_DOWN)){ | |
Serial.println("down"); | |
} | |
if(digitalRead(BUTTON_LEFT)){ | |
Serial.println("left"); | |
} | |
if(digitalRead(BUTTON_RIGHT)){ | |
Serial.println("right"); | |
} | |
} | |
////////////////////// | |
//VARIABLES GLOBALES// | |
///////////////////// | |
MainGame game; | |
unsigned long previousMillis = 0; | |
const long interval = 50; | |
////////////////// | |
///MAIN ARDUINO/// | |
////////////////// | |
void setup() { | |
lcd.begin(16, 2); | |
lcd.createChar(GUN_SPRITE, gun); | |
lcd.createChar(BULLET_SPRITE, bullet); | |
lcd.createChar(PERSON_SPRITE, person); | |
lcd.createChar(ARROW_DOWN_SPRITE, arrow_down); | |
lcd.createChar(ARROW_UP_SPRITE, arrow_up); | |
lcd.createChar(PHANTOM_SPRITE, phantom); | |
lcd.createChar(DOOR_SPRITE, door); | |
//lcd.createChar(7, ); | |
Serial.begin(9600); | |
pinMode(BUTTON_UP, INPUT); | |
pinMode(BUTTON_DOWN, INPUT); | |
pinMode(BUTTON_LEFT, INPUT); | |
pinMode(BUTTON_RIGHT, INPUT); | |
} | |
void loop() { | |
unsigned long currentMillis = millis(); | |
game.handle_input(); | |
#if DEBUG | |
test_tomando_bien_inputs(); | |
#endif | |
if (currentMillis - previousMillis >= interval) { | |
previousMillis = currentMillis; | |
game.update(); | |
} | |
game.draw(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment