From b1785cf5f1cf8138551db704ad83f71b58354773 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Wed, 21 Aug 2024 07:35:52 +0200 Subject: [PATCH] Primer commit --- .gitignore | 2 + Makefile | 5 ++ resources/pelota.png | Bin 0 -> 542 bytes source/ball.cpp | 97 +++++++++++++++++++++++++ source/ball.h | 36 ++++++++++ source/defines.h | 10 +++ source/main.cpp | 168 +++++++++++++++++++++++++++++++++++++++++++ source/sprite.cpp | 67 +++++++++++++++++ source/sprite.h | 44 ++++++++++++ source/texture.cpp | 101 ++++++++++++++++++++++++++ source/texture.h | 40 +++++++++++ 11 files changed, 570 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 resources/pelota.png create mode 100644 source/ball.cpp create mode 100644 source/ball.h create mode 100644 source/defines.h create mode 100644 source/main.cpp create mode 100644 source/sprite.cpp create mode 100644 source/sprite.h create mode 100644 source/texture.cpp create mode 100644 source/texture.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5a6f96 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.exe +*.dll \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fd037cc --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +source := source/*.cpp +executable_name := pelota + +windows: + g++ $(source) -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lSDL2_image -o $(executable_name).exe \ No newline at end of file diff --git a/resources/pelota.png b/resources/pelota.png new file mode 100644 index 0000000000000000000000000000000000000000..ea0dd27a02f10ce9cca07e64788f46a7061a2a43 GIT binary patch literal 542 zcmV+(0^$9MP)Px$*hxe|R9J=GSy7h5APB^~J&_(IJ!X0ob0zktbSXgs#&pxpU#kwtj3l)Q96&_8 zm-75P*9!Mi;I^*Gv);mzGtRXF0055x0K@qS6vx9q?U5rQYGZS)u;h$O&g!@a*4nG^ z|3rzc`Ci4n{G|L+N{C-N{s{lZK|FbB%~k+yZ41(odohmkw;)>vIZDoZDNri`j~bo? zy~;|^1_10Ld5c4kxoAat7Dx_wmDL)cmZ(-7D~44_tw=m(M1;K}nN9i=5fQ zu|0)b_bU-x*+o3J31G~{6vtdEaAi|UNmKVok$BFQOT97Vr5*7%oAlKbj&5`mo(1Z4 zk(RioXiMcDA+%hN^ddQ*^G~e-fWPD;0j)ysiJ)C#$?q+WR+0F6O%RKJbHpM}>bYb; z((gQLqfX*NXf9Xpq$!alXS|oP8z{PI&QIT2M=i=v8}wVJ$IAek5fYyyq=+vjY4 g+IZ`l*7J_`3)S#oeQ>=*YXATM07*qoM6N<$f-HdcJpcdz literal 0 HcmV?d00001 diff --git a/source/ball.cpp b/source/ball.cpp new file mode 100644 index 0000000..2bed89e --- /dev/null +++ b/source/ball.cpp @@ -0,0 +1,97 @@ +#include "ball.h" +#include "defines.h" + +// Constructor +Ball::Ball(int x, int y, int w, int h, int vx, int vy, Texture *texture) +{ + this->x = x; + this->y = y; + this->w = w; + this->h = h; + this->vx = vx; + this->vy = vy; + sprite = new Sprite(texture); + sprite->setPos({x, y}); + sprite->setSize(w, h); + sprite->setClip({0, 0, 24, 24}); + color = {255, 255, 255}; +} + +// Destructor +Ball::~Ball() +{ + if (sprite) + { + delete sprite; + } +} + +// Actualiza la lógica de la clase +void Ball::update() +{ + const int luckyX = (rand() % 2) + 1; + const int luckyY = (rand() % 2) + 1; + + bool collision = false; + + // Actualiza la posición + x += vx; + y += vy; + + // Comprueba las colisiones con el borde de la ventana + if (x < 0) + { + x = 0; + vx = luckyX; + collision = true; + } + + if (x + w > SCREEN_WIDTH) + { + x = SCREEN_WIDTH - w; + vx = -luckyX; + collision = true; + } + + if (y < 0) + { + y = 0; + vy = luckyY; + collision = true; + } + + if (y + h > SCREEN_HEIGHT) + { + y = SCREEN_HEIGHT - h; + vy = -luckyY; + collision = true; + } + + if (collision) + { + color = {rand() % 255, rand() % 255, rand() % 255}; + } + + // Actualiza la posición del sprite + sprite->setPos({x, y}); + sprite->update(); +} + +// Pinta la clase +void Ball::render() +{ + sprite->setColor(color.r, color.g, color.b); + sprite->render(); +} + +// Establece el valor de la velocidad +void Ball::setVx(int value) +{ + vx = value; +} + +// Establece el valor de la velocidad +void Ball::setVy(int value) +{ + vy = value; +} \ No newline at end of file diff --git a/source/ball.h b/source/ball.h new file mode 100644 index 0000000..12266d8 --- /dev/null +++ b/source/ball.h @@ -0,0 +1,36 @@ +#pragma once + +#include "sprite.h" +#include "texture.h" +#include "defines.h" + +class Ball +{ +private: + Sprite *sprite; // Sprite para pintar la clase + int x; // Posición x + int y; // Posición y + int w; // Ancho + int h; // Alto + int vx, vy; // Velocidad + color_t color; // Color de la pelota + +public: + // Constructor + Ball(int x, int y, int w, int h, int vx, int vy, Texture *texture); + + // Destructor + ~Ball(); + + // Actualiza la lógica de la clase + void update(); + + // Pinta la clase + void render(); + + // Establece el valor de la velocidad + void setVx(int value); + + // Establece el valor de la velocidad + void setVy(int value); +}; \ No newline at end of file diff --git a/source/defines.h b/source/defines.h new file mode 100644 index 0000000..e6a118d --- /dev/null +++ b/source/defines.h @@ -0,0 +1,10 @@ +#pragma once + +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 240 +#define NUM_BALLS 100 + +struct color_t +{ + int r,g,b; +}; \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp new file mode 100644 index 0000000..42dc437 --- /dev/null +++ b/source/main.cpp @@ -0,0 +1,168 @@ +#include +#include +#include "texture.h" +#include "ball.h" +#include "defines.h" +#include + +SDL_Window *window = NULL; +SDL_Renderer *renderer = NULL; +SDL_Event *event; +Texture *texture = nullptr; +Ball *ball[NUM_BALLS]; + +bool shouldExit = false; +Uint32 ticks = 0; + +bool init() +{ + // Initialization flag + bool success = true; + + // Initialize SDL + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError()); + success = false; + } + else + { + // Set texture filtering to linear + if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) + { + printf("Warning: Linear texture filtering not enabled!"); + } + + // Create window + window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2, SDL_WINDOW_SHOWN); + if (window == NULL) + { + printf("Window could not be created! SDL Error: %s\n", SDL_GetError()); + success = false; + } + else + { + // Create renderer for window + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + if (renderer == NULL) + { + printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError()); + success = false; + } + else + { + // Initialize renderer color + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); + + // Initialize PNG loading + int imgFlags = IMG_INIT_PNG; + if (!(IMG_Init(imgFlags) & imgFlags)) + { + printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError()); + success = false; + } + + SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT); + } + } + } + + event = new SDL_Event(); + + texture = new Texture(renderer, "resources/pelota.png"); + for (int i = 0; i < NUM_BALLS; ++i) + { + ball[i] = new Ball(rand() % SCREEN_WIDTH, rand() % SCREEN_HEIGHT, 24, 24, 1, 1, texture); + } + + ticks = SDL_GetTicks(); + + return success; +} + +void close() +{ + // Destroy window + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + window = NULL; + renderer = NULL; + + if (event) + { + delete event; + } + + if (texture) + { + delete texture; + } + + for (int i = 0; i < NUM_BALLS; ++i) + { + if (ball[i]) + { + delete ball[i]; + } + } + + // Quit SDL subsystems + IMG_Quit(); + SDL_Quit(); +} + +void checkEvents() +{ + // Comprueba los eventos que hay en la cola + while (SDL_PollEvent(event) != 0) + { + // Evento de salida de la aplicación + if (event->type == SDL_QUIT) + { + shouldExit = true; + break; + } + } +} + +void update() +{ + if (SDL_GetTicks() - ticks > 15) + { + ticks = SDL_GetTicks(); + + for (int i = 0; i < NUM_BALLS; ++i) + { + ball[i]->update(); + } + } +} + +void render() +{ + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + + for (int i = 0; i < NUM_BALLS; ++i) + { + ball[i]->render(); + } + + SDL_RenderPresent(renderer); +} + +int main(int argc, char *args[]) +{ + init(); + + while (!shouldExit) + { + update(); + checkEvents(); + render(); + } + + close(); + + return 0; +} \ No newline at end of file diff --git a/source/sprite.cpp b/source/sprite.cpp new file mode 100644 index 0000000..d1d4aa5 --- /dev/null +++ b/source/sprite.cpp @@ -0,0 +1,67 @@ +#include "sprite.h" + +// Constructor +Sprite::Sprite(Texture *texture) +{ + this->texture = texture; + pos = {0, 0, 0, 0}; + clip = {0, 0, 0, 0}; + frame = 0; + numFrames = 3; + animationSpeed = 20; + animationCounter = 0; +} + +// Destructor +Sprite::~Sprite() +{ +} + +// Establece la posición del sprite +void Sprite::setPos(SDL_Point pos) +{ + this->pos.x = pos.x; + this->pos.y = pos.y; +} + +// Pinta el sprite +void Sprite::render() +{ + texture->render(&clip, &pos); +} + +// Actualiza la lógica de la clase +void Sprite::update() +{ + animationCounter++; + if (animationCounter % animationSpeed == 0) + { + animate(); + } +} + +// Establece el rectangulo de la textura que se va a pintar +void Sprite::setClip(SDL_Rect clip) +{ + this->clip = clip; +} + +// Establece el tamaño del sprite +void Sprite::setSize(int w, int h) +{ + this->pos.w = w; + this->pos.h = h; +} + +// Anima el sprite +void Sprite::animate() +{ + frame = (frame + 1) % numFrames; + clip.x = frame * pos.w; +} + +// Modulación de color +void Sprite::setColor(int r, int g, int b) +{ + texture->setColor(r, g, b); +} \ No newline at end of file diff --git a/source/sprite.h b/source/sprite.h new file mode 100644 index 0000000..761dc45 --- /dev/null +++ b/source/sprite.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include "texture.h" + +class Sprite +{ +private: + Texture *texture; // Textura con los gráficos del sprite + SDL_Rect pos; // Posición y tamaño del sprite + SDL_Rect clip; // Parte de la textura que se va a dibujar + int frame; // Frame a dibujar de la textura definido en clip + int numFrames; // Numero total de frames + int animationSpeed; // Velocidad de animación + int animationCounter; // Contador para la animación + + // Anima el sprite + void animate(); + +public: + // Constructor + Sprite(Texture *texture); + + // Destructor + ~Sprite(); + + // Establece la posición del sprite + void setPos(SDL_Point pos); + + // Pinta el sprite + void render(); + + // Actualiza la lógica de la clase + void update(); + + // Establece el rectangulo de la textura que se va a pintar + void setClip(SDL_Rect clip); + + // Establece el tamaño del sprite + void setSize(int w, int h); + + // Modulación de color + void setColor(int r, int g, int b); +}; \ No newline at end of file diff --git a/source/texture.cpp b/source/texture.cpp new file mode 100644 index 0000000..2469a17 --- /dev/null +++ b/source/texture.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include "texture.h" + +Texture::Texture(SDL_Renderer *renderer) +{ + this->renderer = renderer; + texture = NULL; + width = 0; + height = 0; +} + +Texture::Texture(SDL_Renderer *renderer, std::string filepath) +{ + this->renderer = renderer; + texture = NULL; + width = 0; + height = 0; + loadFromFile(filepath); +} + +Texture::~Texture() +{ + free(); +} + +bool Texture::loadFromFile(std::string path) +{ + // Get rid of preexisting texture + free(); + + // The final texture + SDL_Texture *newTexture = NULL; + + // Load image at specified path + SDL_Surface *loadedSurface = IMG_Load(path.c_str()); + if (loadedSurface == NULL) + { + printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError()); + } + else + { + // Color key image + SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF)); + + // Create texture from surface pixels + newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface); + if (newTexture == NULL) + { + printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError()); + } + else + { + // Get image dimensions + width = loadedSurface->w; + height = loadedSurface->h; + } + + // Get rid of old loaded surface + SDL_FreeSurface(loadedSurface); + } + + // Return success + texture = newTexture; + return texture != NULL; +} + +void Texture::free() +{ + // Free texture if it exists + if (texture != NULL) + { + SDL_DestroyTexture(texture); + texture = NULL; + width = 0; + height = 0; + } +} + +void Texture::render(SDL_Rect *src, SDL_Rect *dst) +{ + // Render to screen + SDL_RenderCopy(renderer, texture, src, dst); +} + +int Texture::getWidth() +{ + return width; +} + +int Texture::getHeight() +{ + return height; +} + +// Modulación de color +void Texture::setColor(int r, int g, int b) +{ + SDL_SetTextureColorMod(texture, r, g, b); +} diff --git a/source/texture.h b/source/texture.h new file mode 100644 index 0000000..efc85ab --- /dev/null +++ b/source/texture.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +// Texture wrapper class +class Texture +{ +private: + SDL_Renderer *renderer; + SDL_Texture *texture; + + // Image dimensions + int width; + int height; + +public: + // Initializes variables + Texture(SDL_Renderer *renderer); + Texture(SDL_Renderer *renderer, std::string filepath); + + // Deallocates memory + ~Texture(); + + // Loads image at specified path + bool loadFromFile(std::string path); + + // Deallocates texture + void free(); + + // Renders texture at given point + void render(SDL_Rect *src = nullptr, SDL_Rect *dst = nullptr); + + // Gets image dimensions + int getWidth(); + int getHeight(); + + // Modulación de color + void setColor(int r, int g, int b); +};