Conversation with Merlin [email protected] · Sat Dec 23 2023

#ifndef BUTTON_H #define BUTTON_H

#include "Component.h" #include <SDL2/SDL.h> #include

namespace cwing { class Button : public Component { public: static Button* getInstance(int x, int y, int w, int h, std::string txt); void mouseDown(const SDL_Event&); void mouseUp(const SDL_Event&); void draw() const; virtual void perform(Button* source) {} ~Button(); protected: Button(int x, int y, int w, int h, std::string txt); private: std::string text; SDL_Texture* texture; SDL_Texture* upIcon, *downIcon; bool isDown = false; }; }

#endif

#ifndef COMPONENT_H #define COMPONENT_H

#include <SDL2/SDL.h>

namespace cwing { class Component { public: virtual ~Component(); virtual void mouseDown(const SDL_Event&) {} virtual void mouseUp(const SDL_Event&) {} virtual void keyDown(const SDL_Event&) {} virtual void keyUp(const SDL_Event&) {} virtual void draw() const = 0; const SDL_Rect& getRect() const { return rect; } protected: Component(int x, int y, int w, int h); private: SDL_Rect rect; Component(const Component&) = delete; const Component& operator=(const Component&) = delete; }; } #endif

=========================== #ifndef CONSTANTS_H #define CONSTANTS_H

#include

namespace constants { //gResPath-contains the relative path to your resources. const std::string gResPath = "./resources/"; }

#endif

// GameEngine.h #ifndef GAMEENGINE_H #define GAMEENGINE_H

#include <SDL2/SDL.h> #include

class Sprite; // Forward declaration

class GameEngine { public: GameEngine(); ~GameEngine();

bool init(const char* title, int width, int height); void cleanup(); void run(); SDL_Renderer* getRenderer(); void addSprite(Sprite* sprite); void removeSprite(Sprite* sprite);

private: SDL_Window* window; SDL_Renderer* renderer; std::vector<Sprite*> sprites;

bool isRunning; void processEvents(); void update(); void render();

};

#endif

================================ #ifndef LABEL_H #define LABEL_H

#include "Component.h" #include #include <SDL2/SDL.h>

namespace cwing {

class Label: public Component { public: static Label* getInstance(int x, int y, int w, int h, std::string txt); void draw() const; std::string getText() const; void setText(std::string newText); ~Label(); protected: Label(int x, int y, int w, int h, std::string txt); private: std::string text; SDL_Texture* texture; };

} #endif

// PlayerSprite.h #pragma once

#include "Sprite.h"

class PlayerSprite : public Sprite { public: // Constructor for PlayerSprite PlayerSprite(SDL_Renderer* renderer, int x, int y, int width, int height);

// Destructor ~PlayerSprite(); // Override update and render void update() override; void render() override;

};

================================= #ifndef SESSION_H #define SESSION_H

#include #include "Component.h"

namespace cwing {

class Session { public: Session(); void add(Component* c); void run(); ~Session(); private: std::vector<Component*> comps; };

} #endif

// Sprite.h #ifndef SPRITE_H #define SPRITE_H using namespace std; #include #include <SDL2/SDL.h>

class GameEngine; // Forward declaration

class Sprite { public: Sprite(SDL_Renderer* renderer, const string& imagePath, int x, int y, int width, int height); virtual ~Sprite();

virtual void update() = 0; virtual void render() = 0; void draw(); private: int positionx; int positiony;

protected: GameEngine* engine;

};

#endif

====================================== #ifndef SYSTEM_H #define SYSTEM_H

#include <SDL2/SDL.h> #include <SDL2/SDL_ttf.h> #include

namespace cwing {

class System { public: System(); ~System(); SDL_Renderer* get_ren() const; TTF_Font* get_font() const; private: SDL_Window* win; SDL_Renderer* ren; TTF_Font* font; }; extern System sys;

}

#endif

#include "Constants.h" #include "Button.h" #include <SDL2/SDL_ttf.h> #include "System.h" #include <SDL2/SDL_image.h>

namespace cwing {

Button::Button(int x, int y, int w, int h, std::string txt):Component(x,y,w,h) { SDL_Surface* surf = TTF_RenderText_Solid(sys.get_font(), txt.c_str(), { 0,0,0 }); texture = SDL_CreateTextureFromSurface(sys.get_ren(), surf); SDL_FreeSurface(surf); upIcon = IMG_LoadTexture(sys.get_ren(), (constants::gResPath + "images/UppKnapp.png").c_str() ); downIcon = IMG_LoadTexture(sys.get_ren(), (constants::gResPath + "images/NerKnapp.png").c_str() ); } Button::~Button() { SDL_DestroyTexture(texture); SDL_DestroyTexture(upIcon); SDL_DestroyTexture(downIcon); } Button* Button::getInstance(int x, int y, int w, int h, std::string txt) { return new Button(x, y, w, h, txt); } void Button::mouseDown(const SDL_Event& eve) { SDL_Point p = { eve.button.x, eve.button.y }; if (SDL_PointInRect(&p, &getRect())) isDown = true; } void Button::mouseUp(const SDL_Event& eve) { SDL_Point p = { eve.button.x, eve.button.y }; if (SDL_PointInRect(&p, &getRect())) perform(this); isDown = false; } void Button::draw() const { if (isDown) SDL_RenderCopy(sys.get_ren(), downIcon, NULL, &getRect()); else SDL_RenderCopy(sys.get_ren(), upIcon, NULL, &getRect()); SDL_RenderCopy(sys.get_ren(), texture, NULL, &getRect()); }

}

#include "Component.h"

namespace cwing {

Component::Component(int x, int y, int w, int h) :rect{ x,y,w,h } { } Component::~Component() { }

}

#include "GameEngine.h" #include "PlayerSprite.h"

int main() { GameEngine game; game.init("My Game", 800, 600);

PlayerSprite* player = new PlayerSprite(game.getRenderer(), 400, 300, 800, 600); game.addSprite(player); game.run(); game.cleanup(); return 0;

}

======================================= // GameEngine.cpp #include "GameEngine.h" #include "Sprite.h"

#include

GameEngine::GameEngine() : window(nullptr), renderer(nullptr), isRunning(false) {}

GameEngine::~GameEngine() { cleanup(); }

bool GameEngine::init(const char* title, int width, int height) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { return false; }

window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN); if (!window) { return false; } renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (!renderer) { return false; } isRunning = true; return true;

}

