Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PROYECTO FINAL
JUEGO SNAKE
1BM4
Pérez Piña Jimena
14 de junio de 2021
Índice general
1. Introducción 2
2. Desarrollo 3
2.1. Planteamiento del problema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2. Justificación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.3. Propuesta de solución . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.4. Análisis y diseño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.4.1. Diagrama de Flujo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4.2. Diagramas de clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.4.3. Código del programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.4. Acción del programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3. Conclusión 62
1
Capítulo 1
Introducción
A continuación, se dará un resumen detallado de todos los procesos que se llevaron a cabo para concluir con
el juego de la serpiente se utilizaron 11 clases con sus respectivos códigos gracias a ellos logramos hacer funcionar
dicho programa no tan fluidamente como se deseaba desde el inicio.
Para lleva acabo todo este programa se utilizaron los principios de C++ todo el proceso que llevamos con los
vectores y parámetros sin ellos nunca se hubiese obtenido el funcionamiento adecuado y deseado del sistema.
La conexión de estas celdas hace que funcione todo de dicho modo se tiene que saber colocar la cantidad exacta
para que los fotogramas corran de forma correcta y que no haya fallas cuando se lleve a cabo dicho proceso
también son indispensables los vectores para llevar el orden correcto en el que cada objeto se formara a su debido
tiempo y dicho ritmo.
Y de dicho así se lleva una construcción de un objeto el cual se complementa con los distintos parámetros que
llevan en esto se cuenta el área diámetro y demás de objeto que se construirá, también hay ciertos parámetros
que no se pueden superar ya que esto violaría las normas de construcción del objeto gracias a todo esto y al
cumplir todos los requisitos se obtiene un alto rendimiento en el programa creado.
2
Capítulo 2
Desarrollo
3
2.2. Justificación
Este proyecto tiene la finalidad de resolver el problema que se ha planteado desde un inicio, hemos tomado en
consideración lo visto en clase para poder implementar la solución más eficaz. Antes que nada, hemos definido los
parámetros que tomaremos en cuenta para poder definir, con base en ellos, las distintas variables que el programa
contendrá.
Anteriormente hemos definido los principios que se utilizarán para poder solucionar este problema, es decir las
estructuras que incluiremos en nuestro programa.
Esta justificación servirá para que lleguemos a la solución del planteamiento de problema el cual está dicho pre-
viamente a esto y nos guiara a una forma rápida de dar solución hacia dicho enigma.
Anteriormente dimos a conocer cuáles son los principios necesarios para implementar una solución sobre dichos
problemas o enigmas en el cual usamos matrices vectores y sus respectivas 11 clases y llevar un orden sobre sus
columnas y reglones, todo esto ha sido asignado con ciertos parámetros para que puedan ser realizados de manera
correcta y ordenada.
4
2.3. Propuesta de solución
Para la propuesta de solución de este programa me he basado en información obtenida en libros, tutoriales
de internet y en las clases impartidas para la materia de POO.
Cuando escribimos un programa orientado a objetos, lo que hacemos es diseñar un conjunto de clases, desde las
cuales se crearán los objetos necesarios cuando el programa se ejecute. Cada una de estas clases incluye dos partes
fácilmente diferenciables: los atributos y los métodos. Los atributos definen el estado de cada uno de los objetos
de esa clase y los métodos, su comportamiento.
Para ello hemos utilizado lo anteriormente visto en clases y en otras prácticas:
Una clase (class) es un tipo de datos definido por el usuario. En C++, una estructura (struct) no es más
que una particularización de una clase en la que todos sus miembros tienen acceso público.
Uno de los contenedores más útiles de la biblioteca estándar es vector. Un vector, al igual que un array C,
es una secuencia de elementos de un tipo dado almacena- dos consecutivamente en memoria.
La asignación dinámica de memoria consiste en asignar la cantidad de memoria necesaria para almacenar
un objeto durante la ejecución del programa, en vez de hacerlo en el momento de la compilación del mismo.
Una clase equivale a la generalización de un tipo específico de objetos, pero cada objeto que construyamos
de esa clase tendrá sus propios datos.
Cuando escribimos un programa orientado a objetos, lo que hacemos es diseñar un conjunto de clases, desde las
cuales se crearán los objetos necesarios cuando el programa se ejecute. Cada una de estas clases incluye dos partes
fácilmente diferenciables: los atributos y los métodos. Los atributos definen el estado de cada uno de los objetos
de esa clase y los métodos, su comportamiento. . Los métodos son funciones miembro de la clase, que se ejecutan
en respuesta a un mensaje que recibe el objeto.
Un miembro declarado privado (private) es accesible solamente por los métodos de su propia clase. Esto significa
que no puede ser accedido por los métodos de cualquier otra clase, incluidas las subclases, o por cualquier otra
función externa (función no perteneciente a una clase), por ejemplo, por la función main.
Un constructor es un método especial de una clase que es llamado automática- mente siempre que se crea
un objeto de esa clase. Su función es iniciar el objeto.
La herencia es una de las características más importantes en la POO porque per- mite que una clase herede los
atributos y métodos de otra clase (los constructores no se heredan). Esta característica garantiza la reutilización
del código.
Con la herencia todas las clases están clasificadas en una jerarquía estricta. Cada clase tiene su superclase (la
clase superior en la jerarquía, también llamada clase base), y cada clase puede tener una o más subclases (las
clases inferiores en la jerarquía; también llamadas clases derivadas).
Las clases que están en la parte inferior en la jerarquía se dice que heredan de las clases que están en la parte
superior en la jerarquía.
El término heredar significa que las subclases disponen de todos los métodos y propiedades de su superclase. Este
mecanismo proporciona una forma rápida y cómoda de extender la funcionalidad de una clase. En C++ cada
clase puede tener una superclase (o clase base), lo que se denomina herencia simple, o dos o más superclases, lo
que se denomina herencia múltiple.
C++ permite el polimorfismo, que es la habilidad de los objetos de diferentes clases que están relacionados
mediante la herencia para responder en forma diferente al mismo mensaje (es decir, a la llamada de función
miembro). El mismo mensaje que se envía a muchos tipos de objetos diferentes toma "muchas formas", y de ahí
viene el término polimorfismo.
Por ejemplo, si la clase Rectangle se deriva de la clase Quadrilateral, un objeto Rectangle es una versión
más específica de un objeto Quadrilateral. Una operación (como el cálculo del perímetro o el área) que puede
realizarse en un objeto Quadrilateral también puede realizarse en un objeto Rectangle.
5
Cuando se hace una petición por medio de un apuntador de clase base (o referencia) , para utilizar una función
virtual, C++ elige la función sobrepuesta correcta en la clase derivada adecuada que está asociada con ese objeto.
Hay muchas veces en que una función miembro no virtual está definida en la clase base y sobrepuesta en una
clase derivada. Si a una función de estas se le llama mediante un apuntador de clase base al objeto de la clase
derivada, se utiliza la versión de la clase base. Si la función miembro se llama mediante un apuntador de la clase
derivada, se utiliza la versión de dicha clase derivada. Este comportamiento no es polimórfico.
Mediante el uso de funciones virtual y el polimorfismo, una llamada de función miembro puede causar que
sucedan diferentes acciones, dependiendo del tipo de objeto que recibe la llamada. Esto le da una capacidad
expresiva tremenda al programador.
El polimorfismo promueve la extensibilidad: el software que está escrito para llamar al comportamiento poli-
mórfico se escribe en forma independiente de los tipos de objetos a los cuales se envían los mensajes. Por lo tanto
los nuevos tipos de objetos que pueden responder a los mensajes existentes se pueden agregar a un sistemas, sin
modificar el sistema base.
WINDOW
sf::Cursor- Cursor define la apariencia de un cursor del sistema.
sf::Keyboard- Dar acceso al estado en tiempo real del teclado.
sf:Mouse- Dar acceso al estado del mouse en tiempo real.
sf:VideoMode- VideoMode define un modo de video (ancho, alto, bpp).
sf:Window- Window sirve como destino para el renderizado OpenGL.
GRAPHICS
sf::Color- Clase de utilidad para manipular colores RGBA.
sf::Font- Clase para cargar y manipular fuentes de caracteres.
sf::Image- Clase para cargar, manipular y guardar imágenes.
sf::RectangleShape- Forma especializada que representa un rectángulo.
sf::RenderTexture- Objetivo para la renderización 2D fuera de la pantalla en una textura.
sf::RenderWindow- Ventana que puede servir como destino para el dibujo 2D.
sf::Sprite- Representación dibujable de una textura, con sus propias transformaciones, color, etc.
sf::Text- Texto gráfico que se puede dibujar en un destino de renderizado.
sf::Texture- Imagen viva en la tarjeta gráfica que se puede utilizar para dibujar.
sf::View- Cámara 2D que define qué región se muestra en la pantalla.
6
SYSTEM
sf::String- Clase de utilidad para manipular cadenas.
sf::Time- Representa un valor de tiempo.
sf:: Vector2<t>-Clase de plantilla de utilidad para manipular vectores bidimensionales.
t= float (Vector2f), int (Vector2i), unsigned int (Vector2u)
7
2.4.1. Diagrama de Flujo
Inicio
Comenzar juego
Tecla W= UP (Arriba)
Tecla A= LEFT (Izquierda)
Tecla S=DOWN (Abajo)
Tecla D=RIGHT (Derecha)
Presionando teclas
’WASD’
Crecer la cola en 1
Terminar juego unidad
Aumentar puntaje
Mostrar puntaje final
Continuar jugando
Si
¿Desea jugar
nuevamente?
No
Fin
8
2.4.2. Diagramas de clases
BORDER
public Border
public ∼ Border
public void update(double deltaT)
BUTTON
private Text text
private ButtonState state
private Color iddleColor
private Color hoverColor
private Color pressedColor
public string getText
public Button
public ∼ Button
public void update(double deltaT)
public void draw(RenderWindow∗w)
public void checkState(Vector2f mousePos)
public bool isPressed
void setTextPos(Vector2f newPos)
void setText(string newText)
.
.
.
.
.
.
.
.
.
.
.
9
COLLIDER
private RectangleSghape ∗ body
public Collider
public ∼ Collider
public bool checkCollision(const Collider & other)
public Vector2f getHalfSize
public Vector2f getPos
ENTITY
private RectangleShape body
private Collider∗c
public Entity
public ∼ Entity
public virtual void draw (RenderWindow ∗w)
public virtual void update(double deltaT)
public Vector2f getPos
public Collider getCollider
public RectangleShape getBody
public getSize
public void setPos(Vector2f newPos)
public void setSize(Vector2f newSize)
public void setFillCol(Color newColor)
FRUIT
private bool collide
public Fruit
public ∼ Fruit
piblic void update(double deltaT)
public void setCollide(bool newCollide)
10
GAME
private RenderWindow window
private stack<State ∗>states
private double deltaT
private int score
public Game
public ∼ Game
public void start
private void update
private void draw
private void processStuff
private void run
private void initStates
HEAD
private DIRECTION dir
private double counter
private vector<Tail ∗>tail
private Texture tailTexture
public Head
public ∼ Head
public void draw(RenderWindow∗ w)
public void update(double deltaT)
public void keyboardInput
public void growTail
public void updateTails
public void headToTail
.
.
11
GAME STATE
private Head ∗ head
private Texture headTexture
private Fruit ∗fruit
private Texture fruitTexture
private vector<Border ∗>borders
private Texture borderTexture
private double counterHF
private double counterHT
private double counterHB
private double pauseCounter
private RectangleShape background
private Text pauseText
private Font font
private Texture scoreTexture
private Button∗ scoreButton
public GameState
public ∼ GameState
public void update(double deltaT)
public void draw(RenderWindow∗ w)
public void processStuff(double deltaT, Vector2f mousePos)
public void updateKeyBinds(double deltaT)
public initBorder
TAIL
public Tail
public ∼ Tail
public void update(double deltaT)
.
.
12
LOST STATE
private Font font
private int ∗score
private Text playerScore
private Button∗ playAgain
private RectangleShape backgroung
private Texture backgroundTexture
public LostState
public ∼ LostState
public void draw(RenderWindow∗ w)
public void update(double deltaT)
public void processStuff(double deltaT, Vector2f mousePos)
public void updateKeyBinds(double deltaT)
public void switchState
public void setScore(string newScore)
STATE
private bool quit
private int holderScore
public State
public ∼ State
public virtual void update(double deltaT)
public virtual void draw(RenderWindow∗ w)
public virtual void processStuff(double deltaT, Vector2f mousePos)
public virtual void updateKeyBinds(double deltaT)
public virtual void checkForQuit
public void setQuit(bool newQuit)
public bool getQuit
public void setHolderScore
public int getHolderScore
public virtual bool switchState
13
2.4.3. Código del programa
Border.h
#ifndef BORDER_H
#define BORDER_H
#include "Entity.h"
class Border :
public Entity
{
public:
Border(sf::Vector2f position, sf::Texture * texture);
~Border();
#endif
Border.cpp
#include "Border.h"
Border::~Border()
{
}
14
Button.h
#ifndef BUTTON_H
#define BUTTON_H
#include <SFML/Graphics.hpp>
#include "Entity.h"
#include <string>
bool isPressed();
private:
sf::Text text;
ButtonState state;
sf::Color idleColor;
15
sf::Color hoverColor;
sf::Color pressedColor;
};
#endif
Button.cpp
#include "Button.h"
this->state = IDLE;
this->idleColor = idleColor;
this->hoverColor = hoverColor;
this->pressedColor = pressedColor;
this->text.setFont(*font);
this->text.setCharacterSize(textSize);
this->text.setString(value);
this->text.setFillColor(textColor);
this->text.setPosition(Entity::getSize());
}
Button::~Button()
{
}
16
}
void Button::draw(sf::RenderWindow * w)
{
w->draw(Entity::getBody());
w->draw(this->text);
}
Hover, or Pressed
void Button::checkState(sf::Vector2f mousePos)
{
this->state = IDLE;
if (Entity::getBody().getGlobalBounds().contains(mousePos))
{
this->state = HOVER;
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
this->state = PRESSED;
}
}
switch (this->state)
{
case IDLE:
Entity::setFillCol(this->idleColor);
break;
case HOVER:
Entity::setFillCol(this->hoverColor);
break;
case PRESSED:
Entity::setFillCol(this->pressedColor);
break;
default:
Entity::setFillCol(sf::Color::Red);
}
17
}
bool Button::isPressed()
{
if (this->state == PRESSED)
{
return true;
}
return false;
}
Collider.h
#ifndef COLLIDER_H
#define COLLIDER_H
#include <SFML/Graphics.hpp>
class Collider
{
public:
18
Collider(sf::RectangleShape* body);
~Collider();
private:
sf::RectangleShape* body;
};
#endif
Collider.cpp
#include "Collider.h"
#include <cmath>
#include <iostream>
Collider::Collider(sf::RectangleShape* body)
:body(body)
{
}
Collider::~Collider()
{
}
19
if (abs(delta.x) - halfSize.x < 0 && abs(delta.y) - halfSize.y < 0)
{
return true;
}
return false;
}
Entity.h
#ifndef ENTITY_H
#define ENTITY_H
#include <SFML/Graphics.hpp>
#include "Collider.h"
class Entity
{
public:
Entity(sf::Vector2f position, sf::Texture * texture);
~Entity();
20
sf::Vector2f getPos();
Collider getCollider();
sf::RectangleShape getBody();
sf::Vector2f getSize();
private:
sf::RectangleShape body;
Collider * c;
};
#endif
Entity.cpp
#include "Entity.h"
#include <iostream>
Entity::~Entity()
{
std::cout << "Deallocating Collider" << std::endl;
21
delete c;
}
void Entity::draw(sf::RenderWindow * w)
{
w->draw(this->body);
}
sf::Vector2f Entity::getPos()
{
return this->body.getPosition();
}
Collider Entity::getCollider()
{
return *c;
}
sf::RectangleShape Entity::getBody()
{
return body;
}
sf::Vector2f Entity::getSize()
{
return body.getSize();
}
22
void Entity::setFillCol(sf::Color newColor)
{
this->body.setFillColor(newColor);
}
Fruit.h
#ifndef FRUIT_H
#define FRUIT_H
#include <SFML/Graphics.hpp>
#include "Entity.h"
#include <ctime>
#include <cstdlib>
private:
bool collide;
};
#endif
Fruit.cpp
#include "Fruit.h"
23
:Entity(position, texture)
{
this->collide = false;
srand(time(0));
}
Fruit::~Fruit()
{
}
Entity::setPos(sf::Vector2f(randNumX, randNumY));
this->collide = false;
}
}
Game.h
#ifndef GAME_H
#define GAME_H
#include <SFML/Graphics.hpp>
#include <stack>
24
#include <string>
#include "Entity.h"
#include "State.h"
#include "GameState.h"
#include "Head.h"
#include "Fruit.h"
#include "Button.h"
#include "LostState.h"
class Game
{
public:
Game();
~Game();
void start();
private:
void update();
void draw();
void processStuff();
void run();
void initStates();
private:
sf::RenderWindow window;
double deltaT;
int score;
};
25
#endif
Game.cpp
#include "Game.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
Game::Game() :
window(sf::VideoMode(800, 800), "SnakeGame", sf::Style::Close)
{
this->deltaT = 0;
this->initStates();
this->score = 0;
Game::~Game()
{
for (int i = 0; i < this->states.size(); i++)
{
delete states.top();
states.pop();
}
}
void Game::start()
{
this->run();
}
void Game::run()
{
sf::Clock clock;
while (this->window.isOpen())
26
{
this->deltaT = clock.restart().asSeconds();
sf::Event evnt;
while (this->window.pollEvent(evnt))
{
if (evnt.type == sf::Event::Closed)
{
this->window.close();
}
}
this->window.clear();
Game::update();
Game::processStuff();
Game::draw();
this->window.display();
}
void Game::update()
{
if (!this->states.empty())
{
this->states.top()->update(this->deltaT);
}
}
void Game::draw()
{
if (!this->states.empty())
{
this->states.top()->draw(&this->window);
}
27
}
void Game::processStuff()
{
if (!this->states.empty())
{
this->states.top()->processStuff(this->deltaT, sf::Vector2f(sf::Mouse::getPosition(this->window)));
if (this->states.top()->getQuit() == true)
{
this->score = this->states.top()->State::getHolderScore();
delete this->states.top();
this->states.pop();
}
}
if (this->states.size() <= 1)
{
this->states.top()->State::setHolderScore(this->score);
if (this->states.top()->switchState())
{
delete this->states.top();
this->states.top() = new LostState();
this->states.push(new GameState());
}
}
}
void Game::initStates()
{
this->states.push(new LostState());
this->states.push(new GameState());
}
GameState.h
28
#ifndef GAMESTATE_H
#define GAMESTATE_H
#include <SFML/Graphics.hpp>
#include <string>
#include "State.h"
#include "Entity.h"
#include "Fruit.h"
#include "Head.h"
#include "Border.h"
#include <vector>
#include "Button.h"
void initBorder();
private:
Head * head;
sf::Texture headTexture;
Fruit * fruit;
sf::Texture fruitTexture;
29
double counterHF;
double counterHT;
double counterHB;
double pauseCounter;
sf::RectangleShape background;
bool pause;
sf::Text pauseText;
sf::Font font;
sf::Texture scoreTexture;
Button* scoreButton;
};
#endif
GameState.cpp
#include "GameState.h"
#include <iostream>
GameState::GameState()
{
this->headTexture.loadFromFile("Sprites/head.png");
this->fruitTexture.loadFromFile("Sprites/fruit.png");
srand(time(0));
30
int randNum = rand() % 740 + 40;
this->initBorder();
this->counterHF = 0;
this->counterHT = 0;
this->counterHB = 0;
this->pauseCounter = 0;
this->background.setPosition(sf::Vector2f(0, 0));
this->background.setFillColor(sf::Color(100, 100, 100));
this->font.loadFromFile("Fonts/DejaVuSans.ttf");
this->pause = false;
this->pauseText.setString("Pause");
this->pauseText.setPosition(sf::Vector2f(300, 300));
this->pauseText.setFont(font);
this->pauseText.setCharacterSize(60);
this->scoreTexture.loadFromFile("Sprites/blank.png");
GameState::~GameState()
{
std::cout << "Deleting Head" << std::endl;
std::cout << "Deleting Fruit" << std::endl;
delete this->head;
31
delete this->fruit;
if (this->pause == false)
{
this->head->update(deltaT);
this->fruit->update(deltaT);
}
}
void GameState::draw(sf::RenderWindow * w)
{
this->background.setSize(sf::Vector2f(w->getSize().x, w->getSize().y));
w->draw(this->background);
this->head->draw(w);
this->fruit->draw(w);
for (int i = 0; i < this->borders.size(); i++)
{
this->borders[i]->draw(w);
}
if (pause == true)
{
w->draw(this->pauseText);
}
32
this->scoreButton->draw(w);
33
State::setQuit(true);
}
}
}
counterHF += deltaT;
counterHT += deltaT;
counterHB += deltaT;
void GameState::initBorder()
{
this->borderTexture.loadFromFile("Sprites/wall.png");
34
int amountNeeded = 83;
sf::Vector2f pos(0, 0);
int flag = 0;
if (i < 20)
{
pos.x += 40;
pos.y = 0;
}
else if (i < 60 && i >= 20)
{
if (i % 2 == 0)
{
pos.x = 0;
}
else
{
pos.x = 800;
}
if (flag == 2)
{
pos.y += 40;
flag = 0;
}
flag++;
}
else if (i >= 60)
{
if (i == 60)
{
pos.x = 0;
35
pos.y = 800;
}
else
{
pos.y = 800;
pos.x += 40;
}
}
}
}
Head.h
#ifndef HEAD_H
#define HEAD_H
#include <SFML/Graphics.hpp>
#include "Entity.h"
#include <vector>
#include "Tail.h"
private:
36
DIRECTION dir;
double counter;
std::vector <Tail *> tail;
sf::Texture tailTexture;
};
#endif
Head.cpp
#include "Head.h"
#include <iostream>
this->counter = 0;
this->tailTexture.loadFromFile("Sprites/tail.png");
Head::~Head()
{
for (int i = 0; i < tail.size(); i++)
{
delete tail[i];
}
}
37
void Head::draw(sf::RenderWindow * w)
{
w->draw(Entity::getBody());
for (int i = 0; i < tail.size(); i++)
{
w->draw(tail[i]->Entity::getBody());
}
}
38
void Head::keyboardInput()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
dir = UP;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
dir = RIGHT;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
dir = DOWN;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
dir = LEFT;
}
}
void Head::updateTails()
{
for (int i = tail.size() - 1; i > 0; i--)
{
tail[i]->setPos(tail[i - 1]->getPos());
}
if (tail.size() >= 1)
{
tail[0]->setPos(Entity::getPos());
}
}
void Head::growTail()
{
if (this->tail.size() == 0)
{
39
this->tail.push_back(new Tail(Entity::getPos(), &this->tailTexture));
}
else
{
this->tail.push_back(new Tail(this->tail[this->tail.size()-1]->getPos(), &this->tailTexture));
}
bool Head::headToTail()
{
if (this->tail.size() > 2)
{
for (int i = 1; i < this->tail.size(); i++)
{
if (Entity::getCollider().checkCollision(this->tail[i]->getCollider()) == true)
{
return true;
}
}
}
return false;
}
LostState.h
#ifndef LOSTSTATE_H
#define LOSTSTATE_H
#include <SFML/Graphics.hpp>
#include "State.h"
#include "Button.h"
#include <string>
class LostState :
public State
{
public:
40
LostState();
~LostState();
void update(double deltaT) override;
void draw(sf::RenderWindow * w) override;
void processStuff(double deltaT, sf::Vector2f mousePos) override;
void updateKeyBinds(double deltaT) override;
bool switchState() override;
void setScore(std::string newScore);
private:
sf::Font font;
int *score;
sf::Text playerScore;
Button* playAgain;
sf::RectangleShape background;
sf::Texture backgroundTexture;
};
#endif
LostState.cpp
#include "LostState.h"
#include <iostream>
LostState::LostState()
{
this->font.loadFromFile("Fonts/DejaVuSans.ttf");
this->backgroundTexture.loadFromFile("Sprites/lost.png");
this->score = nullptr;
this->playerScore.setPosition(sf::Vector2f(350, 200));
this->playerScore.setFillColor(sf::Color::Black);
41
this->playerScore.setFont(this->font);
this->playerScore.setCharacterSize(80);
this->background.setSize(sf::Vector2f(800, 800));
//this->background.setFillColor(sf::Color::Cyan);
this->background.setTexture(&this->backgroundTexture);
}
LostState::~LostState()
{
delete this->playAgain;
}
void LostState::draw(sf::RenderWindow * w)
{
w->draw(this->background);
w->draw(this->playerScore);
this->playAgain->draw(w);
}
42
void LostState::updateKeyBinds(double deltaT)
{
State::checkForQuit();
}
bool LostState::switchState()
{
return (this->playAgain->isPressed());
}
State.h
#ifndef STATE_H
#define STATE_H
#include <SFML/Graphics.hpp>
class State
{
public:
State();
~State();
virtual void update(double deltaT) = 0;
virtual void draw(sf::RenderWindow * w) = 0;
virtual void processStuff(double deltaT , sf::Vector2f mousePos) = 0;
virtual void updateKeyBinds(double deltaT) = 0;
virtual void checkForQuit();
void setQuit(bool newQuit);
bool getQuit() const;
void setHolderScore(int newScore);
int getHolderScore() const;
virtual bool switchState();
43
private:
bool quit;
int holderScore;
};
#endif
State.cpp
#include "State.h"
#include <iostream>
State::State()
{
this->quit = false;
this->holderScore = 0;
}
State::~State()
{
}
void State::checkForQuit()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
setQuit(true);
}
}
44
{
return this->quit;
}
bool State::switchState()
{
return false;
}
Tail.h
#ifndef TAIL_H
#define TAIL_H
#include <SFML/Graphics.hpp>
#include "Entity.h"
45
#endif
Tail.cpp
#include "Tail.h"
Tail::~Tail()
{
}
main.cpp
#include <iostream>
#include "Game.h"
int main()
{
Game snakeGame;
snakeGame.start();
return 0;
}
46
2.4.4. Acción del programa
Figura 2.1: Ventana creada por SFML, en la imagen observamos cuando el juego comienza y la cola es igual a
la cabeza
47
Figura 2.2: Ventana creada por SFML, podemos ver que ahora se ha comido una fruta y la cabeza y la cola son
de distintos colores
48
Figura 2.3: Puntuación vista en la ventana después de perder
49
Figura 2.4: Ejectuable del programa en la consola, vemos como ha comido 2 frutas y ha perdido el juego
50
Figura 2.5: Ventana creada por SFML puesta en pausa con ’P’
51
Figura 2.6: Ejectuable del programa (consola) cuando el juego es puesto en pausa
52
Figura 2.7: Ventana creada por SFML puesta en play después de pausar
53
Figura 2.8: Ejecutable del programa (consola) cuando se presiona ’P’ estando en pausa para poder continuar
54
Figura 2.9: Cambio de color cuando el mouse esta sobre el botón de jugar de nuevo
55
Figura 2.10: Ventana creada por SFML cuando se ha perdido
56
Figura 2.11: Ventana creada por SFML del programa cuando se han logrado 8 puntos y se ha perdido
57
Figura 2.12: Muestra el ejecutable cuando se ha perdido porque la cabeza de la vibora choco con el borde
58
Figura 2.13: Ventana creada por SFML del programa cuando se han logrado 6 puntos y se ha perdido
59
Figura 2.14: Muestra el ejecutable cuando se ha perdido porque la cabeza de la vibora choco con su cuerpo (co-
la)
60
Figura 2.15: Podemos ver como las colas se van arrastrando hacia atrás, además de como se va actualizando el
score
61
Capítulo 3
Conclusión
Podemos concluir que muchas de las aplicaciones prácticas de lo que nosotros aprendemos por medio de la
teoría solo se pueden implementar por medio de la misma práctica, es necesario además de comprender lo que
debemos de crear, trabajar en llegar a una solución lógica por medio de muchos pasos más sencillos.En este caso,
aprendí a utilizar correctamente la herencia como parte de un proyecto, además de aprender a investigar por mi
cuenta situaciones que necesito aprender para lograr un objetivo.
Aprendí a usar la composición y la herencia, además de como usar de manera más adecuada operadores, apun-
tadores, punteros, etc. También conocí más acerca de SFML, de los módulos Graphics, Window y System, y
algunos de sus usos y aplicaciones práticas más comunes.
Aprendimos a utilizar las clases y a identificar de mejor manera los parámetros y los métodos que las conforman,
así como a trabajar con objetos y a definir condiciones para que el programa funcione de manera autónoma. Uti-
lizamos funciones e instrucciones nuevas, por ende fue necesario investigar y realizar pruebas del funcionamiento
de estas.
62