I have a little problem with SDL_Renderer. I can't understand why it doesn't work. Let's look at this example, it works fine:
bool running = true;
SDL_Window* window = SDL_CreateWindow("ASDF", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Texture* texture = IMG_LoadTexture(renderer, "asdf.bmp");
SDL_Event event;
while(running)
{
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE)
{
running = false;
}
break;
default:
break;
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
Then it comes to classes and when I pass the renderer through functions, it won't work anymore.
class Sprite
{
public:
Sprite(const std::string& path) : filePath(path) {};
~Sprite() { SDL_DestroyTexture(tex); };
void draw(SDL_Renderer* renderer);
private:
const std::string& filePath;
SDL_Texture* tex;
};
void Sprite::draw(SDL_Renderer* renderer)
{
printf("renderer sprite = %p\n", renderer);
tex = IMG_LoadTexture(renderer, filePath.c_str());
SDL_RenderCopy(renderer, tex, NULL, NULL);
}
int main(int argc, char **argv)
{
bool running = true;
SDL_Window* window = SDL_CreateWindow("ASDF", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Event event;
Sprite* sprite = new Sprite("asdf.bmp");
while(running)
{
printf("renderer main = %p\n", renderer);
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE)
{
running = false;
}
break;
default:
break;
}
}
SDL_RenderClear(renderer);
sprite->draw(renderer);
SDL_RenderPresent(renderer);
}
return 0;
}
The address of renderer is the same in main and in the draw function. I know that I'm probably making some sort of beginner's mistake here but i can't find it out.
The texture is being loaded every frame when you call sprite->draw.
You should move the line tex = IMG_LoadTexture(renderer, filePath.c_str()); to the constructor so that it is only loaded once.
The reason for this is that the texture will not be ready for rendering in the same frame that it is loaded.
As a side note you don't appear to be cleaning up the SDL_Window or SDL_Renderer with their respective destroy functions or calling SDL_Quit although I accept this may have been omitted for submitting the code example.
Related
The only thing I see is the RenderDrawColor.
Also the "circle.png" is in the right folder (where the main.cpp is).
#include <SDL.h>
#include <SDL_Image.h>
int main(int argc,char* args[]) {
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_PNG);
SDL_Window* window = SDL_CreateWindow("_", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(render,0, 255, 255, 255);
SDL_Surface* img = IMG_Load("circle.png");
SDL_Texture* texture = SDL_CreateTextureFromSurface(render, img);
SDL_FreeSurface(img);
SDL_Event event;
while (1) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
return 0;
}
}
SDL_RenderClear(render);
SDL_RenderCopy(render, texture, NULL, NULL);
SDL_RenderPresent(render);
}
system("PAUSE");
return 0;
}
Had to include zlib1.dll and libpng16-16.dll to the same folder as the cpp.
libpng16-16.dll depends on zlib1.dll.
I am extremely new to game development. I am attempting to move sprites on a window with SDL. I was using http://gamedevgeek.com/tutorials/moving-sprites-with-sdl/ as a reference for this to help me get a feel for SDL. However, this method of blit doesn't work with SDL2. I researched and found that I must convert surfaces to textures and render those, but I am running into some frustrating difficulties. When ran, the background image seems to render fine, but the sprite only appears in the corner of the window, and when moved, it seems to be overwritten by the background. Here is the code:
#include <iostream>
#include "stdafx.h"
#include <SDL.h>
#include <SDL_image.h>
const int WIDTH = 900;
const int HEIGHT = 360;
const int SPRITE_SIZE = 256;
int main(int argc, char *argv[])
{
SDL_Surface *imageSurface = NULL;
SDL_Surface *windowSurface = NULL;
SDL_Surface *temp = NULL;
SDL_Surface *sprite = NULL;
SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);
SDL_Rect rcSprite;
SDL_Rect gdSprite;
SDL_Event windowEvent;
SDL_Event event;
SDL_Renderer *renderer = NULL;
SDL_Texture *texture;
SDL_Texture *spriteTexture;
const Uint8 *keystate;
int colorkey;
int count;
int xPosition = 0;
int yPosition = 0;
int gameover = 0;
SDL_Window *window = SDL_CreateWindow("ABDUCTO", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_ALLOW_HIGHDPI);
windowSurface = SDL_GetWindowSurface(window);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
imageSurface = IMG_Load("farm.png");
sprite= IMG_Load("sprite6.png");
texture = SDL_CreateTextureFromSurface(renderer, imageSurface);
spriteTexture = SDL_CreateTextureFromSurface(renderer, sprite);
SDL_FreeSurface(sprite);
SDL_FreeSurface(imageSurface);
//rcSprite used as source rectangle, gdSprite as destination rectangle. Initialize them to the same position
rcSprite.x = xPosition;
rcSprite.y = yPosition;
rcSprite.w = SPRITE_SIZE;
rcSprite.h = SPRITE_SIZE;
gdSprite.x = xPosition;
gdSprite.y = yPosition;
gdSprite.w = SPRITE_SIZE;
gdSprite.h = SPRITE_SIZE;
while (!gameover)
{
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
gameover = 1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
case SDLK_q:
gameover = 1;
break;
}
break;
}
}
keystate = SDL_GetKeyboardState(NULL);
// When key pressed, update the destination rectangle
if (keystate[SDL_SCANCODE_LEFT]) {
gdSprite.x -= 2;
}
if (keystate[SDL_SCANCODE_RIGHT]) {
gdSprite.x += 2;
}
if (keystate[SDL_SCANCODE_UP]) {
gdSprite.y -= 2;
}
if (keystate[SDL_SCANCODE_DOWN]) {
gdSprite.y += 2;
}
if (gdSprite.x < 0) {
gdSprite.x = 0;
}
else if (gdSprite.x > WIDTH - SPRITE_SIZE) {
gdSprite.x = WIDTH - SPRITE_SIZE;
}
if(gdSprite.y < 0) {
gdSprite.y = 0;
}
else if (gdSprite.y > HEIGHT - SPRITE_SIZE) {
gdSprite.y = HEIGHT - SPRITE_SIZE;
}
//Render the window
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderCopy(renderer, spriteTexture, &rcSprite, &gdSprite);
SDL_RenderPresent(renderer);
//SDL_BlitSurface(imageSurface, NULL, windowSurface, NULL);
//SDL_BlitSurface(sprite, NULL, imageSurface, &rcSprite);
//SDL_UpdateWindowSurface(window);
//update the source rectangle to move with the sprite??
rcSprite.x = gdSprite.x;
rcSprite.y = gdSprite.y;
}
SDL_DestroyTexture(spriteTexture);
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
return 0;
SDL_Quit();
}
Any input is appreciated. Thank you.
probably has to do something with the path of your images, or copying the files into the resources on compilation.
are you on windows, osx or linux?
What IDE are you using?
But i noticed two things:
1)
Before the SDL_CreateWindow you should initialize SDL:
SDL_Init(SDL_INIT_EVERYTHING);
2)
SDL_Quit(); will never be called because one line above you quit the main function with return 0;
=> you should swap the lines!
noticed some more:
3) DON'T update the source rectangle to move with the sprite
just render the whole sprite to the gdSprite loction:
SDL_RenderCopy(renderer, sTexture, NULL, &gdSprite);
Here is some code in SMFL
RenderWindow window(VideoMode(320, 480), "The Game!");
Texture t1,t2,t3;
t1.loadFromFile("images/tiles.png");
t2.loadFromFile("images/background.png");
t3.loadFromFile("images/frame.png");
Sprite s(t1), background(t2), frame(t3);
Does SDL 2.0 has functions like this and how to convert them to SDL 2.0
yes, all is there:
https://programmersranch.blogspot.kr/2014/03/sdl2-animations-with-sprite-sheets.html
#include <SDL.h>
#include <SDL_image.h>
int main(int argc, char ** argv)
{
bool quit = false;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG);
SDL_Window * window = SDL_CreateWindow("SDL2 Sprite Sheets",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640,
480, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface * image = IMG_Load("spritesheet.png");
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
image);
while (!quit)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_FreeSurface(image);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return 0;
}
I am trying to make a simpler container for text in SDL by way of classes. The class is supposed to contain a pointer to an SDL_Texture and an SDL_Rect as well as some methods to get the information from the instances of the class. My problem arises when I try to blit the texture to the screen with the following function:
//Assume that renderer is already created
SDL_RenderCopy(renderer, texture.getTexture(), NULL, &texture.getRect());
The compiler brings my attention to the fourth parameter and states the following:
error: taking address of temporary [-fpermissive]
The code for my class is:
//Class
class Texture
{
private:
SDL_Texture* texture;
SDL_Rect rect;
public:
Texture(){/*Don't call any of the functions when initialized like this*/}
Texture(SDL_Texture* texure)
{
this->texture = texture;
}
SDL_Texture* getTexture()
{
return texture;
}
SDL_Rect getRect()
{
return rect;
}
void setRect(int posX, int posY, int scale, SDL_Texture* texture)
{
int textW = 0;
int textH = 0;
SDL_QueryTexture(texture, NULL, NULL, &textW, &textH);
this->rect = {posX,posY,textW*scale, textH*scale};
}
};
The code for my main program is:
//Main Program
TTF_Font* font = TTF_OpenFont("./PKMNRSEU.FON", 17);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
Texture texture(renderText(font, "Hello", white, renderer));
texture.setRect(100, 100, 5, texture.getTexture());
bool running = true;
Uint32 startingTick;
SDL_Event event;
while (running)
{
startingTick = SDL_GetTicks();
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
running = false;
break;
}
}
SDL_RenderCopy(renderer, texture.getTexture(), NULL, &texture.getRect());
SDL_RenderPresent(renderer);
clockTick(startingTick);
}
SDL_DestroyRenderer(renderer);
TTF_CloseFont(font);
I have also tried instantiating my object like this:
Texture* texture = new Texture(renderText(font, "Hello", white, renderer));
But I still get the same error. I suspect it is to do with the SDL_Rect not being a pointer.
Thanks in advance!
A simple solution could be to change the signature/implementation of getRect as follows:
SDL_Rect *getRect()
{
return ▭
}
Then you can call SDL_RenderCopy like this:
SDL_RenderCopy(renderer, texture.getTexture(), NULL, texture.getRect());
Solution:
Works when writing the whole image adress instead of only the name
I know I asked a similar question recently but I haven't got a solution yet. I'm trying to load a simple bmp picture to a window in c++ and SDL. This is my code:
int main(int argc, char *argv[])
{
//init
SDL_Init( SDL_INIT_EVERYTHING );
//screen window
SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, 32, SDL_SWSURFACE);
SDL_WM_SetCaption( WINDOW_TITLE, 0 );
//image
SDL_Surface *background = IMG_Load("images.png");
SDL_Event event;
bool gameRunning = true;
//loop
while (gameRunning)
{
if (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
gameRunning = false;
}
}
SDL_BlitSurface(background, NULL, screen, NULL);
//update screen
SDL_Flip(screen);
}
//quit
SDL_Quit();
return 0;
}
Is there anything wrong with my code or can be a problem with my computer? I know I have placed the image in the project folder and spelt it the right way.