void GameEngine::cleanup() { for (auto& sprite : sprites) { delete sprite; } sprites.clear();

if (renderer) { SDL_DestroyRenderer(renderer); renderer = nullptr; } if (window) { SDL_DestroyWindow(window); window = nullptr; } SDL_Quit();

}

void GameEngine::run() { while (isRunning) { processEvents(); update(); render(); } }

SDL_Renderer* GameEngine::getRenderer() { return renderer; }

void GameEngine::addSprite(Sprite* sprite) { sprites.push_back(sprite); }

void GameEngine::removeSprite(Sprite* sprite) { sprites.erase(std::remove(sprites.begin(), sprites.end(), sprite), sprites.end()); }

void GameEngine::processEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { isRunning = false; } } }

void GameEngine::update() { for (auto& sprite : sprites) { sprite->update(); } }

void GameEngine::render() { SDL_RenderClear(renderer);

for (auto& sprite : sprites) { sprite->render(); } SDL_RenderPresent(renderer);

}

#include "Label.h" #include <SDL2/SDL_ttf.h> #include "System.h" #include #include

using namespace std;

namespace cwing {

Label* Label::getInstance(int x, int y, int w, int h, std::string txt) { return new Label(x, y, w, h, txt); } Label::Label(int x, int y, int w, int h, std::string txt): Component(x,y,w,h), text(txt) { SDL_Surface* surf = TTF_RenderText_Solid(sys.get_font(), text.c_str(), { 0,0,0 }); texture = SDL_CreateTextureFromSurface(sys.get_ren(), surf); SDL_FreeSurface(surf); } void Label::draw() const { SDL_RenderCopy(sys.get_ren(), texture, NULL, &getRect()); } Label::~Label() { SDL_DestroyTexture(texture); } string Label::getText() const { return text; } void Label::setText(std::string newText) { text = newText; SDL_DestroyTexture(texture); SDL_Surface* surf = TTF_RenderText_Solid(sys.get_font(), text.c_str(), { 0,0,0 }); texture = SDL_CreateTextureFromSurface(sys.get_ren(), surf); SDL_FreeSurface(surf); }

}

// PlayerSprite.cpp #include "PlayerSprite.h"

PlayerSprite::PlayerSprite(SDL_Renderer* renderer, int x, int y, int width, int height) : Sprite(renderer,"test.jpg", x, y, width, height) {

}

PlayerSprite::~PlayerSprite() {

}

void PlayerSprite::update() { }

void PlayerSprite::render() { }

=================================== #include "Session.h" #include <SDL2/SDL.h> #include "System.h"

#include

