Skip to content Skip to sidebar Skip to footer

Widget HTML #1

Learn to Make an Alien Farm Game With C++ SDL2 From Scratch



Learn to Make an Alien Farm Game With C++ SDL2 From Scratch

You can construct paths and waterways, plant alien crops and trees, and colorful animals that move.

Enroll Now

Creating a game from scratch is an exciting journey that involves multiple aspects of programming, from understanding the basics of a language to mastering game development libraries. In this tutorial, we will walk through the steps to create a simple "Alien Farm" game using C++ and the Simple DirectMedia Layer 2 (SDL2) library.

Prerequisites

Before we start, ensure you have the following installed on your system:

  • A C++ compiler (GCC, Clang, or MSVC)
  • SDL2 library
  • SDL2_image library (for handling images)
  • A text editor or an IDE like Visual Studio Code

Setting Up Your Development Environment

  1. Install SDL2 and SDL2_image:

    • On Windows, you can download the development libraries from the SDL website and follow the installation instructions.
    • On macOS, you can use Homebrew:
      sh
      brew install sdl2 sdl2_image
    • On Linux, you can install them using your package manager. For example, on Ubuntu:
      sh
      sudo apt-get install libsdl2-dev libsdl2-image-dev
  2. Set Up Your Project Structure: Create a directory for your project and inside it, create the following structure:

    css
    AlienFarm/ ├── src/ │ ├── main.cpp ├── assets/ │ ├── alien.png │ ├── farm.png └── Makefile

Writing the Game

  1. Initialize SDL2:

    In main.cpp, start by including the necessary headers and initializing SDL2.

    cpp
    #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 600; bool initSDL(SDL_Window** window, SDL_Renderer** renderer) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl; return false; } *window = SDL_CreateWindow("Alien Farm", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (!*window) { std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl; return false; } *renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED); if (!*renderer) { std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() << std::endl; return false; } int imgFlags = IMG_INIT_PNG; if (!(IMG_Init(imgFlags) & imgFlags)) { std::cerr << "SDL_image could not initialize! IMG_Error: " << IMG_GetError() << std::endl; return false; } return true; } void closeSDL(SDL_Window* window, SDL_Renderer* renderer) { SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); IMG_Quit(); SDL_Quit(); } int main(int argc, char* args[]) { SDL_Window* window = nullptr; SDL_Renderer* renderer = nullptr; if (!initSDL(&window, &renderer)) { std::cerr << "Failed to initialize!" << std::endl; return -1; } bool quit = false; SDL_Event e; while (!quit) { while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { quit = true; } } SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); // Render game objects here SDL_RenderPresent(renderer); } closeSDL(window, renderer); return 0; }
  2. Loading and Rendering Images:

    Next, load and render images. Add the following functions to main.cpp to load textures and render them.

    cpp
    SDL_Texture* loadTexture(const std::string &path, SDL_Renderer* renderer) { SDL_Texture* newTexture = nullptr; SDL_Surface* loadedSurface = IMG_Load(path.c_str()); if (!loadedSurface) { std::cerr << "Unable to load image " << path << "! SDL_image Error: " << IMG_GetError() << std::endl; return nullptr; } newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface); if (!newTexture) { std::cerr << "Unable to create texture from " << path << "! SDL Error: " << SDL_GetError() << std::endl; } SDL_FreeSurface(loadedSurface); return newTexture; } void renderTexture(SDL_Texture* texture, SDL_Renderer* renderer, int x, int y) { SDL_Rect renderQuad = { x, y, 100, 100 }; // Adjust width and height as needed SDL_RenderCopy(renderer, texture, NULL, &renderQuad); }

    Load and render the alien and farm images in the main game loop.

    cpp
    int main(int argc, char* args[]) { SDL_Window* window = nullptr; SDL_Renderer* renderer = nullptr; if (!initSDL(&window, &renderer)) { std::cerr << "Failed to initialize!" << std::endl; return -1; } SDL_Texture* alienTexture = loadTexture("assets/alien.png", renderer); SDL_Texture* farmTexture = loadTexture("assets/farm.png", renderer); if (!alienTexture || !farmTexture) { std::cerr << "Failed to load textures!" << std::endl; return -1; } bool quit = false; SDL_Event e; while (!quit) { while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { quit = true; } } SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); renderTexture(farmTexture, renderer, 0, 0); // Background renderTexture(alienTexture, renderer, 350, 250); // Alien SDL_RenderPresent(renderer); } SDL_DestroyTexture(alienTexture); SDL_DestroyTexture(farmTexture); closeSDL(window, renderer); return 0; }
  3. Handling User Input:

    To make the game interactive, we need to handle user input. Modify the event loop to handle key presses.

    cpp
    int main(int argc, char* args[]) { SDL_Window* window = nullptr; SDL_Renderer* renderer = nullptr; if (!initSDL(&window, &renderer)) { std::cerr << "Failed to initialize!" << std::endl; return -1; } SDL_Texture* alienTexture = loadTexture("assets/alien.png", renderer); SDL_Texture* farmTexture = loadTexture("assets/farm.png", renderer); if (!alienTexture || !farmTexture) { std::cerr << "Failed to load textures!" << std::endl; return -1; } bool quit = false; SDL_Event e; int alienX = 350; int alienY = 250; while (!quit) { while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { quit = true; } else if (e.type == SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_UP: alienY -= 10; break; case SDLK_DOWN: alienY += 10; break; case SDLK_LEFT: alienX -= 10; break; case SDLK_RIGHT: alienX += 10; break; } } } SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderClear(renderer); renderTexture(farmTexture, renderer, 0, 0); // Background renderTexture(alienTexture, renderer, alienX, alienY); // Alien SDL_RenderPresent(renderer); } SDL_DestroyTexture(alienTexture); SDL_DestroyTexture(farmTexture); closeSDL(window, renderer); return 0; }
  4. Adding Game Logic:

    Finally, let's add some simple game logic. For example, you can add collision detection between the alien and certain objects on the farm.

    cpp
    bool checkCollision(SDL_Rect a, SDL_Rect b) { int leftA = a.x; int rightA = a.x + a.w; int topA = a.y; int bottomA = a.y + a.h; int leftB = b.x; int rightB = b.x + b.w; int topB = b.y; int bottomB = b.y + b.h; if (bottomA <= topB) { return false; } if (topA >= bottomB) { return false;