v2
This commit is contained in:
		
							
								
								
									
										93
									
								
								src/assets.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/assets.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
#include "assets.hpp"
 | 
			
		||||
 | 
			
		||||
AssetManager::AssetManager() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AssetManager::~AssetManager() {
 | 
			
		||||
    clearAssets();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AssetManager::load(const std::string& name, const std::string& filePath) {
 | 
			
		||||
    SDL_Surface* surface = IMG_Load(filePath.c_str());
 | 
			
		||||
    if (!surface) {
 | 
			
		||||
        SDL_Log("Failed to load image %s: %s", filePath.c_str(), SDL_GetError());
 | 
			
		||||
    }
 | 
			
		||||
    assets[name] = surface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SDL_Surface* AssetManager::getAsset(const std::string& name) const {
 | 
			
		||||
    auto it = assets.find(name);
 | 
			
		||||
    if (it != assets.end()) {
 | 
			
		||||
        return it->second;
 | 
			
		||||
    }
 | 
			
		||||
    SDL_Log("Asset %s not found", name.c_str());
 | 
			
		||||
    return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AssetManager::unloadAsset(const std::string& name) {
 | 
			
		||||
    auto it = assets.find(name);
 | 
			
		||||
    if (it != assets.end()) {
 | 
			
		||||
        SDL_DestroySurface(it->second);
 | 
			
		||||
        assets.erase(it);
 | 
			
		||||
    }
 | 
			
		||||
    SDL_Log("Asset %s not found", name.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AssetManager::clearAssets() {
 | 
			
		||||
    for (auto& pair : assets) {
 | 
			
		||||
        SDL_DestroySurface(pair.second);
 | 
			
		||||
    }
 | 
			
		||||
    assets.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TileMap::TileMap(AssetManager& assetManager)
 | 
			
		||||
    : assetManager(assetManager) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TileMap::~TileMap() {
 | 
			
		||||
    clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TileMap::addTile(const std::string& name, const Tile& tile) {
 | 
			
		||||
    tiles[name] = tile;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Tile TileMap::getTile(const std::string& name) const {
 | 
			
		||||
    auto it = tiles.find(name);
 | 
			
		||||
    if (it != tiles.end()) {
 | 
			
		||||
        return it->second;
 | 
			
		||||
    }
 | 
			
		||||
    SDL_Log("Tile %s not found", name.c_str());
 | 
			
		||||
    return Tile(); // Return an empty Tile
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SDL_Surface* TileMap::getTileAsset(const std::string& name) const {
 | 
			
		||||
    auto it = tiles.find(name);
 | 
			
		||||
    if (it != tiles.end()) {
 | 
			
		||||
        return assetManager.getAsset(it->second.assetName);
 | 
			
		||||
    }
 | 
			
		||||
    SDL_Log("Tile %s not found", name.c_str());
 | 
			
		||||
    return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Rect TileMap::getTileRect(const std::string& name) const {
 | 
			
		||||
    auto it = tiles.find(name);
 | 
			
		||||
    if (it != tiles.end()) {
 | 
			
		||||
        return Rect(it->second.srcRect);
 | 
			
		||||
    }
 | 
			
		||||
    SDL_Log("Tile %s not found", name.c_str());
 | 
			
		||||
    return Rect(); // Return an empty Rect
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TileMap::removeTile(const std::string& name) {
 | 
			
		||||
    auto it = tiles.find(name);
 | 
			
		||||
    if (it != tiles.end()) {
 | 
			
		||||
        tiles.erase(it);
 | 
			
		||||
    } else {
 | 
			
		||||
        SDL_Log("Tile %s not found", name.c_str());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TileMap::clear() {
 | 
			
		||||
    tiles.clear();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										180
									
								
								src/engine.cpp
									
									
									
									
									
								
							
							
						
						
									
										180
									
								
								src/engine.cpp
									
									
									
									
									
								
							@@ -1,78 +1,138 @@
 | 
			
		||||
#include "engine.h"
 | 
			
		||||
#include "engine.hpp"
 | 
			
		||||
 | 
			
		||||
Engine::Engine(std::string title, int width, int height)
 | 
			
		||||
{
 | 
			
		||||
    // convert title to char*
 | 
			
		||||
    ctitle = title.c_str();
 | 
			
		||||
Engine::Engine(const char* windowTitle, int windowWidth, int windowHeight, int windowFlags) {
 | 
			
		||||
    // Initialize SDL
 | 
			
		||||
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
 | 
			
		||||
        SDL_Log("SDL could not initialize! SDL_Error: %s", SDL_GetError());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Initialize SDL and TFF;
 | 
			
		||||
    TTF_Init();
 | 
			
		||||
    SDL_Init(SDL_INIT_EVERYTHING);
 | 
			
		||||
    // Create the window
 | 
			
		||||
    window = SDL_CreateWindow(windowTitle, windowWidth, windowHeight, windowFlags);
 | 
			
		||||
    if (!window) {
 | 
			
		||||
        SDL_Log("Window could not be created! SDL_Error: %s", SDL_GetError());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create window and renderer
 | 
			
		||||
    window = SDL_CreateWindow(
 | 
			
		||||
        ctitle, 
 | 
			
		||||
        SDL_WINDOWPOS_CENTERED, 
 | 
			
		||||
        SDL_WINDOWPOS_CENTERED, 
 | 
			
		||||
        width, 
 | 
			
		||||
        height, 
 | 
			
		||||
        SDL_WINDOW_SHOWN
 | 
			
		||||
    );
 | 
			
		||||
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
 | 
			
		||||
    // Create the renderer
 | 
			
		||||
    renderer = SDL_CreateRenderer(window, nullptr);
 | 
			
		||||
    if (!renderer) {
 | 
			
		||||
        SDL_Log("Renderer could not be created! SDL_Error: %s", SDL_GetError());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::initSound()
 | 
			
		||||
{
 | 
			
		||||
    // Initialize sound
 | 
			
		||||
    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048);
 | 
			
		||||
    soundInitialized = true;
 | 
			
		||||
Engine::~Engine() {
 | 
			
		||||
    // Destroy the asset manager
 | 
			
		||||
    assets.clearAssets();
 | 
			
		||||
 | 
			
		||||
    // Destroy the renderer
 | 
			
		||||
    if (renderer) {
 | 
			
		||||
        SDL_DestroyRenderer(renderer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Destroy the window
 | 
			
		||||
    if (window) {
 | 
			
		||||
        SDL_DestroyWindow(window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Quit SDL subsystems
 | 
			
		||||
    SDL_Quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::clear(SDL_Color color)
 | 
			
		||||
{
 | 
			
		||||
    // Set color
 | 
			
		||||
void Engine::clearScreen(const Color& color) {
 | 
			
		||||
    // Set the draw color
 | 
			
		||||
    SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
 | 
			
		||||
 | 
			
		||||
    // Clear screen
 | 
			
		||||
    
 | 
			
		||||
    // Clear the screen
 | 
			
		||||
    SDL_RenderClear(renderer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::startFrame()
 | 
			
		||||
{
 | 
			
		||||
    // Start frame
 | 
			
		||||
    frameStart = SDL_GetTicks();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::render()
 | 
			
		||||
{
 | 
			
		||||
    // Render screen
 | 
			
		||||
void Engine::present() {
 | 
			
		||||
    // Present the renderer
 | 
			
		||||
    SDL_RenderPresent(renderer);
 | 
			
		||||
 | 
			
		||||
    if (1000 / targetFrameRate > SDL_GetTicks() - frameStart)
 | 
			
		||||
    {
 | 
			
		||||
        SDL_Delay(1000 / targetFrameRate - (SDL_GetTicks() - frameStart));
 | 
			
		||||
    
 | 
			
		||||
    // Calculate frame duration
 | 
			
		||||
    frameEndTime = SDL_GetTicks();
 | 
			
		||||
    frameDuration = frameEndTime - frameStartTime;
 | 
			
		||||
    // Calculate delay to maintain target FPS
 | 
			
		||||
    if (targetFPSValue > 0) {
 | 
			
		||||
        Uint32 targetFrameTime = 1000 / targetFPSValue;
 | 
			
		||||
        if (frameDuration < targetFrameTime) {
 | 
			
		||||
            SDL_Delay(targetFrameTime - frameDuration);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::update()
 | 
			
		||||
{
 | 
			
		||||
    // Update input
 | 
			
		||||
    input.update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Engine::~Engine()
 | 
			
		||||
{
 | 
			
		||||
    // Free renderer and window
 | 
			
		||||
    SDL_DestroyRenderer(renderer);
 | 
			
		||||
    SDL_DestroyWindow(window);
 | 
			
		||||
 | 
			
		||||
    // If sound is initialized, quit Mix
 | 
			
		||||
    if (soundInitialized)
 | 
			
		||||
    {
 | 
			
		||||
        Mix_Quit();
 | 
			
		||||
void Engine::draw(SDL_Surface* surface, Rect destRect) {
 | 
			
		||||
    // Draw a surface to the renderer at the specified destination rectangle
 | 
			
		||||
    if (!surface) {
 | 
			
		||||
        SDL_Log("Cannot draw null surface");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Quit SDL and TTF
 | 
			
		||||
    SDL_Quit();
 | 
			
		||||
    TTF_Quit();
 | 
			
		||||
    SDL_FRect sdlDestRect = {
 | 
			
		||||
        static_cast<float>(destRect.x),
 | 
			
		||||
        static_cast<float>(destRect.y),
 | 
			
		||||
        static_cast<float>(destRect.width),
 | 
			
		||||
        static_cast<float>(destRect.height)
 | 
			
		||||
    };
 | 
			
		||||
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
 | 
			
		||||
    if (!texture) {
 | 
			
		||||
        SDL_Log("Failed to create texture from surface: %s", SDL_GetError());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SDL_RenderTexture(renderer, texture, nullptr, &sdlDestRect);
 | 
			
		||||
    SDL_DestroyTexture(texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::draw(SDL_Surface* surface, Rect srcRect, Rect destRect) {
 | 
			
		||||
    // Draw a surface to the renderer with specified source and destination rectangles
 | 
			
		||||
    if (!surface) {
 | 
			
		||||
        SDL_Log("Cannot draw null surface");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_FRect sdlSrcRect = {
 | 
			
		||||
        static_cast<float>(srcRect.x),
 | 
			
		||||
        static_cast<float>(srcRect.y),
 | 
			
		||||
        static_cast<float>(srcRect.width),
 | 
			
		||||
        static_cast<float>(srcRect.height)
 | 
			
		||||
    };
 | 
			
		||||
    SDL_FRect sdlDestRect = {
 | 
			
		||||
        static_cast<float>(destRect.x),
 | 
			
		||||
        static_cast<float>(destRect.y),
 | 
			
		||||
        static_cast<float>(destRect.width),
 | 
			
		||||
        static_cast<float>(destRect.height)
 | 
			
		||||
    };
 | 
			
		||||
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
 | 
			
		||||
    if (!texture) {
 | 
			
		||||
        SDL_Log("Failed to create texture from surface: %s", SDL_GetError());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SDL_RenderTexture(renderer, texture, &sdlSrcRect, &sdlDestRect);
 | 
			
		||||
    SDL_DestroyTexture(texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::draw(Tile tile, Rect destRect) {
 | 
			
		||||
    // Draw a tile to the renderer at the specified destination rectangle
 | 
			
		||||
    SDL_Surface* surface = assets.getAsset(tile.assetName);
 | 
			
		||||
    if (!surface) {
 | 
			
		||||
        SDL_Log("Tile asset %s not found", tile.assetName.c_str());
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    draw(surface, tile.srcRect, destRect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::startFrame() {
 | 
			
		||||
    // Start the frame timer
 | 
			
		||||
    frameStartTime = SDL_GetTicks();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Engine::targetFPS(int fps) {
 | 
			
		||||
    // Set the target frames per second
 | 
			
		||||
    targetFPSValue = fps;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,133 +0,0 @@
 | 
			
		||||
// Includes
 | 
			
		||||
#include "engine.h"
 | 
			
		||||
 | 
			
		||||
// Variables
 | 
			
		||||
SDL_Surface* assets;
 | 
			
		||||
Music* music;
 | 
			
		||||
Engine *engine;
 | 
			
		||||
 | 
			
		||||
// Functions
 | 
			
		||||
// Quit function
 | 
			
		||||
void quit()
 | 
			
		||||
{
 | 
			
		||||
    // Free assets
 | 
			
		||||
    SDL_FreeSurface(assets);
 | 
			
		||||
    delete engine;
 | 
			
		||||
    // Exit program
 | 
			
		||||
    exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Main function
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{   
 | 
			
		||||
    engine = new Engine("Game", 800, 600);
 | 
			
		||||
    engine->initSound();
 | 
			
		||||
    engine->targetFrameRate = 60;
 | 
			
		||||
 | 
			
		||||
    // Load assets
 | 
			
		||||
    assets = SDL_LoadBMP("example_assets/sprites.bmp");
 | 
			
		||||
    music = new Music("example_assets/crystal_zone.mp3");
 | 
			
		||||
    
 | 
			
		||||
    // frame map
 | 
			
		||||
    std::map<std::string, SDL_Rect> idle = {
 | 
			
		||||
        { "idle", { 76, 456, 68, 128 } },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::map<std::string, SDL_Rect> front = {
 | 
			
		||||
        { "front", { 4, 456, 68, 125 } },
 | 
			
		||||
        { "front2", { 76, 456, 68, 128 } },
 | 
			
		||||
        { "front3", { 148, 456, 68, 125 } }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::map<std::string, SDL_Rect> back = {
 | 
			
		||||
        { "back", { 662, 456, 68, 125 } },
 | 
			
		||||
        { "back2", { 734, 456, 68, 128 } },
 | 
			
		||||
        { "back3", { 806, 456, 68, 125 } }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::map<std::string, SDL_Rect> walk = {
 | 
			
		||||
        { "walk", { 220, 456, 68, 124 } },
 | 
			
		||||
        { "walk2", { 292, 456, 73, 127 } },
 | 
			
		||||
        { "walk3", { 369, 456, 68, 124 } }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::map<std::string, SDL_Rect> test = {
 | 
			
		||||
        { "test", { 4, 2095, 68, 59 } },
 | 
			
		||||
        { "test2", { 76, 2095, 68, 59 } }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Create sprite and animation
 | 
			
		||||
    Sprite* sprite = new Sprite(engine->renderer, assets);
 | 
			
		||||
    AnimationManager* animations = new AnimationManager(sprite);
 | 
			
		||||
    animations->addAnimation("idle", idle, 10, false, true, false, false);
 | 
			
		||||
    animations->addAnimation("walk_left", walk, 10, false, true, true, false);
 | 
			
		||||
    animations->addAnimation("walk_right", walk, 10, true, true, true, false);
 | 
			
		||||
    animations->addAnimation("walk_back", back, 10, false, true, true, false);
 | 
			
		||||
    animations->addAnimation("walk_front", front, 10, false, true, true, true);
 | 
			
		||||
    animations->addAnimation("test", test, 20, false, true, false, false);
 | 
			
		||||
    animations->setAnimation("idle");
 | 
			
		||||
 | 
			
		||||
    // Play music
 | 
			
		||||
    music->play();
 | 
			
		||||
 | 
			
		||||
    // Main loop
 | 
			
		||||
    while (true)
 | 
			
		||||
    {
 | 
			
		||||
        // Start time
 | 
			
		||||
        engine->startFrame();
 | 
			
		||||
 | 
			
		||||
        // Update input
 | 
			
		||||
        engine->update();
 | 
			
		||||
 | 
			
		||||
        // Exit if window s closed
 | 
			
		||||
        if (engine->input.exit || engine->input.activeKeys[SDLK_ESCAPE])
 | 
			
		||||
        {
 | 
			
		||||
            quit();
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        if (engine->input.activeKeys[SDLK_d] || engine->input.controllers[0].buttons[CBUTTONS::DPAD_RIGHT] || engine->input.controllers[0].leftStickX > 8000)
 | 
			
		||||
        {
 | 
			
		||||
            animations->setAnimation("walk_right");
 | 
			
		||||
            sprite->move({ 1, 0 });
 | 
			
		||||
        }
 | 
			
		||||
        if (engine->input.activeKeys[SDLK_a] || engine->input.controllers[0].buttons[CBUTTONS::DPAD_LEFT]  || engine->input.controllers[0].leftStickX < -8000)
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            animations->setAnimation("walk_left");
 | 
			
		||||
            sprite->move({ -1, 0 });
 | 
			
		||||
        }
 | 
			
		||||
        if (engine->input.activeKeys[SDLK_w] || engine->input.controllers[0].buttons[CBUTTONS::DPAD_UP] || engine->input.controllers[0].leftStickY < -8000)
 | 
			
		||||
        {
 | 
			
		||||
            animations->setAnimation("walk_back");
 | 
			
		||||
            sprite->move({ 0, -1 });
 | 
			
		||||
        }
 | 
			
		||||
        if (engine->input.activeKeys[SDLK_s] || engine->input.controllers[0].buttons[CBUTTONS::DPAD_DOWN] || engine->input.controllers[0].leftStickY > 8000)
 | 
			
		||||
        {
 | 
			
		||||
            animations->setAnimation("walk_front");
 | 
			
		||||
            sprite->move({ 0, 1 });
 | 
			
		||||
        }
 | 
			
		||||
        if (engine->input.activeKeys[SDLK_SPACE] || engine->input.controllers[0].buttons[CBUTTONS::A])
 | 
			
		||||
        {
 | 
			
		||||
            animations->playAnimation("test");
 | 
			
		||||
        }
 | 
			
		||||
        if (!engine->input.keysPressed({ SDLK_w, SDLK_a, SDLK_s, SDLK_d }) && engine->input.controllers[0].leftStickX < 8000 && engine->input.controllers[0].leftStickX > -8000 &&
 | 
			
		||||
            engine->input.controllers[0].leftStickY < 8000 && engine->input.controllers[0].leftStickY > -8000 &&
 | 
			
		||||
            !engine->input.controllerPressed({ CBUTTONS::DPAD_UP, CBUTTONS::DPAD_DOWN, CBUTTONS::DPAD_LEFT, CBUTTONS::DPAD_RIGHT }))
 | 
			
		||||
        {
 | 
			
		||||
            animations->setAnimation("idle");
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        // Update animation
 | 
			
		||||
        animations->update();
 | 
			
		||||
 | 
			
		||||
        // Clear screen
 | 
			
		||||
        engine->clear({ 100, 150, 255, 255 });
 | 
			
		||||
 | 
			
		||||
        // Draw sprite
 | 
			
		||||
        animations->draw(engine->renderer);
 | 
			
		||||
 | 
			
		||||
        // Update screen    
 | 
			
		||||
        engine->render();
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										158
									
								
								src/input.cpp
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								src/input.cpp
									
									
									
									
									
								
							@@ -1,78 +1,112 @@
 | 
			
		||||
#include "input.h"
 | 
			
		||||
#include "input.hpp"
 | 
			
		||||
 | 
			
		||||
Input::Input() {
 | 
			
		||||
 | 
			
		||||
Input::Input()
 | 
			
		||||
{
 | 
			
		||||
    SDL_Init(SDL_INIT_JOYSTICK);
 | 
			
		||||
    exit = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::update()
 | 
			
		||||
{
 | 
			
		||||
    while (SDL_PollEvent(&event))
 | 
			
		||||
    {
 | 
			
		||||
        switch (event.type)
 | 
			
		||||
        {
 | 
			
		||||
        case SDL_CONTROLLERBUTTONDOWN:
 | 
			
		||||
            controllers[event.cbutton.which].buttons[event.cbutton.button] = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_CONTROLLERBUTTONUP:
 | 
			
		||||
            controllers[event.cbutton.which].buttons[event.cbutton.button] = false;
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_MOUSEBUTTONDOWN:
 | 
			
		||||
            mouse.buttons[event.button.button] = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_MOUSEBUTTONUP:
 | 
			
		||||
            mouse.buttons[event.button.button] = false;
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_KEYDOWN:
 | 
			
		||||
            activeKeys[event.key.keysym.sym] = true;    
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_KEYUP:
 | 
			
		||||
            activeKeys.erase(event.key.keysym.sym);
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_CONTROLLERDEVICEADDED:
 | 
			
		||||
            controllers[SDL_NumJoysticks() - 1] = {
 | 
			
		||||
                SDL_GameControllerOpen(SDL_NumJoysticks() - 1),
 | 
			
		||||
                SDL_GameControllerName(SDL_GameControllerOpen(SDL_NumJoysticks() - 1))
 | 
			
		||||
            };
 | 
			
		||||
            printf("Controller added: %s\n", controllers[SDL_NumJoysticks() - 1].name.c_str());
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_QUIT:
 | 
			
		||||
            exit = true;
 | 
			
		||||
            break;
 | 
			
		||||
Input::~Input() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::handleEvents() {
 | 
			
		||||
    while (SDL_PollEvent(&event)) {
 | 
			
		||||
        switch (event.type) {
 | 
			
		||||
            case SDL_EVENT_QUIT:
 | 
			
		||||
                quitRequestedFlag = true;
 | 
			
		||||
                break;
 | 
			
		||||
            case SDL_EVENT_KEY_DOWN:
 | 
			
		||||
                if (keyStates[event.key.scancode] == false) {
 | 
			
		||||
                    keyFallingEdgeStates[event.key.scancode] = true;
 | 
			
		||||
                }
 | 
			
		||||
                keyStates[event.key.scancode] = true;
 | 
			
		||||
                break;
 | 
			
		||||
            case SDL_EVENT_KEY_UP:
 | 
			
		||||
                keyStates[event.key.scancode] = false;
 | 
			
		||||
                keyFallingEdgeStates[event.key.scancode] = false;
 | 
			
		||||
                break;
 | 
			
		||||
            case SDL_EVENT_MOUSE_BUTTON_DOWN:
 | 
			
		||||
                if (mouseButtonStates[event.button.button] == false) {
 | 
			
		||||
                    mouseButtonFallingEdgeStates[event.button.button] = true;
 | 
			
		||||
                }
 | 
			
		||||
                mouseButtonStates[event.button.button] = true;
 | 
			
		||||
                break;
 | 
			
		||||
            case SDL_EVENT_MOUSE_BUTTON_UP:
 | 
			
		||||
                mouseButtonStates[event.button.button] = false;
 | 
			
		||||
                mouseButtonFallingEdgeStates[event.button.button] = false;
 | 
			
		||||
                break;
 | 
			
		||||
            case SDL_EVENT_MOUSE_MOTION:
 | 
			
		||||
                mousePosition.x = static_cast<int>(event.motion.x);
 | 
			
		||||
                mousePosition.y = static_cast<int>(event.motion.y);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        for (auto& controller : controllers)
 | 
			
		||||
        {
 | 
			
		||||
            controller.second.leftStickX = SDL_GameControllerGetAxis(controller.second.controller, SDL_CONTROLLER_AXIS_LEFTX);
 | 
			
		||||
            controller.second.leftStickY = SDL_GameControllerGetAxis(controller.second.controller, SDL_CONTROLLER_AXIS_LEFTY);
 | 
			
		||||
            controller.second.rightStickX = SDL_GameControllerGetAxis(controller.second.controller, SDL_CONTROLLER_AXIS_RIGHTX);
 | 
			
		||||
            controller.second.rightStickY = SDL_GameControllerGetAxis(controller.second.controller, SDL_CONTROLLER_AXIS_RIGHTY);
 | 
			
		||||
            controller.second.leftTrigger = SDL_GameControllerGetAxis(controller.second.controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
 | 
			
		||||
            controller.second.rightTrigger = SDL_GameControllerGetAxis(controller.second.controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
 | 
			
		||||
        }
 | 
			
		||||
        SDL_GetMouseState(&mouse.x, &mouse.y);
 | 
			
		||||
        mouse.wheel = event.wheel.y;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::keysPressed(std::vector<SDL_Keycode> keys)
 | 
			
		||||
{
 | 
			
		||||
    for (auto key : keys)
 | 
			
		||||
    {
 | 
			
		||||
        if (activeKeys[key])
 | 
			
		||||
        {
 | 
			
		||||
bool Input::quitRequested() const {
 | 
			
		||||
    return quitRequestedFlag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::isKeyPressed(SDL_Scancode key) {
 | 
			
		||||
    auto it = keyStates.find(key);
 | 
			
		||||
    return it != keyStates.end() && it->second;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::isKeyPressed(std::vector<SDL_Scancode> keys) {
 | 
			
		||||
    for (const auto& key : keys) {
 | 
			
		||||
        if (isKeyPressed(key)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::controllerPressed(std::vector<Uint8> buttons, int controller)
 | 
			
		||||
{
 | 
			
		||||
    for (auto button : buttons)
 | 
			
		||||
    {
 | 
			
		||||
        if (controllers[controller].buttons[button])
 | 
			
		||||
        {
 | 
			
		||||
bool Input::isMouseButtonPressed(Uint8 button) {
 | 
			
		||||
    auto it = mouseButtonStates.find(button);
 | 
			
		||||
    return it != mouseButtonStates.end() && it->second;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::isMouseButtonPressed(std::vector<Uint8> buttons) {
 | 
			
		||||
    for (const auto& button : buttons) {
 | 
			
		||||
        if (isMouseButtonPressed(button)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vector2 Input::getMousePosition() const {
 | 
			
		||||
    return mousePosition;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::hasKeyBeenPressed(SDL_Scancode key) {
 | 
			
		||||
    auto it = keyFallingEdgeStates.find(key);
 | 
			
		||||
    if (it != keyFallingEdgeStates.end() && it->second) {
 | 
			
		||||
        keyFallingEdgeStates[key] = false;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::hasKeyBeenPressed(std::vector<SDL_Scancode> keys) {
 | 
			
		||||
    for (const auto& key : keys) {
 | 
			
		||||
        if (hasKeyBeenPressed(key)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::hasMouseButtonBeenPressed(Uint8 button) {
 | 
			
		||||
    auto it = mouseButtonFallingEdgeStates.find(button);
 | 
			
		||||
    if (it != mouseButtonFallingEdgeStates.end() && it->second) {
 | 
			
		||||
        mouseButtonFallingEdgeStates[button] = false;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
bool Input::hasMouseButtonBeenPressed(std::vector<Uint8> buttons) {
 | 
			
		||||
    for (const auto& button : buttons) {
 | 
			
		||||
        if (hasMouseButtonBeenPressed(button)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								src/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/main.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
#include "engine.hpp"
 | 
			
		||||
 | 
			
		||||
// Main function
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
    // Create the engine with a window title and dimensions
 | 
			
		||||
    Engine engine("SDL3 Game Engine", 800, 600);
 | 
			
		||||
    TileMap tileMap(engine.assets);
 | 
			
		||||
 | 
			
		||||
    // Load bird asset
 | 
			
		||||
    engine.assets.load("bird", "assets/bird.png");
 | 
			
		||||
    tileMap.addTile("bird0", Tile{{0, 0, 34, 24}, "bird"});
 | 
			
		||||
    tileMap.addTile("bird1", Tile{{34, 0, 34, 24}, "bird"});
 | 
			
		||||
    tileMap.addTile("bird2", Tile{{68, 0, 34, 24}, "bird"});
 | 
			
		||||
 | 
			
		||||
    int currentBirdIndex = 0;
 | 
			
		||||
 | 
			
		||||
    // bird position
 | 
			
		||||
    Vector2 birdPosition(0, 0);
 | 
			
		||||
 | 
			
		||||
    while (!engine.input.quitRequested()) {
 | 
			
		||||
        // Start a new frame
 | 
			
		||||
        engine.startFrame();
 | 
			
		||||
 | 
			
		||||
        // Handle input events
 | 
			
		||||
        engine.input.handleEvents();
 | 
			
		||||
 | 
			
		||||
        // check for movement keys
 | 
			
		||||
        if (engine.input.isKeyPressed(SDL_SCANCODE_D)) {
 | 
			
		||||
            birdPosition.x += 1; // Move right
 | 
			
		||||
        }
 | 
			
		||||
        if (engine.input.isKeyPressed(SDL_SCANCODE_A)) {
 | 
			
		||||
            birdPosition.x -= 1; // Move left
 | 
			
		||||
        }
 | 
			
		||||
        if (engine.input.isKeyPressed(SDL_SCANCODE_W)) {
 | 
			
		||||
            birdPosition.y -= 1; // Move up
 | 
			
		||||
        }
 | 
			
		||||
        if (engine.input.isKeyPressed(SDL_SCANCODE_S)) {
 | 
			
		||||
            birdPosition.y += 1; // Move down
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Change bird sprite on space key press
 | 
			
		||||
        if (engine.input.hasKeyBeenPressed(SDL_SCANCODE_SPACE)) {
 | 
			
		||||
            currentBirdIndex = (currentBirdIndex + 1) % 3; // Cycle through bird sprites
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Clear the screen with a color
 | 
			
		||||
        engine.clearScreen({0, 0, 0}); // Black color
 | 
			
		||||
 | 
			
		||||
        // Draw the bird asset at a specific position
 | 
			
		||||
        engine.draw(tileMap.getTile("bird" + std::to_string(currentBirdIndex)), birdPosition);
 | 
			
		||||
 | 
			
		||||
        // Present the rendered frame
 | 
			
		||||
        engine.present();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,56 +0,0 @@
 | 
			
		||||
#include "sound.h"
 | 
			
		||||
 | 
			
		||||
Music::Music(const char* path)
 | 
			
		||||
{
 | 
			
		||||
    music = Mix_LoadMUS(path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Music::play(int loops)
 | 
			
		||||
{
 | 
			
		||||
    Mix_PlayMusic(music, loops);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Music::pause()
 | 
			
		||||
{
 | 
			
		||||
    Mix_PauseMusic();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Music::stop()
 | 
			
		||||
{
 | 
			
		||||
    Mix_HaltMusic();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Music::resume()
 | 
			
		||||
{
 | 
			
		||||
    Mix_ResumeMusic();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Music::setVolume(int volume)
 | 
			
		||||
{
 | 
			
		||||
    Mix_VolumeMusic(volume);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Music::~Music()
 | 
			
		||||
{
 | 
			
		||||
    Mix_FreeMusic(music);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Effect::Effect(const char* path)
 | 
			
		||||
{
 | 
			
		||||
    effect = Mix_LoadWAV(path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Effect::play(int loops, int channel)
 | 
			
		||||
{
 | 
			
		||||
    Mix_PlayChannel(channel, effect, loops);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Effect::setVolume(int volume)
 | 
			
		||||
{
 | 
			
		||||
    Mix_VolumeChunk(effect, volume);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Effect::~Effect()
 | 
			
		||||
{
 | 
			
		||||
    Mix_FreeChunk(effect);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										170
									
								
								src/sprite.cpp
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								src/sprite.cpp
									
									
									
									
									
								
							@@ -1,170 +0,0 @@
 | 
			
		||||
#include "sprite.h"
 | 
			
		||||
 | 
			
		||||
Sprite::Sprite(SDL_Renderer *renderer, SDL_Surface *surface)
 | 
			
		||||
{
 | 
			
		||||
    Texture = SDL_CreateTextureFromSurface(renderer, surface);
 | 
			
		||||
    dstrect = { 0, 0, surface->w, surface->h };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Sprite::~Sprite()
 | 
			
		||||
{
 | 
			
		||||
    SDL_DestroyTexture(Texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Sprite::draw(SDL_Renderer* renderer, std::string frame, bool autoRect, bool flip)
 | 
			
		||||
    {
 | 
			
		||||
    if (frames.find(frame) == frames.end())
 | 
			
		||||
    {
 | 
			
		||||
        printf("Frame not found\n");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (autoRect)
 | 
			
		||||
    {
 | 
			
		||||
        dstrect = { dstrect.x, dstrect.y, frames[frame].w, frames[frame].h };
 | 
			
		||||
    }
 | 
			
		||||
    SDL_SetTextureAlphaMod(Texture, 255);
 | 
			
		||||
    dstrect.w *= scale.x;
 | 
			
		||||
    dstrect.h *= scale.y;
 | 
			
		||||
    SDL_RenderCopyEx(renderer, Texture, &frames[frame], &dstrect, angle, NULL, flip ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Sprite::addFrame(std::string name, SDL_Rect rect)
 | 
			
		||||
{
 | 
			
		||||
    frames[name] = rect;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Sprite::setPos(int_vec2 position)
 | 
			
		||||
{
 | 
			
		||||
    dstrect.x = position.x;
 | 
			
		||||
    dstrect.y = position.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Sprite::move(int_vec2 position)
 | 
			
		||||
{
 | 
			
		||||
    dstrect.x += position.x;
 | 
			
		||||
    dstrect.y += position.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int_vec2 Sprite::getSize(std::string frame)
 | 
			
		||||
{
 | 
			
		||||
    size = { frames[frame].w, frames[frame].h };
 | 
			
		||||
    return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Sprite::autorect(std::string frame)
 | 
			
		||||
{
 | 
			
		||||
    dstrect = { dstrect.x, dstrect.y, frames[frame].w, frames[frame].h };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Animation::Animation(std::map<std::string, SDL_Rect> frames, Sprite* sprite, int frameDuration)
 | 
			
		||||
{
 | 
			
		||||
    this->sprite = sprite;
 | 
			
		||||
    this->frameDuration = frameDuration;
 | 
			
		||||
 | 
			
		||||
    for (auto const& x : frames)
 | 
			
		||||
    {
 | 
			
		||||
        this->frames.push_back(x.first);
 | 
			
		||||
        this->sprite->addFrame(x.first, x.second);
 | 
			
		||||
    }
 | 
			
		||||
    currentFrameName = this->frames[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Animation::reset()
 | 
			
		||||
{
 | 
			
		||||
    frameIndex = 0;
 | 
			
		||||
    frameDirection = 1;
 | 
			
		||||
    currentFrameName = frames[0];
 | 
			
		||||
    end = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Animation::update()
 | 
			
		||||
{
 | 
			
		||||
    frameCounter++;
 | 
			
		||||
    end = false;
 | 
			
		||||
    if (frameCounter >= frameDuration)
 | 
			
		||||
    {
 | 
			
		||||
        frameCounter = 0;
 | 
			
		||||
        if (pingpong)
 | 
			
		||||
        {
 | 
			
		||||
            frameIndex += frameDirection;
 | 
			
		||||
            if (frameIndex >= frames.size() - 1 || frameIndex <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (!loop)
 | 
			
		||||
                {
 | 
			
		||||
                    frameDirection = 0;
 | 
			
		||||
                    end = true;
 | 
			
		||||
                } else { 
 | 
			
		||||
                    frameDirection *= -1;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            frameIndex++;
 | 
			
		||||
            if (frameIndex >= frames.size())
 | 
			
		||||
            {
 | 
			
		||||
                if (!loop)
 | 
			
		||||
                {
 | 
			
		||||
                    frameIndex = frames.size() - 1;
 | 
			
		||||
                    end = true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    frameIndex = 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        currentFrameName = frames[frameIndex];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Animation::draw(SDL_Renderer* renderer, bool autoRect, bool flip)
 | 
			
		||||
{
 | 
			
		||||
    sprite->draw(renderer, currentFrameName, autoRect, flip);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AnimationManager::AnimationManager(Sprite* sprite)
 | 
			
		||||
{
 | 
			
		||||
    this->sprite = sprite;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnimationManager::addAnimation(std::string name, std::map<std::string, SDL_Rect> frames, int frameDuration, bool flip, bool autoRect, bool loop, bool pingpong)
 | 
			
		||||
{
 | 
			
		||||
    animations[name] = new Animation(frames, sprite, frameDuration);
 | 
			
		||||
    this->flip[name] = flip;
 | 
			
		||||
    this->autoRect[name] = autoRect;
 | 
			
		||||
    animations[name]->loop = loop;
 | 
			
		||||
    animations[name]->pingpong = pingpong;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnimationManager::setAnimation(std::string name)
 | 
			
		||||
{
 | 
			
		||||
    if (!playing) {
 | 
			
		||||
        currentAnimation = name;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnimationManager::update()
 | 
			
		||||
{
 | 
			
		||||
    animations[currentAnimation]->update();
 | 
			
		||||
    if (playing && animations[currentAnimation]->end)
 | 
			
		||||
    {
 | 
			
		||||
        playing = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnimationManager::draw(SDL_Renderer* renderer)
 | 
			
		||||
{
 | 
			
		||||
    animations[currentAnimation]->draw(renderer, autoRect[currentAnimation], flip[currentAnimation]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnimationManager::playAnimation(std::string name)
 | 
			
		||||
{
 | 
			
		||||
    if (!playing) {
 | 
			
		||||
        animations[name]->loop = false;
 | 
			
		||||
        animations[name]->reset();
 | 
			
		||||
        setAnimation(name);
 | 
			
		||||
        playing = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								src/text.cpp
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/text.cpp
									
									
									
									
									
								
							@@ -1,17 +0,0 @@
 | 
			
		||||
#include "text.h"
 | 
			
		||||
 | 
			
		||||
Text::Text(TTF_Font* font, SDL_Color color)
 | 
			
		||||
{
 | 
			
		||||
    this->font = font;
 | 
			
		||||
    this->color = color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Text::draw(SDL_Renderer* renderer, std::string text, int x, int y)
 | 
			
		||||
{
 | 
			
		||||
    surface = TTF_RenderText_Solid(font, text.c_str(), color);
 | 
			
		||||
    texture = SDL_CreateTextureFromSurface(renderer, surface);
 | 
			
		||||
    rect = { x, y, surface->w, surface->h };
 | 
			
		||||
    SDL_RenderCopy(renderer, texture, NULL, &rect);
 | 
			
		||||
    SDL_FreeSurface(surface);
 | 
			
		||||
    SDL_DestroyTexture(texture);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user