namespace cwing {

Session::Session(){ std::cout << "*** Session::Session()\n"; } void Session::add(Component* c) { comps.push_back(c); } void Session::run() { bool quit = false; while (!quit) { SDL_Event eve; while (SDL_PollEvent(&eve)) { switch (eve.type) { case SDL_QUIT: quit = true; break; case SDL_MOUSEBUTTONDOWN: for (Component* c : comps) c->mouseDown(eve); break; case SDL_MOUSEBUTTONUP: for (Component* c : comps) c->mouseUp(eve); break; case SDL_KEYDOWN: for (Component* c : comps) c->keyDown(eve); break; case SDL_KEYUP: for (Component* c : comps) c->keyUp(eve); break; } // switch } // inre while SDL_SetRenderDrawColor(sys.get_ren(), 255, 255, 255, 255); SDL_RenderClear(sys.get_ren()); for (Component* c : comps) c->draw(); SDL_RenderPresent(sys.get_ren()); } //yttre while } Session::~Session() { }

}

// Sprite.cpp #include "Sprite.h" #include "Constants.h"

using namespace std;

Sprite::Sprite(SDL_Renderer* renderer, const string& imagePath, int x, int y, int width, int height){ positionx = x; positiony = y;

}

Sprite::~Sprite() { }

void Sprite::update() { // Default implementation for base Sprite class }

void Sprite::draw() { }

======================================= #include "Constants.h" #include "System.h" #include <SDL2/SDL.h> #include

namespace cwing {

System::System() { std::cout << "*** System::System()\n"; SDL_Init(SDL_INIT_EVERYTHING); win = SDL_CreateWindow("Cwing", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 400, 0); ren = SDL_CreateRenderer(win, -1, 0); TTF_Init(); font = TTF_OpenFont( (constants::gResPath + "fonts/arial.ttf").c_str(), 36); std::cout << "resPath: " << constants::gResPath << std::endl; } System::~System() { std::cout << "*** System::~System()\n"; TTF_CloseFont(font); TTF_Quit(); SDL_DestroyWindow(win); SDL_DestroyRenderer(ren); SDL_Quit(); } SDL_Renderer* System::get_ren() const { return ren; } TTF_Font* System::get_font() const { return font; } System sys; // Statiskt globalt objekt (definierad utanför funktioner.)

}

Modify the code to make a jumping ball game and adjust the gameEngine

To create a jumping ball game using the provided code, we'll need to make some modifications and additions to the existing classes and functions. Here's an overview of the necessary changes:

  1. Modify the Sprite class to represent the ball character, including attributes for position, velocity, and functions for jumping and collision detection.
  2. Update the GameEngine class to handle the game loop, including logic for updating and rendering the ball sprite, as well as handling user input for jumping.
  3. Add a new class or modify the PlayerSprite class to handle the ball's behavior, such as jumping, gravity, and collision detection.
  4. Utilize the Session class to manage the game session and handle inputs for jumping.

Let's go through these steps and make the necessary modifications:

1. Modify the Sprite Class

// Sprite.h class Sprite { public: // ... (existing code) // Add attributes for velocity and gravity int velocityY; const int gravity = 1; // Add jump functionality void jump(); // Add collision detection bool checkCollision(const SDL_Rect& otherRect); };

2. Update the GameEngine Class

// GameEngine.h class GameEngine { public: // ... (existing code) void processInput(); void updateBall(); void checkCollisions(); };
// GameEngine.cpp void GameEngine::processInput() { // Handle input for jumping SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_SPACE) { // Trigger ball jump // Example: player->jump(); } } } } void GameEngine::updateBall() { // Update ball position and velocity for (auto& sprite : sprites) { if (dynamic_cast<PlayerSprite*>(sprite)) { sprite->update(); } } } void GameEngine::checkCollisions() { // Check collisions with other sprites or boundaries // Example: ballCollision = player->checkCollision(otherSpriteRect); } // Modify other existing functions as needed

3. Add or Modify the PlayerSprite Class

// PlayerSprite.h class PlayerSprite : public Sprite { public: PlayerSprite(SDL_Renderer* renderer, int x, int y, int width, int height); ~PlayerSprite(); void update() override; void render() override; void jump(); };
// PlayerSprite.cpp PlayerSprite::PlayerSprite(SDL_Renderer* renderer, int x, int y, int width, int height) : Sprite(renderer, "ball_image.jpg", x, y, width, height) { // Initialize player-specific attributes velocityY = 0; } void PlayerSprite::update() { // Update player position and handle gravity positiony += velocityY; velocityY += gravity; // Check for boundary collisions // Example: if (positiony > windowHeight - playerHeight) { positiony = windowHeight - playerHeight; } } void PlayerSprite::jump() { // Implement jump logic // Example: if (positiony == groundLevel) { velocityY = -10; } // Adjust the jump height and initial velocity as needed }

4