Skip to content

Instantly share code, notes, and snippets.

@jnrdrgz
Last active June 25, 2020 19:28
Show Gist options
  • Save jnrdrgz/33daa6897dc5e13830c6438d1000eb9f to your computer and use it in GitHub Desktop.
Save jnrdrgz/33daa6897dc5e13830c6438d1000eb9f to your computer and use it in GitHub Desktop.
arduino 4_1
////////////////////////////////////////////////////
//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