Hi I’m trying to follow this Cheetah Animation I’ve edited the main.cpp to suit my SDL Template on VS 2022, code compiles with no erros but sprite does not appear on the window. For Cheetah.png I used the exact same file path as the Github repo. what’s wrong here?
`#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include “helper.h”
// Definitions
#define TZ_H (512 / 4) // Width of a single frame
#define TZ_V (252 / 2) // Height of a single frame
#define WHITE 255, 255, 255, 255
#define BLACK 0, 0, 0, 255
#define RED 255, 0, 0, 255
#define WW (TZ_H * 2.5)
#define WH (TZ_V * 2.5)
#define FRAME_TIME 0.1f // 100ms per frame
// Globals
int ww = WW;
int wh = WH;
// Visibles
SDL_Surface* temp_surface = NULL;
SDL_Texture* cheetah = NULL;
SDL_Rect cheetah_dst;
SDL_Rect cheetah_src;
// Function prototypes
float time_(void);
void assets_in(void);
void assets_out(void);
// Create a placeholder image if the real one fails to load
SDL_Surface* create_placeholder_surface() {
SDL_Surface* surface = SDL_CreateRGBSurface(0, 512, 252, 32,
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF);
if (surface == NULL) {
printf(“Couldn’t create placeholder surface: %s\n”, SDL_GetError());
return NULL;
}
// Fill with a background color (white)
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 255, 255, 255));
// Draw grid lines to represent the sprite frames
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 2; j++) {
SDL_Rect frame = { i * 128, j * 126, 128, 126 };
SDL_FillRect(surface, &frame, SDL_MapRGB(surface->format,50 + i * 40,50 + j * 40,150));
// Draw a border (white)
SDL_Rect border = { i * 128 + 5, j * 126 + 5, 118, 116 };
SDL_FillRect(surface, &border, SDL_MapRGB(surface->format,255, 255, 255)); // White color
}
}
return surface;
}
// Load assets
void assets_in(void) {
// Try loading the image
temp_surface = IMG_Load(“./assets/gfx/Cheetah.png”);
if (temp_surface == NULL) {
printf("Failed to load image: %s\n", IMG_GetError());
printf("Creating placeholder instead\n");
// Create placeholder
temp_surface = create_placeholder_surface();
if (temp_surface == NULL) {
exit(EXIT_FAILURE);
}
}
else {
printf("Image loaded successfully!\n");
}
// Create texture from surface
cheetah = SDL_CreateTextureFromSurface(Renderer, temp_surface);
SDL_FreeSurface(temp_surface); // Free the surface after creating texture
if (cheetah == NULL) {
printf("Failed to create texture: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
else {
printf("Texture created successfully!\n");
}
// Setup destination rectangle (where to draw on screen)
cheetah_dst.w = TZ_H * 2;
cheetah_dst.h = TZ_V * 2;
cheetah_dst.x = ww / 2 - cheetah_dst.w / 2;
cheetah_dst.y = wh / 2 - cheetah_dst.h / 2;
// Setup source rectangle (which part of the sprite sheet to draw)
cheetah_src.w = TZ_H;
cheetah_src.h = TZ_V;
cheetah_src.x = 0;
cheetah_src.y = 0;
printf("Cheetah source rect: x=%d, y=%d, w=%d, h=%d\n", cheetah_src.x, cheetah_src.y, cheetah_src.w, cheetah_src.h);
printf("Cheetah dest rect: x=%d, y=%d, w=%d, h=%d\n", cheetah_dst.x, cheetah_dst.y, cheetah_dst.w, cheetah_dst.h);
}
// Clean up assets
void assets_out(void) {
if (cheetah != NULL) {
SDL_DestroyTexture(cheetah);
cheetah = NULL;
}
}
// Get current time in seconds
float time_(void) {
static Uint64 start = 0;
static float frequency = 0;
if (start == 0) {
start = SDL_GetPerformanceCounter();
frequency = (float)SDL_GetPerformanceFrequency();
return 0.0f;
}
Uint64 counter = SDL_GetPerformanceCounter();
return ((float)(counter - start) / frequency);
}
int main(int argc, char* argv) {
(void)argc;
(void)argv;
// Initialize
init();
// Create a full screen window
Window = SDL_CreateWindow("Cheetah Animation", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP);
if (Window == NULL) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
// Create renderer
Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
if (Renderer == NULL) {
printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
// Get the screen dimensions
SDL_DisplayMode displayMode;
if (SDL_GetCurrentDisplayMode(0, &displayMode) != 0) {
printf("Could not get display mode: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
ww = displayMode.w;
wh = displayMode.h;
printf("Window created in full screen mode: %dx%d\n", ww, wh);
// Load assets
assets_in();
float currentTime = 0.0f;
float accumulator = 0.0f;
SDL_Event event;
int running = 1;
// Main loop
while (running) {
// Event loop
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = 0;
}
if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
running = 0;
break;
default:
break;
}
}
}
// Timing and animation
float newTime = time_();
float deltaTime = newTime - currentTime;
currentTime = newTime;
accumulator += deltaTime;
if (accumulator >= FRAME_TIME) {
// Move to the next frame
cheetah_src.x += TZ_H;
// If we've reached the end of the row
if (cheetah_src.x > TZ_H * 3) {
cheetah_src.x = 0; // Reset to the start of the row
// Toggle between top and bottom row
cheetah_src.y = (cheetah_src.y == 0) ? TZ_V : 0;
}
// Reset accumulator, but keep remainder for smoother animation
accumulator -= FRAME_TIME;
}
// Rendering
SDL_SetRenderDrawColor(Renderer, 0, 0, 255, 255); // Blue background
SDL_RenderClear(Renderer);
if (cheetah == NULL) {
printf("Cheetah texture is NULL! Skipping render.\n");
}
else {
printf("Rendering cheetah...\n");
SDL_RenderCopy(Renderer, cheetah, &cheetah_src, &cheetah_dst);
}
SDL_RenderPresent(Renderer);
// Debugging output
printf("Current time: %f, Delta time: %f, Accumulator: %f\n", currentTime, deltaTime, accumulator);
printf("Cheetah source rect: x=%d, y=%d, w=%d, h=%d\n", cheetah_src.x, cheetah_src.y, cheetah_src.w, cheetah_src.h);
printf("Cheetah dest rect: x=%d, y=%d, w=%d, h=%d\n", cheetah_dst.x, cheetah_dst.y, cheetah_dst.w, cheetah_dst.h);
}
// Cleanup
assets_out();
exit_();
return EXIT_SUCCESS;
}`