I got an existing old project in C language with old version of SDL 1.2,
i am trying to make it run and after installing the SDL, I found out that my PC is 64 bit so I need the new SDL2, after re-installing the right SDL2, i configured the include lines to point to SDL2 folder instead of the old SDL and when i try to run I am receiving 2 errors:
1 - 'SDL_HWSURFACE' undeclared (first use in this function)
2 - 'SDL_SetColorKey' undeclared (first use in this function)
PS - working with MINGW compiler
any ideas?
I am attaching the code, but it is a long one...
/*
* GuiFramework.c
*
* Created on: 24 áñôè 2014
* Author: Ilias
*/
#include "GuiFramework.h"
static Control* root = NULL;
static SDL_Surface* surface = NULL;
static SDL_Surface* image = NULL;
static int click_x, click_y;
static Control* foundButton = NULL;
static int quit = FALSE;
static int enabled = FALSE;
static int visible = FALSE;
static int onlyEnabled = TRUE;
Control* allocControl() {
Control* control = malloc(sizeof(Control));
if (control == NULL) {
perror_message("malloc");
freeControls(root);
exit(0);
}
control->children = NULL;
control->parent = NULL;
control->next = NULL;
control->clip = NULL;
control->onClick = NULL;
control->onDraw = NULL;
control->enabled = TRUE;
control->visible = TRUE;
return control;
}
SDL_Rect* createRect(int x, int y, int w, int h) {
SDL_Rect* rect = malloc(sizeof(SDL_Rect));
if (rect == NULL) {
perror_message("malloc");
freeControls(root);
exit(0);
}
rect->w = w;
rect->h = h;
rect->x = x;
rect->y = y;
return rect;
}
Control* createButton(Control* parent, SDL_Rect* dim, SDL_Rect* clip, void (*func)(Control*), int enabled) {
Control* control = allocControl();
appendControl(parent, control);
control->type = BUTTON;
control->dim = dim;
control->abs = createRect(parent->abs->x + dim->x, parent->abs->y + dim->y, dim->w, dim->h);
control->clip = clip;
control->onClick = func;
control->visible = parent->visible;
control->enabled = enabled && control->visible;
return control;
}
Control* createPanel(Control* parent, SDL_Rect* dim, void (*func)(Control*), int visible) {
Control* control = allocControl();
appendControl(parent, control);
control->type = PANEL;
control->dim = dim;
control->abs = createRect(parent->abs->x + dim->x, parent->abs->y + dim->y, dim->w, dim->h);
control->onDraw = func;
control->visible = parent->visible && visible;
return control;
}
Control* createImage(Control* parent, SDL_Rect* dim, SDL_Rect* clip) {
Control* control = allocControl();
appendControl(parent, control);
control->type = IMAGE;
control->dim = dim;
control->abs = createRect(parent->abs->x + dim->x, parent->abs->y + dim->y, dim->w, dim->h);
control->clip = clip;
control->visible = parent->visible;
return control;
}
Control* createWindow(int width, int height, char* caption) {
Control* control = allocControl(NULL);
control->type = WINDOW;
control->dim = createRect(0, 0, width, height);
control->abs = createRect(0, 0, width, height);
/* Initialize the surface for resize issues */
if (surface != NULL) {
SDL_FreeSurface(surface);
}
surface = SDL_SetVideoMode(width, height, 0, SDL_HWSURFACE);
if (surface == NULL) {
printf("ERROR: failed to set video mode: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
/* Color the window background */
colorRect(control->dim, 0xFF, 0xFF, 0xFF);
SDL_WM_SetCaption(caption, caption);
return control;
}
void appendControl(Control* parent, Control* child) {
Control* currChild;
child->parent = parent;
/* Appends the control to the end list of the children of parent */
if (parent->children == NULL) {
parent->children = child;
} else {
currChild = parent->children;
while (currChild->next != NULL) {
currChild = currChild->next;
}
currChild->next = child;
}
}
void initializeSDL() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("ERROR: unable to init SDL: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
atexit(SDL_Quit);
}
void loadImage(char* name) {
SDL_Surface* loadedImage = SDL_LoadBMP(name);
if (loadedImage == NULL) {
printf("ERROR: unable to load image: %s\n", SDL_GetError());
exit(0);
}
image = loadedImage;
}
void colorRect(SDL_Rect* rect, int r, int g, int b) {
if (SDL_FillRect(surface, rect, SDL_MapRGB(surface->format, r, g, b)) < 0) {
printf("ERROR: failed to fill rect with color: %s\n", SDL_GetError());
freeControls(root);
exit(0);;
}
}
void drawBorders(SDL_Rect* rect, int width, int r, int g, int b) {
int i;
SDL_Rect* borderClips[4];
borderClips[0] = createRect(rect->x - width, rect->y - width, rect->w + 2 * width, width);
borderClips[1] = createRect(rect->x - width, rect->y - width, width, rect->h + 2 * width);
borderClips[2] = createRect(rect->x + rect->w, rect->y - width, width, rect->h + 2 * width);
borderClips[3] = createRect(rect->x - width, rect->y + rect->h, rect->w + 2 * width, width);
/* Draw Borders around given rect */
for (i = 0; i < 4; i++) {
colorRect(borderClips[i], r, g, b);
}
free(borderClips[0]);
free(borderClips[1]);
free(borderClips[2]);
free(borderClips[3]);
}
void optimizeImage() {
Uint32 colorKey;
SDL_Surface* optimizedImage = SDL_DisplayFormat(image);
SDL_FreeSurface(image);
if (optimizedImage == NULL) {
printf("ERROR: unable to optimize image: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
/* RGB: 250,255,255 is the key color */
colorKey = SDL_MapRGB(optimizedImage->format, 0xFA, 0xFF, 0xFF);
SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorKey);
image = optimizedImage;
}
void freeControls(Control* root) {
traverseTree(root, freeControl, TRUE);
if (quit) {
SDL_FreeSurface(image);
}
}
int freeControl(Control* control) {
if (control->dim != NULL) {
free(control->dim);
}
if (control->abs != NULL) {
free(control->abs);
}
free(control);
return 1;
}
void drawRoot() {
traverseTree(root, drawControl, FALSE);
/* After controls are drawn we flip */
if (SDL_Flip(surface) < 0) {
printf("ERROR: unable to flip screen: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
}
int drawControl(Control* control) {
if (control->visible) {
/* Draw if there is an onDraw function (used mostly by panels) */
if (control->onDraw != NULL) {
control->onDraw(control);
}
/* Draw also if there is an image to draw */
if (control->clip != NULL) {
if (SDL_BlitSurface(image, control->clip, surface, control->abs) < 0) {
printf("ERROR: unable to blit surface: %s\n", SDL_GetError());
freeControls(root);
exit(0);
}
}
}
return 1;
}
int setControlEnabled(Control* control) {
control->enabled = enabled && control->visible;
return 1;
}
int setControlVisible(Control* control) {
control->visible = visible;
return 1;
}
int findButton(Control* control) {
/* Check only if control is clickable */
if (control->onClick != NULL) {
if (click_x >= control->abs->x && click_x < control->abs->x + control->abs->w &&
click_y >= control->abs->y && click_y < control->abs->y + control->abs->h) {
if (!onlyEnabled || control->enabled) {
/* Found a button in the area, no need to keep looping */
foundButton = control;
return 0;
}
}
}
return 1;
}
int traverseTree(Control* control, int(*func)(Control*), int postOrder) {
Control* child;
Control* next;
int keepLooping = 1;
if (control != NULL) {
/* Perform func before recursion if not post order */
if (!postOrder && keepLooping) {
keepLooping = func(control);
}
/* Recurse the tree */
child = control->children;
while (child != NULL && keepLooping) {
next = child->next;
keepLooping = traverseTree(child, func, postOrder);
child = next;
}
/* Perform func after recursion if post order */
if (postOrder && keepLooping) {
keepLooping = func(control);
}
}
return keepLooping;
}
void handleEvents() {
SDL_Event e;
while (!quit) {
if (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) { /* A quit was detected */
quitGuiLoop();
} else if (e.type == SDL_MOUSEBUTTONDOWN) { /* Mouse click was detected */
if (e.button.button == SDL_BUTTON_LEFT) {
click_x = e.button.x;
click_y = e.button.y;
/* Find the button that was pressed */
onlyEnabled = TRUE;
traverseTree(root, findButton, TRUE);
if (foundButton != NULL) {
foundButton->onClick(foundButton);
foundButton = NULL;
}
}
}
drawRoot();
delay(10);
}
}
}
void delay(int ms) {
SDL_Delay(ms);
}
void quitGuiLoop() {
quit = 1;
}
Control* getControlByDimension(int x, int y) {
Control* control;
click_x = x;
click_y = y;
/* Find the button located at specified coordinates */
onlyEnabled = FALSE;
traverseTree(root, findButton, TRUE);
control = foundButton;
foundButton = NULL;
return control;
}
Control* getRoot() {
return root;
}
void setRoot(Control* newRoot) {
root = newRoot;
}
void setControlsVisible(Control* root, int visibleValue) {
visible = visibleValue;
traverseTree(root, setControlVisible, TRUE);
}
void setControlsEnabled(Control* root, int enabledValue) {
enabled = enabledValue;
traverseTree(root, setControlEnabled, TRUE);
}
Related
Can someone help me to increase the length of the snake and make it follow the head ?
I tried to develop a simple snake game without videos or help and did almost great but cannot figure out how to increase the size of the snake and move it properly.
I'd be very thankful
#include <SDL2/SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#define LOG(x) printf("%s\n", x)
#define LOG_ERROR(x) fprintf(stderr, "Error: %s\n", x)
#define LOG_SDL_ERROR(x) fprintf(stderr, "%s: %s\n", x, SDL_GetError())
#define global_variable static
#define internal_function static
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define HEAD_SIZE 30
#define APPLE_SIZE 25
#define MAX_LENGHT 10
typedef const char* string;
typedef float realNum;
typedef struct Snake
{
SDL_Rect body[MAX_LENGHT];
int xSpeed;
int ySpeed;
int site;
realNum xPos;
realNum yPos;
} Snake;
typedef struct Apple
{
int xPos;
int yPos;
int size;
} Apple;
void checkColissions(Apple *apple, Snake *snake );
bool initGame(void);
void update(realNum);
void handleEvent(SDL_Event);
void renderGame(void);
void gameOver(void);
void shutdownGame(void);
Snake makeSnake(void);
void renderSnake(Snake *snake);
void updateSnake(Snake *, realNum);
Apple makeApple();
void renderApple(Apple *);
global_variable bool Running;
global_variable SDL_Window *g_pWindow;
global_variable SDL_Renderer *g_pRenderer;
Snake *g_pSnake = NULL;
Apple *g_pApple = NULL;
int
main(int argc, char const *argv[])
{
srand((unsigned int)time(NULL));
atexit(shutdownGame);
if (!initGame())
{
LOG_ERROR("Failed Initialization");
exit(1);
}
else
{
Running = true;
int fps = 330;
int desiredDelta = 1000/fps;
SDL_Event event;
while (Running)
{
renderGame();
update(desiredDelta);
handleEvent(event);
SDL_Delay(rand() % 30);
}
}
return (EXIT_SUCCESS);
}
bool
initGame()
{
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
LOG_SDL_ERROR("Failed initialization: ");
return (false);
}
else
{
g_pWindow =
SDL_CreateWindow("Snake", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
g_pRenderer =
SDL_CreateRenderer(g_pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
g_pSnake = (Snake*)malloc(sizeof(Snake));
g_pApple = (Apple*)malloc(sizeof(Apple));
*g_pSnake = makeSnake();
*g_pApple = makeApple();
if ((g_pApple || g_pSnake || g_pRenderer || g_pWindow) == NULL)
{
return (false);
}
g_pWindow == NULL ? LOG_ERROR("Window failed") : LOG("Succes Window");
g_pRenderer == NULL ? LOG_ERROR("Renderer failed") : LOG("Succes Renderer");
g_pApple == NULL ? LOG_ERROR("Apple failed") : LOG("Succes Apple");
g_pSnake == NULL ? LOG_ERROR("Snake failed") : LOG("Succes Snake");
LOG("Game initialized");
}
return true;
}
void
renderGame()
{
SDL_SetRenderDrawColor(g_pRenderer, 0, 80, 0, 255);
SDL_RenderClear(g_pRenderer);
renderSnake(g_pSnake);
renderApple(g_pApple);
SDL_RenderPresent(g_pRenderer);
}
void update(realNum elapsed)
{
updateSnake(g_pSnake, elapsed);
checkColissions(g_pApple, g_pSnake);
}
void
handleEvent(SDL_Event event)
{
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_QUIT:
{
Running = false;
} break;
default:
break;
}
}
void
shutdownGame()
{
if (g_pWindow)
{
SDL_DestroyWindow(g_pWindow);
}
if (g_pRenderer)
{
SDL_DestroyRenderer(g_pRenderer);
}
if (g_pApple)
{
free(g_pApple);
}
if (g_pSnake)
{
free(g_pSnake);
}
SDL_Quit();
LOG("Game shutdowned");
}
Snake makeSnake(void)
{
const int speed = 0;
Snake snake = {
.xSpeed = speed,
.ySpeed = speed,
.xPos = SCREEN_WIDTH / 2,
.yPos = SCREEN_HEIGHT / 2,
.site = HEAD_SIZE
};
SDL_Rect SnakeRect = {
.h = snake.site,
.w = snake.site,
.x = snake.xPos,
.y = snake.yPos
};
snake.body[0] = SnakeRect;
return (snake);
}
void renderSnake(Snake *snake)
{
for (int i = 0; i < MAX_LENGHT; i++)
{
SDL_SetRenderDrawColor(g_pRenderer, 0, 0, 100, 255);
SDL_RenderFillRect(g_pRenderer, &snake->body[i]);
}
}
void updateSnake(Snake *snake, realNum elapsed)
{
const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
for (int i = 0; i < MAX_LENGHT; i++)
{
/* code */
snake->body[i].y += snake->ySpeed * elapsed;
snake->body[i].x += snake->xSpeed * elapsed;
}
/* code */
/* code */
/* code */
if (keyboardState[SDL_SCANCODE_W])
{
snake->ySpeed = -1;
snake->xSpeed = 0;
}
if (keyboardState[SDL_SCANCODE_D])
{
snake->ySpeed = 0;
snake->xSpeed = 1;
}
if (keyboardState[SDL_SCANCODE_A])
{
snake->ySpeed = 0;
snake->xSpeed = -1;
}
if (keyboardState[SDL_SCANCODE_S])
{
snake->ySpeed = 1;
snake->xSpeed = 0;
}
if (snake->body->x < 0 - HEAD_SIZE)
{
snake->body->x = SCREEN_WIDTH + HEAD_SIZE;
}
if (snake->body->x > SCREEN_WIDTH + HEAD_SIZE)
{
snake->body->x = 0 - HEAD_SIZE;
}
if (snake->body->y < 0 - HEAD_SIZE)
{
snake->body->y = SCREEN_HEIGHT + HEAD_SIZE;
}
if (snake->body->y > SCREEN_HEIGHT + HEAD_SIZE)
{
snake->body->y = 0 - HEAD_SIZE;
}
}
void
checkColissions(Apple *apple, Snake *snake )
{
SDL_Rect appleRect = {
.h = APPLE_SIZE,
.w = APPLE_SIZE,
.x = apple->xPos,
.y = apple->yPos
};
if (SDL_HasIntersection(&appleRect, snake->body))
{
*g_pApple = makeApple();
};
}
Can someone help me to increase the length of the snake and make it follow the head ?
Snake is defined by an array of coordinates, not just one (x,y). You need some kind of circular buffer, that can change capacity. Or you can just use an array, and then change every element of the array with every snake's move. And then you would realize that circular buffer is a really neat idea.
Once you have your buffer, be it an array or circular buffer, the question becomes how to move and enlarge the snake in it. It is simple. To move the snake you add one coordinate to the head, and remove one from the tail of the buffer. When the snake should become bigger you just don't remove the last element in the buffer. Add to the head, but don't remove the tail. This is how circular buffer would be handled. In case of a plain array moving means overwriting everything, and enlarging means adding to the beginning, and moving everything else by one place.
I've been working on a game with SDL2 and C, and this is my code so far:
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#define BLOCK_SIZE 50
#define SPEED 5
int initialize();
void handle_input();
void draw_player();
typedef struct {
SDL_Renderer *renderer;
SDL_Window *window;
bool running;
int FPS;
int width;
int height;
bool close_requested;
int input[256];
} Game;
Game game = {
.running = true,
.FPS = 60,
.width = 600,
.height = 600,
.close_requested = false,
.input = {},
};
SDL_Rect player = {
.x = 300,
.y = 300,
.w = BLOCK_SIZE,
.h = BLOCK_SIZE
};
int main(int argc, char* argv[]) {
initialize();
while(game.running && !game.close_requested) { //Game loop
SDL_SetRenderDrawColor(game.renderer, 0, 0, 0, 255);
SDL_RenderClear(game.renderer);
handle_input();
draw_player();
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
} //End of game loop
SDL_DestroyRenderer(game.renderer);
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}
int initialize() {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { //return 0 on success
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
game.window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, game.width, game.height, 0); //creates window
if (!game.window) {
printf("error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; //creates a renderer
game.renderer = SDL_CreateRenderer(game.window, -1, render_flags);
if (!game.renderer) {
printf("error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(game.window);
SDL_Quit();
return 1;
}
return 0;
}
void handle_input() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
//printf("input: %p code: %i\n", game.input, event.key.keysym.scancode);
if (event.type == SDL_KEYDOWN) {
game.input[event.key.keysym.scancode] = true;
//printf("True");
}
if (event.type == SDL_KEYUP) {
game.input[event.key.keysym.scancode] = false;
//printf("False");
}
if (game.input[SDL_SCANCODE_UP]) {
player.y -= SPEED;
} else if (game.input[SDL_SCANCODE_DOWN]) {
player.y += SPEED;
} else if (game.input[SDL_SCANCODE_LEFT]) {
player.x -= SPEED;
} else if (game.input[SDL_SCANCODE_RIGHT]) {
player.x += SPEED;
}
}
}
void draw_player() {
SDL_SetRenderDrawColor(game.renderer, 0, 200, 50, 255);
SDL_RenderFillRect(game.renderer, &player);
}
I'm using an array called int input[] within the typedef struct, and within the handle_input() function, I'm using the array like this:
if (event.type == SDL_KEYDOWN) {
game.input[event.key.keysym.scancode] = true;
}
if (event.type == SDL_KEYUP) {
game.input[event.key.keysym.scancode] = false;
}
So that I can easily check if a key is pressed like this:
if (game.input[SDL_SCANCODE_UP]) {
//do something
}
However, when this code is run, the movement is broken up and choppy, and there is a slight delay when you press the key down. I've set the SDL_Delay to 60 FPS, so this shouldn't be an issue with that. The issue must be with the way I'm handling the inputs. Why isn't the input code firing at a consistent and fast rate?
I am currently making a sdl2(/graphical) version of the game of life in C, so when the screen is resized I need to update the grid. When the screen is resized I don't want it to just change the size of the tiles, I want it to actually create more tiles. So I reallocate the cells list, which contains all of the cells states but for some odd reason that doesn't work.
bool updateCells(int w, int h) {
size_t x, y,
oldGridCol,
oldGridRow;
oldGridCol = gridCol;
oldGridRow = gridRow;
gridRow = w / gridSizeW;
gridCol = h / gridSizeH;
cells = (cellState_t *)realloc(cells, (gridRow * gridCol) * sizeof(cellState_t));
if(cells == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Memory allocation failed!");
return false;
}
for(y = 0; y < oldGridRow; y++) {
for(x = 0; x < oldGridCol; x++) {
writeCell(y, x, *(cells + (x + (y * oldGridCol))));
}
}
return false;
}
When this function is called the realloc function returns this:
malloc(): invalid size (unsorted)
Aborted
Thank you in advance!
I have made a minimal reproducible example of this program, which doesn't use SDL2, just plain C. Now for some reason this example works.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
typedef enum cellState {
dead,
live,
potentialDead,
potentialLive
} cellState_t;
size_t gridRow,
gridCol,
gridSizeW,
gridSizeH;
cellState_t *cells;
bool quitLoop;
bool initCells(void);
bool updateCells(int w, int h);
void writeCell(size_t row, size_t col, cellState_t state);
cellState_t readCell(size_t row, size_t col);
void die(const char *f, const size_t l, const char *fmt, ...);
int main(int argc, char *args[]) {
int w, h;
quitLoop = false;
gridSizeW = 25;
gridSizeH = 25;
// Let's assume that the window size is 640 by 480
gridRow = 640 / gridSizeW;
gridCol = 480 / gridSizeH;
if(!initCells())
die(__FILE__, __LINE__, "Failed to initialize cells!");
writeCell(1, 2, live);
writeCell(2, 3, live);
writeCell(3, 3, live);
writeCell(3, 2, live);
writeCell(3, 1, live);
while(!quitLoop) {
updateCells(640, 480);
printf("%d\n", readCell(1, 2));
}
return EXIT_SUCCESS;
}
bool initCells(void) {
cells = calloc((gridRow * gridCol), sizeof(cellState_t));
if(cells == NULL) {
return false;
}
return true;
}
bool updateCells(int w, int h) {
size_t x, y,
oldGridCol,
oldGridRow;
oldGridCol = gridCol;
oldGridRow = gridRow;
gridRow = w / gridSizeW;
gridCol = h / gridSizeH;
cells = (cellState_t *)realloc(cells, (gridRow * gridCol) * sizeof(cellState_t));
if(cells == NULL) {
return false;
}
for(y = 0; y < oldGridRow; y++) {
for(x = 0; x < oldGridCol; x++) {
writeCell(y, x, *(cells + (x + (y * oldGridCol))));
}
}
return false;
}
void writeCell(size_t row, size_t col, cellState_t state) {
*(cells + (col + (row * gridCol))) = state;
}
cellState_t readCell(size_t row, size_t col) {
return *(cells + (col + (row * gridCol)));
}
void die(const char *f, const size_t l, const char *fmt, ...) {
va_list vargs;
va_start(vargs, fmt);
fprintf(stderr, "error from file %s on line %ld: ", f, l);
//SDL_LogMessageV(SDL_LOG_CATEGORY_ERROR, SDL_LOG_PRIORITY_CRITICAL, fmt, vargs);
fputc('\n', stderr);
va_end(vargs);
exit(EXIT_FAILURE);
}
Maybe it's the window size variable that affects the outcome, or something like that.
But the full code doesn't work, here's the full code:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#define WINDOW_NAME "sdl-life"
#define WINDOWW 640
#define WINDOWH 480
typedef enum cellState {
dead,
live,
potentialDead,
potentialLive
} cellState_t;
SDL_Window *gWindow;
SDL_Renderer *gRenderer;
SDL_Texture *gLiveCellTexture,
*gGrid;
size_t gridRow,
gridCol,
gridSizeW,
gridSizeH;
cellState_t *cells;
bool quitLoop;
bool initSdl(void);
void closeSdl(void);
SDL_Texture *loadTexture(const char *path);
bool loadMedia(void);
bool initCells(void);
bool updateCells(int w, int h);
void writeCell(size_t row, size_t col, cellState_t state);
cellState_t readCell(size_t row, size_t col);
void displayCell(cellState_t status, SDL_Rect location);
void displayAllCells(void);
void die(const char *f, const size_t l, const char *fmt, ...);
int main(int argc, char *args[]) {
SDL_Event event;
int w, h;
quitLoop = false;
if(!initSdl())
die(__FILE__, __LINE__, "Failed to initialize SDL!");
if(!loadMedia())
die(__FILE__, __LINE__, "Failed to load media!");
SDL_GetWindowSize(gWindow, &w, &h);
gridSizeW = 25;
gridSizeH = 25;
gridRow = w / gridSizeW;
gridCol = h / gridSizeH;
if(!initCells())
die(__FILE__, __LINE__, "Failed to initialize cells!");
writeCell(1, 2, live);
writeCell(2, 3, live);
writeCell(3, 3, live);
writeCell(3, 2, live);
writeCell(3, 1, live);
SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0x00);
while(!quitLoop) {
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT)
quitLoop = true;
}
SDL_RenderClear(gRenderer);
SDL_GetWindowSize(gWindow, &w, &h);
updateCells(w, h);
displayAllCells();
SDL_RenderPresent(gRenderer);
}
closeSdl();
return EXIT_SUCCESS;
}
bool initSdl(void) {
SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, "The initialization process has begun");
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to initialize SDL: %s", SDL_GetError());
return false;
}
if(!IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to initialize SDL_image: %s", IMG_GetError());
return false;
}
if(TTF_Init() == -1) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to initialize SDL_ttf: %s", TTF_GetError());
return false;
}
gWindow = SDL_CreateWindow(WINDOW_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOWW, WINDOWH, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if(gWindow == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to create the window: %s", SDL_GetError());
return false;
}
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(gRenderer == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to create the renderer: %s", SDL_GetError());
return false;
}
SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, "The initialization has finished");
return true;
}
void closeSdl(void) {
SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, "SDL is shutting DOWN!");
free(cells);
SDL_DestroyTexture(gLiveCellTexture);
SDL_DestroyTexture(gGrid);
SDL_DestroyRenderer(gRenderer);
SDL_DestroyWindow(gWindow);
IMG_Quit();
TTF_Quit();
SDL_Quit();
}
SDL_Texture *loadTexture(const char *path) {
SDL_Texture *newTexture;
SDL_Surface *loadedSurface;
loadedSurface = IMG_Load(path);
if(loadedSurface == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to load surface: %s", IMG_GetError());
return NULL;
}
SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0x0, 0xff, 0xff));
newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
if(newTexture == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to convert surface to texture: %s", SDL_GetError());
return NULL;
}
SDL_FreeSurface(loadedSurface);
return(newTexture);
}
bool loadMedia(void) {
gLiveCellTexture = loadTexture("livecell.png");
if(gLiveCellTexture == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to load surface: %s", IMG_GetError());
return false;
}
gGrid = loadTexture("grid.png");
if(gGrid == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Failed to load surface: %s", IMG_GetError());
return false;
}
return true;
}
bool initCells(void) {
cells = calloc((gridRow * gridCol), sizeof(cellState_t));
if(cells == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Memory allocation failed!");
return false;
}
return true;
}
bool updateCells(int w, int h) {
size_t x, y,
oldGridCol,
oldGridRow;
oldGridCol = gridCol;
oldGridRow = gridRow;
gridRow = w / gridSizeW;
gridCol = h / gridSizeH;
cells = (cellState_t *)realloc(cells, (gridRow * gridCol) * sizeof(cellState_t));
if(cells == NULL) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Memory reallocation failed!");
return false;
}
for(y = 0; y < oldGridRow; y++) {
for(x = 0; x < oldGridCol; x++) {
writeCell(y, x, *(cells + (x + (y * oldGridCol))));
}
}
return false;
}
void writeCell(size_t row, size_t col, cellState_t state) {
*(cells + (col + (row * gridCol))) = state;
}
cellState_t readCell(size_t row, size_t col) {
return *(cells + (col + (row * gridCol)));
}
void displayCell(cellState_t status, SDL_Rect location) {
SDL_RenderCopy(gRenderer, gGrid, NULL, &location);
if(status == live) {
SDL_RenderCopy(gRenderer, gLiveCellTexture, NULL, &location);
}
}
void displayAllCells(void) {
size_t x, y;
SDL_Rect location;
location.w = gridSizeW;
location.h = gridSizeH;
location.x = 0;
location.y = 0;
for(y = 0; y < gridRow; y++) {
for(x = 0; x < gridCol; x++) {
displayCell(readCell(y, x), location);
location.x += location.w;
}
location.y += location.h;
location.x = 0;
}
}
void die(const char *f, const size_t l, const char *fmt, ...) {
va_list vargs;
va_start(vargs, fmt);
fprintf(stderr, "error from file %s on line %ld: ", f, l);
SDL_LogMessageV(SDL_LOG_CATEGORY_ERROR, SDL_LOG_PRIORITY_CRITICAL, fmt, vargs);
va_end(vargs);
closeSdl();
exit(EXIT_FAILURE);
}
My guess is that your problem occurs when you try to realloc cells to
gridRow * gridCol
since w / gridSizeW seems to be the amount of elements you want. Try:
cells = (cellState_t *)realloc(cells, (gridRow * gridCol) * sizeof(cellState_t));
Let's analize your code. The grid is a 2D-array named cells, which
you allocate dynamically basing on its dimensions which are kept in gridSizeW and gridSizeH.
Ideally to address a cell you use its coordinates which
would go from (1 to gridSizeW; 1 to gridSizeH) or instead, more commonly, from (0 to gridSizeW-1; 0 to gridSizeH-1).
Your routine to get the value of a cell is:
cellState_t readCell(size_t row, size_t col) {
return *(cells + (col + (row * gridCol)));
}
which implements the idea of taking the requested row number, multiply it for the width, and adding the column number. This is correct to turn a 2D address to a 1D one.
The problem is that your in-memory representation of the grid has nothing (or little) to do with the dimensions of the screen. If you have a grid 25 x 25 (you assign these as initial width and height), you must allocate 25*25 cells, no matter what SDL_GetWindowSize() returns to you.
Basically, you should always use gridSizeW and gridSizeH for coping with the cell pointer. You use instead gridRow and gridCol. Only when you update the screen, you perform a "scaling" of a row+column coordinate of then grid to an X+Y coordinate of the screen. So your readcell routine, assuming a 0-based numbering, should be:
cellState_t readCell(size_t row, size_t col) {
return *(cells + (col + (row * gridSizeW)));
// gridSizeW -------^
}
The variables gridRow and gridCol, which are the ratio of w/gridwidth and h/gridheight as you correctly wrote:
SDL_GetWindowSize(gWindow, &w, &h); // w+h: screen dimensions
gridSizeW = 25; // grid dimensions
gridSizeH = 25;
gridRow = w / gridSizeW; // screenwidth=250? then a cell is 10 pixels wide
gridCol = h / gridSizeH;
are to be used only when interfacing to SDL.
I am trying to programmatically change the VersionInfo attributes of a DLL file. I used this article as reference.
#include <iostream>
#include <stdio.h>
#include <windows.h>
int main(int argc, char** argv) {
LPCTSTR lpszFile = "E:\\_test\\rand_test\\test.dll";
DWORD dwHandle,
dwSize;
struct {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
// determine the size of the resource information
dwSize = GetFileVersionInfoSize(lpszFile, &dwHandle);
if (0 < dwSize)
{
unsigned char* lpBuffer = (unsigned char*) malloc(dwSize);
// Get whole VersionInfo resource/structure
GetFileVersionInfo(lpszFile, 0, dwSize, lpBuffer);
char strSubBlock[37]; // fits "\\StringFileInfo\\xxxxxxxx\\CompanyName\0"
LPTSTR pValueBuffer;
HANDLE hResource = BeginUpdateResource(lpszFile, FALSE);
if (NULL != hResource)
{
UINT uTemp;
// get the language information
if (!VerQueryValue(lpBuffer, "\\VarFileInfo\\Translation", (LPVOID *) &lpTranslate, &uTemp) != FALSE)
{
printf("Error 1\n");
return 1;
}
sprintf(strSubBlock, "\\StringFileInfo\\%04x%04x\\CompanyName", lpTranslate->wLanguage, lpTranslate->wCodePage);
if (!VerQueryValue(lpBuffer, (LPTSTR) ((LPCTSTR) strSubBlock), (LPVOID *) &pValueBuffer, &uTemp)) {
printf("Error 2\n");
return 1;
}
// PROBLEM!!!
// (pValueBuffer-lpBuffer) is 0x438 (longer than the Versioninfo resource!) but should be 0xB8
// so, pValueBuffer does not point to the actual company name.
ZeroMemory(pValueBuffer, strlen(pValueBuffer) * sizeof(TCHAR));
strcpy(pValueBuffer, "My Company, Inc."); // String may only become smaller or equal, never bigger than strlen(pValueBuffer)
if (UpdateResource(hResource,
RT_VERSION,
MAKEINTRESOURCE(VS_VERSION_INFO),
lpTranslate->wLanguage, // or 0
lpBuffer,
dwSize) != FALSE)
{
EndUpdateResource(hResource, FALSE);
}
}
free(lpBuffer);
}
return 0;
}
I think I have understood everything the code does. The plan is to read the Versioninfo block, then find the position where e.g. the CompanyName lies using VerQueryValue, then change the data, and then write it back using UpdateResource.
But there is a problem: VerQueryValue should output the position where the CompanyName string lies. But instead, it gives a pointer location, which is a few hundred bytes away, so it points somewhere outside the VersionInfo structure.
What am I doing wrong and how can I make it work?
(Also, does anybody know if there is a more elegant way to do this task, maybe even remove the limitation that the string has to be smaller or equal to the original?)
version resource this is serialized tree. if you want modify it - you need deserialize it to tree structure in memory, modify node, and serialize to new memory.
despite in msdn defined several Version Information Structures, really all it have common format
struct RsrcHeader
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[];
// aligned on 4*n
// BYTE Value[wValueLength]; // if (wType == 0)
// or
// WCHAR Value[wValueLength]; // if (wType == 1)
// every element aligned on 4*n
// RsrcHeader childs[];
};
so possible write common parse and serialize procedures
#if DBG
#define DBG_OPT(x) _CRT_UNPARENTHESIZE(x)
#else
#define DBG_OPT(x)
#endif
class RsrcNode
{
struct RsrcHeader
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[];
};
C_ASSERT(sizeof(RsrcHeader) == 6);
RsrcNode* _first, *_next;
PCWSTR _name;
const void* _pvValue;
ULONG _cbValue;
WORD _wValueLength;
WORD _wType;
DBG_OPT((PCSTR _prefix)); // only for debug output
public:
bool ParseResourse(PVOID buf, ULONG size, ULONG* pLength, PCSTR prefix);
RsrcNode(DBG_OPT((PCSTR prefix = "")))
: _next(0), _first(0) DBG_OPT((, _prefix(prefix)))
{
}
~RsrcNode();
bool IsStringValue() const
{
return _wType;
}
const void* getValue(ULONG& cb)
{
cb = _cbValue;
return _pvValue;
}
void setValue(const void* pv, ULONG cb)
{
_pvValue = pv, _cbValue = cb;
_wValueLength = (WORD)(_wType ? cb / sizeof(WCHAR) : cb);
}
RsrcNode* find(const PCWSTR strings[], ULONG n);
ULONG GetSize() const;
PVOID Store(PVOID buf, ULONG* pcb) const;
};
bool RsrcNode::ParseResourse(PVOID buf, ULONG size, ULONG* pLength, PCSTR prefix)
{
union {
PVOID pv;
RsrcHeader* ph;
ULONG_PTR up;
PCWSTR sz;
};
pv = buf;
if (size < sizeof(RsrcHeader) || (up & 3))
{
return false;
}
WORD wType = ph->wType;
ULONG wValueLength = ph->wValueLength, wLength = ph->wLength;
ULONG cbValue = 0;
switch (wType)
{
case 1:
cbValue = wValueLength * sizeof(WCHAR);
break;
case 0:
cbValue = wValueLength;
break;
default:
return false;
}
*pLength = wLength;
if (wLength > size || wLength < sizeof(RsrcHeader) || cbValue >= (wLength -= sizeof(RsrcHeader)))
{
return false;
}
wLength -= cbValue;
sz = ph->szKey, _name = sz;
do
{
if (wLength < sizeof(WCHAR))
{
return false;
}
wLength -= sizeof(WCHAR);
} while (*sz++);
DbgPrint("%s%S {\n", prefix, _name);
if (up & 3)
{
if (wLength < 2)
{
return false;
}
up += 2, wLength -= 2;
}
_wType = wType, _wValueLength = (WORD)wValueLength, _cbValue = cbValue, _pvValue = pv;
if (wValueLength && wType)
{
if (sz[wValueLength - 1])
{
return false;
}
DbgPrint("%s\t%S\n", prefix, sz);
}
if (wLength)
{
if (!*--prefix) return false;
up += wValueLength;
do
{
if (up & 3)
{
if (wLength < 2)
{
return false;
}
up += 2;
if (!(wLength -= 2))
{
break;
}
}
if (RsrcNode* node = new RsrcNode(DBG_OPT((prefix))))
{
node->_next = _first, _first = node;
if (node->ParseResourse(ph, wLength, &size, prefix))
{
continue;
}
}
return false;
} while (up += size, wLength -= size);
prefix++;
}
DbgPrint("%s}\n", prefix);
return true;
}
RsrcNode::~RsrcNode()
{
if (RsrcNode* next = _first)
{
do
{
RsrcNode* cur = next;
next = next->_next;
delete cur;
} while (next);
}
DBG_OPT((DbgPrint("%s%S\n", _prefix, _name)));
}
RsrcNode* RsrcNode::find(const PCWSTR strings[], ULONG n)
{
PCWSTR str = *strings++;
if (!str || !wcscmp(str, _name))
{
if (!--n)
{
return this;
}
if (RsrcNode* next = _first)
{
do
{
if (RsrcNode* p = next->find(strings, n))
{
return p;
}
} while (next = next->_next);
}
}
return 0;
}
ULONG RsrcNode::GetSize() const
{
ULONG size = sizeof(RsrcHeader) + (1 + (ULONG)wcslen(_name)) * sizeof(WCHAR);
if (_cbValue)
{
size = ((size + 3) & ~3) + _cbValue;
}
if (RsrcNode* next = _first)
{
do
{
size = ((size + 3) & ~3) + next->GetSize();
} while (next = next->_next);
}
return size;
}
PVOID RsrcNode::Store(PVOID buf, ULONG* pcb) const
{
union {
RsrcHeader* ph;
ULONG_PTR up;
PVOID pv;
};
pv = buf;
ph->wType = _wType;
ph->wValueLength = _wValueLength;
ULONG size = (1 + (ULONG)wcslen(_name)) * sizeof(WCHAR), cb;
memcpy(ph->szKey, _name, size);
up += (size += sizeof(RsrcHeader));
if (_cbValue)
{
up = (up + 3) & ~3;
memcpy(pv, _pvValue, _cbValue);
up += _cbValue;
size = ((size + 3) & ~3) + _cbValue;
}
if (RsrcNode* next = _first)
{
do
{
up = (up + 3) & ~3;
pv = next->Store(pv, &cb);
size = ((size + 3) & ~3) + cb;
} while (next = next->_next);
}
reinterpret_cast<RsrcHeader*>(buf)->wLength = (WORD)size;
*pcb = size;
return pv;
}
with this helper structure we can update version in next way:
#include "VerHlp.h"
BOOL UpdateVersion(PVOID pvVersion, ULONG cbVersion, PVOID& pvNewVersion, ULONG& cbNewVersion)
{
BOOL fOk = FALSE;
char prefix[16];
memset(prefix, '\t', sizeof(prefix));
prefix[RTL_NUMBER_OF(prefix) - 1] = 0;
*prefix = 0;
if (RsrcNode* node = new RsrcNode)
{
if (node->ParseResourse(pvVersion, cbVersion, &cbVersion, prefix + RTL_NUMBER_OF(prefix) - 1))
{
static const PCWSTR str[] = {
L"VS_VERSION_INFO", L"StringFileInfo", 0, L"CompanyName"
};
if (RsrcNode *p = node->find(str, RTL_NUMBER_OF(str)))
{
if (p->IsStringValue())
{
ULONG cb;
const void* pvCompanyName = p->getValue(cb);
DbgPrint("CompanyName: %S\n", pvCompanyName);
static WCHAR CompanyName[] = L"[ New Company Name ]";
if (cb != sizeof(CompanyName) ||
memcmp(pvCompanyName, CompanyName, sizeof(CompanyName)))
{
p->setValue(CompanyName, sizeof(CompanyName));
cbVersion = node->GetSize();
if (pvVersion = LocalAlloc(0, cbVersion))
{
node->Store(pvVersion, &cbNewVersion);
pvNewVersion = pvVersion;
fOk = TRUE;
}
}
}
}
}
delete node;
}
return fOk;
}
struct EnumVerData
{
HANDLE hUpdate;
BOOL fDiscard;
};
BOOL CALLBACK EnumResLangProc(HMODULE hModule,
PCWSTR lpszType,
PCWSTR lpszName,
WORD wIDLanguage,
EnumVerData* Ctx
)
{
if (HRSRC hResInfo = FindResourceExW(hModule, lpszType, lpszName, wIDLanguage))
{
if (HGLOBAL hg = LoadResource(hModule, hResInfo))
{
if (ULONG size = SizeofResource(hModule, hResInfo))
{
if (PVOID pv = LockResource(hg))
{
if (UpdateVersion(pv, size, pv, size))
{
if (UpdateResource(Ctx->hUpdate, lpszType, lpszName, wIDLanguage, pv, size))
{
Ctx->fDiscard = FALSE;
}
LocalFree(pv);
}
}
}
}
}
return TRUE;
}
ULONG UpdateVersion(PCWSTR FileName)
{
ULONG dwError = NOERROR;
EnumVerData ctx;
if (ctx.hUpdate = BeginUpdateResource(FileName, FALSE))
{
ctx.fDiscard = TRUE;
if (HMODULE hmod = LoadLibraryExW(FileName, 0, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE))
{
if (!EnumResourceLanguages(hmod, RT_VERSION,
MAKEINTRESOURCE(VS_VERSION_INFO),
(ENUMRESLANGPROCW)EnumResLangProc, (LONG_PTR)&ctx))
{
dwError = GetLastError();
}
FreeLibrary(hmod);
}
else
{
dwError = GetLastError();
}
if (!dwError && !EndUpdateResourceW(ctx.hUpdate, ctx.fDiscard))
{
dwError = GetLastError();
}
}
else
{
dwError = GetLastError();
}
return dwError;
}
I am looking through the code and i cant find solution for the problem of invalid renderer. I am beginner with SDL2 and i have to write code in pure C.
I think that in my code there is more errors but because of this one i cant go further. Code is half in polish language so if u cant get what is where i can rewrite this a bit . Problem occure when in main i try to load function"Odczyt_z_Pliku". Probably somewhere there is a problem.
SDL_GetError() says" invalid renderer.
#include<SDL.h>
#include<stdio.h>
#include<SDL_image.h>
#pragma warning(disable : 4996)
#define WYSOKOSC_EKRANU 768
#define SZEROKOSC_EKRANU 1024
typedef enum bool{
false,true
}bool;
typedef struct sTekstura {
int wysokosc;
int szerokosc;
SDL_Texture *Tekstura;
}sTekstura;
void IniTekstury(sTekstura T)
{
T.wysokosc = 0;
T.szerokosc = 0;
T.Tekstura = NULL;
}
void free(sTekstura T)
{
//Free texture if it exists
if (T.Tekstura != NULL)
{
SDL_DestroyTexture(T.Tekstura);
T.Tekstura = NULL;
T.szerokosc = 0;
T.wysokosc = 0;
}
}
int Odczyt_z_Pliku(char nazwa[50],sTekstura T,SDL_Renderer* Renderer)
{
free(T);
SDL_Texture* nTekstura = NULL;
//Load image at specified path
SDL_Surface* Powierzchnia = IMG_Load(nazwa);
if (Powierzchnia == NULL)
{
printf("Unable to load image %s! SDL_image Error: %s\n", nazwa, IMG_GetError());
}
else
{
SDL_SetColorKey(Powierzchnia, SDL_TRUE, SDL_MapRGB(Powierzchnia->format, 0xFF, 0xFF, 0xFF));
//Create texture from surface pixels
nTekstura = SDL_CreateTextureFromSurface(Renderer, Powierzchnia);
if (nTekstura == NULL)
{
printf("Unable to create texture from %s! SDL Error: %s\n", nazwa, SDL_GetError());
}
else
{
//Get image dimensions
T.szerokosc = Powierzchnia->w;
T.wysokosc = Powierzchnia->h;
}
//Get rid of old loaded surface
SDL_FreeSurface(Powierzchnia);
}
//Return success
T.Tekstura = nTekstura;
if (T.Tekstura != NULL)
{
return 1;
}
else
{
return 0;
}
}
bool Inicjalizacja(SDL_Window *Okno,SDL_Renderer *Renderer)
{
//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
Okno = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SZEROKOSC_EKRANU, WYSOKOSC_EKRANU, SDL_WINDOW_SHOWN);
if (Okno == NULL)
{
printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
success = false;
}
else
{
//Create renderer for window
Renderer = SDL_CreateRenderer(Okno, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
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;
}
}
}
}
return success;
}
void setBlendMode(sTekstura T, SDL_BlendMode blending) //MK: Funkcja ustawiająca przezroczystosc
{
//Set blending function
SDL_SetTextureBlendMode(T.Tekstura, blending);
}
void setAlpha(sTekstura T,Uint8 alpha) //MK: Funkcja ustawiająca przezroczystość
{
//Modulate texture alpha
SDL_SetTextureAlphaMod(T.Tekstura, alpha);
}
void render(int x, int y,sTekstura T,SDL_Renderer *Renderer)
{
//Set rendering space and render to screen
SDL_Rect renderQuad = { x, y, T.szerokosc, T.wysokosc };
SDL_RenderCopy(Renderer, T.Tekstura, NULL, &renderQuad);
}
int main(int argc, char *argv[])
{
SDL_Window * Okno = NULL;
SDL_Renderer* Renderer = NULL;
sTekstura TloMenu;
TloMenu.szerokosc = 0;
TloMenu.wysokosc = 0;
TloMenu.Tekstura = NULL;
sTekstura TloGra;
TloGra.szerokosc = 0;
TloGra.wysokosc = 0;
TloGra.Tekstura = NULL;
sTekstura Pudlo;
Pudlo.szerokosc = 0;
Pudlo.wysokosc = 0;
Pudlo.Tekstura = NULL;
sTekstura Sciana;
Sciana.szerokosc = 0;
Sciana.wysokosc = 0;
Sciana.Tekstura = NULL;
sTekstura StartGry;
StartGry.szerokosc = 0;
StartGry.wysokosc = 0;
StartGry.Tekstura = NULL;
sTekstura KoniecGry;
KoniecGry.szerokosc = 0;
KoniecGry.wysokosc = 0;
KoniecGry.Tekstura = NULL;
SDL_Event e;
//Start up SDL and create window
if (!Inicjalizacja(Okno,Renderer))
{
printf("Failed to initialize!\n");
}
else
{
if(!Odczyt_z_Pliku("MENU BOMBERMAN.png", Sciana, Renderer))
{
puts("Nie wczytano kostki");
return 0;
}
if (!Odczyt_z_Pliku("pudlo3.bmp", Pudlo, Renderer))
{
puts("Nie wczytano pudla");
return 0;
}
if (!Odczyt_z_Pliku("MenuBomberman.bmp", TloMenu, Renderer))
{
puts("Nie wczytano menu");
return 0;
}
if (!Odczyt_z_Pliku("Mapa.bmp", TloGra, Renderer))
{
puts("Nie wczytano mapy");
return 0;
}
if (!Odczyt_z_Pliku("NEW GAME.bmp", StartGry, Renderer))
{
puts("Nie wczytano napisu nowej gry");
return 0;
}
else
{
//Set standard alpha blending
setBlendMode(StartGry, SDL_BLENDMODE_BLEND);
}
if (!Odczyt_z_Pliku("exitgimp.bmp", KoniecGry, Renderer))
{
puts("Nie wczytano napisu koniec gry");
return 0;
}
else
{
//Set standard alpha blending
setBlendMode(StartGry, SDL_BLENDMODE_BLEND);
}
//Main loop flag
bool quit = false;
//Modulation component
Uint8 AlphaStartu = 255;
Uint8 AlphaKonca = 127;
//While application is running
while (!quit)
{
//Handle events on queue
while (SDL_PollEvent(&e) != 0)
{
//User requests quit
if (e.type == SDL_QUIT)
{
quit = true;
}
//Handle key presses
else if (e.type == SDL_KEYDOWN)
{
//Increase alpha on w
if (e.key.keysym.sym == SDLK_w)
{
AlphaKonca = 127;
AlphaStartu = 255;
}
//Decrease alpha on s
else if (e.key.keysym.sym == SDLK_s)
{
AlphaKonca = 256;
AlphaStartu = 127;
}
}
}
//Clear screen
SDL_SetRenderDrawColor(Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderClear(Renderer);
//Render background
render(0, 0, TloMenu, Renderer);
//Render front blended
setAlpha(KoniecGry,AlphaKonca);
setAlpha(StartGry, AlphaStartu);
render(0, 0,StartGry,Renderer);
render(0, 0,KoniecGry,Renderer);
//Update screen
SDL_RenderPresent(Renderer);
}
}
//Free resources and close SDL
close();
return 0;
}
When you get to Odczyt_z_Pliku, Renderer is still a NULL pointer.
As it stands, in your main() function you have a variable Renderer of type SDL_Renderer* (initialized to NULL). You then pass that value NULL into SDL_Renderer* which also takes an argument of type SDL_Renderer*.
However, in C this is just a pass by copy of the value of the pointer itself (not the value pointed to by the pointer). In other words, the argument Renderer to your function just creates a local variable in that function. So in Odczyt_z_Pliku when you do Renderer = SDL_CreateRenderer(...); that may return a new pointer but it's only assigning it to the local variable Renderer, but this has no effect on the Renderer variable in your main() function.
In C, the way to write a function that sets the value of a pointer that is a local variable in the calling function is to use a double pointer. That is, change the signature of Inicjalizacja to
bool Inicjalizacja(SDL_Window **Okno, SDL_Renderer **Renderer)
then in main() (or wherever else) call it like:
SDL_Window * Okno = NULL;
SDL_Renderer* Renderer = NULL;
...
if (!Inicjalizacja(&Okno, &Renderer)) {
...
}
and so on. (Note: You made the same mistake with the SDL_Window Okno as well, and possibly elsewhere--I haven't read the full code).
The syntax &Okno means pass the address of (i.e. a pointer to) the variable Okno. Since Okno is itself a pointer, the address of the pointer is a double pointer.
Then in Inicjalizacja write:
*Renderer = SDL_CreateRenderer(...);
and similarly with Okno. The *Renderer syntax (which I find somewhat confusing) means the value pointed to by a pointer. Since Renderer here is a double pointer, this means assign the single pointer (of type Renderer*) into the pointer pointed to by Renderer. Now the Renderer* pointer in your main() function will be properly initialized.
Note, similarly you should change the following check to:
if (*Renderer == NULL) {...}
and so on. We know Renderer != NULL since it's a pointer to a local variable allocated in our main() function. The interesting question is what value SDL_CreateRenderer returned, so we want to look at *Renderer.