La programació orientada a objectes (OOP) ens ajuda a organitzar el codi en estructures que són més fàcils de gestionar i entendre. En aquest projecte, crearem un joc de Pong utilitzant OOP, on definirem classes per representar objectes com el "Bat" (pala) i la "Ball" (pilota).
Una classe és una plantilla que defineix un tipus d'objecte, incloent les seves propietats (variables) i comportaments (funcions o mètodes).
class NomClasse {
// Variables i funcions aquí
};
A continuació es mostra com es declara la classe "Bat" per controlar la pala:
class Bat {
private:
int m_Length = 100; // Longitud de la pala
int m_Height = 10; // Altura de la pala
int m_XPosition; // Posició en l'eix X
int m_YPosition; // Posició en l'eix Y
public:
void moveRight(); // Moure a la dreta
void moveLeft(); // Moure a l'esquerra
};
En aquest exemple, m_Length, m_Height, m_XPosition, i m_YPosition són variables que emmagatzemen l'estat de la pala. Les funcions moveRight i moveLeft controlen el moviment de la pala.
L'encapsulació es refereix a l'ús de modificadors d'accés (com private i public) per protegir les dades internes d'una classe. Això significa que només les funcions que hem definit (públiques) poden accedir a les variables privades.
El polimorfisme permet que diferents classes puguin ser tractades com si fossin la mateixa classe base. La herència permet que una classe nova adquireixi les propietats i mètodes d'una classe existent, facilitant la reutilització del codi.
Per crear la classe "Bat", comencem amb el fitxer d'encapçalament Bat.h:
#pragma once
#include <SFML/Graphics.hpp>
using namespace sf;
class Bat {
private:
Vector2f m_Position; // Posició de la pala
RectangleShape m_Shape; // Forma visual de la pala
float m_Speed = 1000.0f; // Velocitat de la pala
bool m_MovingRight = false; // Indicador de moviment a la dreta
bool m_MovingLeft = false; // Indicador de moviment a l'esquerra
public:
Bat(float startX, float startY);
FloatRect getPosition();
RectangleShape getShape();
void moveLeft();
void moveRight();
void stopLeft();
void stopRight();
void update(Time dt);
};
El constructor inicialitza la pala amb una posició determinada:
Bat::Bat(float startX, float startY) : m_Position(startX, startY) {
m_Shape.setSize(sf::Vector2f(50, 5)); // Configura la mida de la pala
m_Shape.setPosition(m_Position); // Col·loca la pala a la pantalla
}
Aquí es defineixen les funcions que controlen el moviment de la pala:
void Bat::moveLeft() {
m_MovingLeft = true; // Activa el moviment a l'esquerra
}
void Bat::moveRight() {
m_MovingRight = true; // Activa el moviment a la dreta
}
void Bat::update(Time dt) {
if (m_MovingLeft) {
m_Position.x -= m_Speed * dt.asSeconds(); // Mou la pala a l'esquerra
}
if (m_MovingRight) {
m_Position.x += m_Speed * dt.asSeconds(); // Mou la pala a la dreta
}
m_Shape.setPosition(m_Position); // Actualitza la posició de la pala a la pantalla
}
La funció principal del joc gestiona el bucle de joc i les entrades de l'usuari:
int main() {
RenderWindow window(VideoMode(1920, 1080), "Pong", Style::Fullscreen);
Bat bat(1920 / 2, 1080 - 20); // Crea la pala al centre de la pantalla
Ball ball(1920 / 2, 0); // Crea la pilota a la part superior
while (window.isOpen()) {
// Gestionar els esdeveniments
// Actualitzar la pala i la pilota
// Dibuixar la pala i la pilota
}
return 0;
}
El codi següent gestiona les entrades de l'usuari per controlar la pala:
Event event;
while (window.pollEvent(event)) {
if (event.type == Event::Closed)
window.close();
}
// Controlar el moviment de la pala
if (Keyboard::isKeyPressed(Keyboard::Left)) {
bat.moveLeft();
} else {
bat.stopLeft();
}
if (Keyboard::isKeyPressed(Keyboard::Right)) {
bat.moveRight();
} else {
bat.stopRight();
}
El bucle de joc actualitza i dibuixa els elements del joc:
Time dt = clock.restart(); // Actualitza el temps
bat.update(dt); // Actualitza la pala
window.clear(); // Neteja la pantalla
window.draw(bat.getShape()); // Dibuixa la pala
window.display(); // Mostra el contingut actualitzat
En aquesta part, hem cobert les bases de la programació orientada a objectes amb C++ a través del joc de Pong. Hem après a crear classes, controlar els seus atributs i comportaments, i gestionar la lògica del joc a la funció principal. La programació orientada a objectes facilita la creació de jocs més complexos i organitzats.
En aquest pas, implementarem la classe Ball i afegirem la detecció de collisions i puntuació per completar el joc de Pong. La classe Ball serà responsable de la lògica de moviment de la pilota, així com de la seva interacció amb els límits de la pantalla i la pala del jugador.
Ball: Crearem una nova classe per representar la pilota.Ball: Aprendrem a instanciar la classe i a utilitzar les seves funcions.La classe Ball tindrà atributs similars als de la classe Bat, incloent la posició, la forma i la velocitat. A més, gestionarà la seva direcció de moviment amb dues variables: m_DirectionX i m_DirectionY.
Algunes de les funcions que implementarem inclouen:
Ball(float startX, float startY): Constructor per inicialitzar la pilota a una posició específica.void update(Time dt): Actualitza la posició de la pilota en funció del temps transcorregut.void reboundSides(): Inverteix la direcció horitzontal de la pilota quan col·lisiona amb un costat de la pantalla.void reboundBatOrTop(): Inverteix la direcció vertical de la pilota quan col·lisiona amb la pala o la part superior de la pantalla.void reboundBottom(): Restaura la pilota a la part superior de la pantalla quan toca el fons.La detecció de colisions es realitzarà mitjançant la funció intersects de SFML, que ens permetrà comprovar si la pilota ha col·lisionat amb la pala o amb els límits de la finestra del joc.
El bucle principal del joc s'actualitzarà per manejar les col·lisions i la puntuació:
// Actualitzar la pilota i la pala
bat.update(dt);
ball.update(dt);
// Comprovar col·lisions
if (ball.getPosition().intersects(bat.getPosition())) {
ball.reboundBatOrTop(); // Col·lisió amb la pala
score++; // Incrementar puntuació
}
Amb la implementació de la classe Ball i la detecció de colisions, el joc de Pong estarà a punt. Els jugadors podran jugar, colpejar la pilota amb la pala, marcar punts i experimentar la dinàmica del joc. En el següent capítol, continuarem amb més funcionalitats i optimitzacions per millorar l'experiència del jugador.