Jump to content

SDL2 - Dúvidas


PsySc0rpi0n

Recommended Posts

Boas...

Andava aqui a ler uns tutoriais sobre SDL e estava a tentar criar uma janela com uma imagem! Estou apenas no início!

Mas a janela não está a carregar a imagem. Fica como que bloqueada e quando arrasto a janela ela fica com uma imagem do desktop como se fosse a imagem que eu carreguei!

Não sei se tem a ver com o facto de eu ter pegado numa imagem .jpg e a ter "Gravado Como" .bmp, estando a usar a função SDL_LoadBMP()...

Também já tentei mesmo abrir uma imagem .jpg no Gimp e exportar como .bmp em vez de fazer "Gravar Como" mas o resultado é o mesmo.

O código é este:


#include <stdio.h>
#include "SDL2/SDL.h"
#include <stdbool.h>

const int screenWidth = 1024;
const int screenHeight = 768;

bool sdl_Init(SDL_Window* pWindow, SDL_Surface* pSurface);
bool sdl_LoadMedia(SDL_Surface* pSurface, char* pfilepath);
void sdl_Close(SDL_Window* pWindow, SDL_Surface* pSurface);

int main(int argc, char** argv){
    SDL_Window* gWindow = NULL;
    SDL_Surface* gScreenSurface = NULL;
    SDL_Surface* gXOut = NULL;
    SDL_Event evt;
    bool quit = false;

    if( !sdl_Init(gWindow, gScreenSurface) ){
    	printf("Failed to initialise!\n");
    }else{
    	if( !sdl_LoadMedia(gXOut, "Devil_May_Cry_III.bmp") ){
    		printf("Failed to load media!\n");
    	}else{
    		while(!quit){
    			while(SDL_PollEvent (&evt) != 0){
    				if(evt.type == SDL_QUIT)
    					quit = true;
    			}
    			SDL_BlitSurface(gXOut, NULL, gScreenSurface, NULL);
    			SDL_UpdateWindowSurface(gWindow);
    		}
    	}
    }
    sdl_Close(gWindow, gXOut);
    return 0;
}




/***********************
**Function definitions**
************************/

bool sdl_Init(SDL_Window* pWindow, SDL_Surface* pSurface){
	bool success = true;

 	if(SDL_Init(SDL_INIT_VIDEO) < 0){
 		printf("SDL could not initialize! SDL_Error: %s!\n", SDL_GetError());
 		success = false;
 	}else{
 		pWindow = SDL_CreateWindow( "WindowZed fun",
 									SDL_WINDOWPOS_UNDEFINED,
 									SDL_WINDOWPOS_UNDEFINED,
 									screenWidth,
 									screenHeight,
 									SDL_WINDOW_SHOWN
								  );
 		if(pWindow == NULL){
 			printf("Window Could not be created! SDL Error: %s!\n", SDL_GetError());
 			success = false;
 		}else{
 			pSurface = SDL_GetWindowSurface(pWindow);
 		}
 	}
 	return success;
 }



bool sdl_LoadMedia(SDL_Surface* pSurface, char* pfilepath){
	bool success = true;

	pSurface = SDL_LoadBMP(pfilepath);
	if(pSurface == NULL){
		printf("Unable to load %s. SDL Error: %s!\n", pfilepath, SDL_GetError());
		success = false;
	}
	return success;
}



void sdl_Close(SDL_Window* pWindow, SDL_Surface* pSurface){
	SDL_FreeSurface(pSurface);
	pSurface = NULL;

	SDL_DestroyWindow(pWindow);
	pWindow = NULL;

	SDL_Quit();
}

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

Eu ainda só estou a copiar (e a adicionar uns pósitos) código de uns tutorias da net e por isso ainda estou a tentar perceber como funciona o SDL por isso não sei o que é isso do meu "ciclo run" nem onde é que estou a "assambarcar o cpu todo para mim". Troca lá isso por miúdos.

O "ciclo run" deve ser um dos whiles que eu lá tenho mas a outra expressão não faço ideia!

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

4 minutes ago, HappyHippyHippo said:

ciclo run: While(!quit)

Tentei assim mas o resultado é o mesmo:

#include <stdio.h>
#include "SDL2/SDL.h"
#include <stdbool.h>

const int screenWidth = 1024;
const int screenHeight = 768;

bool sdl_Init(SDL_Window* pWindow, SDL_Surface* pSurface);
bool sdl_LoadMedia(SDL_Surface* pSurface, char* pfilepath);
void sdl_Close(SDL_Window* pWindow, SDL_Surface* pSurface);

int main(int argc, char** argv){
    SDL_Window* gWindow = NULL;
    SDL_Surface* gScreenSurface = NULL;
    SDL_Surface* gXOut = NULL;
    SDL_Event evt;
    bool quit = false;

    if( !sdl_Init(gWindow, gScreenSurface) ){
    	printf("Failed to initialise!\n");
    }else{
    	if( !sdl_LoadMedia(gXOut, "Devil_May_Cry_III.bmp") ){
    		printf("Failed to load media!\n");
    	}else{
    		while(!quit){
    			while(SDL_PollEvent (&evt) != 0){
    				if(evt.type == SDL_QUIT)
    					quit = true;
    			}
    			SDL_BlitSurface(gXOut, NULL, gScreenSurface, NULL);
    			SDL_UpdateWindowSurface(gWindow);
                SDL_Delay(30);//         <---aqui
    		}
    	}
    }
    sdl_Close(gWindow, gXOut);
    return 0;
}




/***********************
**Function definitions**
************************/

bool sdl_Init(SDL_Window* pWindow, SDL_Surface* pSurface){
	bool success = true;

 	if(SDL_Init(SDL_INIT_VIDEO) < 0){
 		printf("SDL could not initialize! SDL_Error: %s!\n", SDL_GetError());
 		success = false;
 	}else{
 		pWindow = SDL_CreateWindow( "WindowZed fun",
 									SDL_WINDOWPOS_UNDEFINED,
 									SDL_WINDOWPOS_UNDEFINED,
 									screenWidth,
 									screenHeight,
 									SDL_WINDOW_SHOWN
								  );
 		if(pWindow == NULL){
 			printf("Window Could not be created! SDL Error: %s!\n", SDL_GetError());
 			success = false;
 		}else{
 			pSurface = SDL_GetWindowSurface(pWindow);
 		}
 	}
 	return success;
 }



bool sdl_LoadMedia(SDL_Surface* pSurface, char* pfilepath){
	bool success = true;

	pSurface = SDL_LoadBMP(pfilepath);
	if(pSurface == NULL){
		printf("Unable to load %s. SDL Error: %s!\n", pfilepath, SDL_GetError());
		success = false;
	}
	return success;
}



void sdl_Close(SDL_Window* pWindow, SDL_Surface* pSurface){
	SDL_FreeSurface(pSurface);
	pSurface = NULL;

	SDL_DestroyWindow(pWindow);
	pWindow = NULL;

	SDL_Quit();
}
Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

Afinal não percebi porque é que tinha o código mal @HappyHippyHippo.

Estou no work e não me recordo ao certo das alterações que se fizeram no code porque não o tenho aqui comigo. Mas sei que tinha ali uma confusão qualquer com os ponteiros porque acho que tinha que passar as variáveis [tt]gWindow[/tt], [tt]gScreenShot[/tt] e [tt]gXout[/tt] como ponteiro para ponteiro ou algo parecido!

Mas não percebi porquê!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

ok ... eu poderia te redireccionar para o tópico onde andas a reclamar da existência de uma variavel global, algo completamente ao lado do inteuito do código ... mas vou ficar por aqui

a regra é simples :
- quando queres que uma função retorne um valor por parâmetro, isto é, o retorno não é feito por resultado da função, mas sim por alteração de um valor dado como argumento da função, então passas um ponteiro para a região da memória a ser alterada.

tendo isso, como todas as tuas funções auxiliares fazem exactamente isso, deverás dar ponteiros para as variáveis. Como o tipo das tuas variáveis são "SDL_Surface *", então um ponteiro para isso é "SDL_Surface **"
 

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

57 minutes ago, HappyHippyHippo said:

ok ... eu poderia te redireccionar para o tópico onde andas a reclamar da existência de uma variavel global, algo completamente ao lado do inteuito do código ... mas vou ficar por aqui

a regra é simples :
- quando queres que uma função retorne um valor por parâmetro, isto é, o retorno não é feito por resultado da função, mas sim por alteração de um valor dado como argumento da função, então passas um ponteiro para a região da memória a ser alterada.

tendo isso, como todas as tuas funções auxiliares fazem exactamente isso, deverás dar ponteiros para as variáveis. Como o tipo das tuas variáveis são "SDL_Surface *", então um ponteiro para isso é "SDL_Surface **"
 

A outra thread, acho eu, não tem muito a ver com esta questão, mas ok! Adiante, senão já sei onde isto vai acabar!

Eu não percebo bem esse conceito. "SDL_Surface* gSurface" é um endereço de memória. Se eu passo para uma função a variável "gSurface", já estou a passar um endereço de memória, que por sinal é o endereço de memória usado pela variável gSurface dentro da função main! Então dentro da nova função eu teria acesso ao conteúdo da variável "gSurface" dentro da função main, mas parece que não é assim que funciona!

 

E depois, acho que em termos gerais a malta não entende bem (eu incluído) o uso dos operadores * e &. Nomeadamente quando o nível referenciamento/desreferencimaento (ou lá como se chama) aumenta.

Se eu declaro:

int i;

i é uma variável tipo inteiro

&i é o endereço de memória desta variável.

*i, não sei se existe ou se tem algum significado.

 

Se eu declaro:

int* i;

i, é um endereço de memória

&i é um endereço de memória diferente do anterior (tenho dúvidas aqui sobre que endereço é este)

*i, é o valor apontado por i.

 

E depois começa a aumentar o nível de referenciação/desreferenciação

int** i;

i é um endereço de memória de um endereço de memória.

&i é um endereço de memória de um endereço de memória de um endereço de memória

*i é um valor que é um endereço de memória

**i é o valor apontado por i...

Quer se queira quer não isto´começa a ser confuso a partir de um determinado nível!

"Ah e tal, complicam o que é simples!"... Cada um no seu galho!

E depois ainda posso divagar mais:

int i;

E isto:

&&i;

tem algum significado?

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

Bom, acho que era assim que ficava a funcionar bem...

Quando chegar a casa já vejo.

Spoiler

#include <stdio.h>
#include "SDL2/SDL.h"
#include <stdbool.h>

const int screenWidth = 1024;
const int screenHeight = 768;

bool sdl_Init(SDL_Window** pWindow, SDL_Surface** pSurface);
bool sdl_LoadMedia(SDL_Surface** pSurface, char* pfilepath);
void sdl_Close(SDL_Window** pWindow, SDL_Surface** pSurface);

int main(int argc, char** argv){
    SDL_Window* gWindow = NULL;
    SDL_Surface* gScreenSurface = NULL;
    SDL_Surface* gXOut = NULL;
    SDL_Event evt;
    bool quit = false;

    enum KeyPressSurfaces{
    	KEY_PRESS_SURFACE_DEFAULT,
    	KEY_PRESS_SURFACE_UP,
    	KEY_PRESS_SURFACE_DOWN,
    	KEY_PRESS_SURFACE_LEFT,
    	KEY_PRESS_SURFACE_RIHT,
    	KEY_PRESS_SURFACE_TOTAL
    };

    if( !sdl_Init(& gWindow, & gScreenSurface) ){
    	printf("Failed to initialise!\n");
    	exit(-1);
    }
	if( !sdl_LoadMedia(& gXOut, "Devil_May_Cry_III.bmp") ){
		printf("Failed to load media!\n");
		exit(-1);
	}
	while(!quit){
		while(SDL_PollEvent (&evt) != 0){
			if(evt.type == SDL_QUIT)
				quit = true;
		}
		SDL_BlitSurface(gXOut, NULL, gScreenSurface, NULL);
		SDL_UpdateWindowSurface(gWindow);
	}
    sdl_Close(& gWindow, & gXOut);
    return 0;
}




/***********************
**Function definitions**
************************/

bool sdl_Init(SDL_Window** pWindow, SDL_Surface** pSurface){
	bool success = true;

 	if(SDL_Init(SDL_INIT_VIDEO) < 0){
 		printf("SDL could not initialize! SDL_Error: %s!\n", SDL_GetError());
 		success = false;
 	}else{
 		*pWindow = SDL_CreateWindow( "WindowZed fun",
 									SDL_WINDOWPOS_UNDEFINED,
 									SDL_WINDOWPOS_UNDEFINED,
 									screenWidth,
 									screenHeight,
 									SDL_WINDOW_SHOWN
								  );
 		if(*pWindow == NULL){
 			printf("Window Could not be created! SDL Error: %s!\n", SDL_GetError());
 			success = false;
 		}else{
 			*pSurface = SDL_GetWindowSurface(*pWindow);
 		}
 	}
 	return success;
 }



bool sdl_LoadMedia(SDL_Surface** pSurface, char* pfilepath){
	bool success = true;

	* pSurface = SDL_LoadBMP(pfilepath);
	if(pSurface == NULL){
		printf("Unable to load %s. SDL Error: %s!\n", pfilepath, SDL_GetError());
		success = false;
	}
	return success;
}



void sdl_Close(SDL_Window** pWindow, SDL_Surface** pSurface){
	SDL_FreeSurface(* pSurface);
	* pSurface = NULL;

	SDL_DestroyWindow(* pWindow);
	* pWindow = NULL;

	SDL_Quit();
}

 

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

4 minutes ago, Flinger said:

Tenta o seguinte exercício. Faz uma função que te aloque dinamicamente (malloc) uma qualquer estrutura e retorna o apontador por referência para a main.

É a melhor forma de entenderes o porquê do **.

De uma forma mais simples **i é o apontado para uma variável onde guardas o apontador para outra variável.

Eu percebo isso, mas não no context do código que estava a fazer!

Se eu envio um endereço de uma variável com scope na função main para dentro dessa função e depois atribuo algum valor a esse endereço de memória, devia estar automaticamente a alterar o valor na função main porque foi o endereço da variável na função main que eu passei para dentro da função em questão!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

duas questões

void foo(int i) {
  i = 10;
}

int main (void) {
  int i = 0;
  foo (i);
  printf ("%d", i); // qual o valor apresentado ?
  return 0;
}
void foo(int * i) {
  * i = malloc(19);
}

int main (void) {
  int * i = 0;
  foo (i);
  printf ("%p", i); // qual o valor apresentado ?
  return 0;
}

novamente ... isto é matéria do outro post

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Não...Tu estás a enviar um valor para dentro da função. Esse valor vai ser exactamente o mesmo quando a função termina. No caso de um apontador, tu estás a enviar o endereço de uma variável. O endereço nunca muda, o que está escrito nesse endereço é que muda.Por isso é que se tu tiveres a função:

void incrementa(int x)
{
	x++;
}

Isto não funciona, certo? Porquê?

Agora pensa lá. Tu estás a inicializar a variável como SDL_Surface* gScreenSurface = NULL.

Se o endereço é 0, como vais obter o valor(endereço) certo no fim da função?

Link to comment
Share on other sites

O "x++; funciona, não é é actualizado na função que chamou a função "incrementa".

A questão é que se tentar imprimir a variável "gScreenSurface" sem * nem nada com %p vai mostrar o endereço da variável gScreenSurface e é isso que é enviado para dentro da função e supostamente esse endereço tem scope na função main e seria aí que o valor apontado por esse endereço ia ser alterado! Por isso é que não percebo bem a necessidade de enviar o & de uma variável do tipo int* ou whatever!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

@HappyHippyHippo, o Segundo exemplo dá segfault.

 

(gdb) bt
#0  0x00000000004006f9 in foo (i=0x0) at teste.c:5
#1  0x0000000000400719 in main () at teste.c:10

E isto tem só para aí 10% de matéria do outro post! Não vejo variáveis globais aqui, nem variáveis globais a serem devolvidas em funções, etc etc... Mas não quero ir por aqui, porque já sei o resultado!

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

1 minute ago, PsySc0rpi0n said:

@HappyHippyHippo, o Segundo exemplo dá segfault.

 


(gdb) bt
#0  0x00000000004006f9 in foo (i=0x0) at teste.c:5
#1  0x0000000000400719 in main () at teste.c:10

tira o * antes do i na atribuição do malloc ... desculpa ... mas mesmo assim a resposta deveria ser de cabeça

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Sim, eu acho que o que devia imprimir zero. No entanto se compilar e executar isso dá (nil).

Quando se faz:

int* i = 0;

não estamos a tentar forçar a que os valores que vão ser guardados em "i" fiquem no endereço de memória '0' (zero)?

Edited by PsySc0rpi0n

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

18 minutes ago, PsySc0rpi0n said:

Sim, eu acho que o que devia imprimir zero. No entanto se compilar e executar isso dá (nil).

Quando se faz:


int* i = 0;

não estamos a tentar forçar a que os valores que vão ser guardados em "i" fiquem no endereço de memória '0' (zero)?

sim ... mas isso é antes da chamada da função ... o printf é depois da função

agora diz, porque razão, apesar de enviar um ponteiro, e ser feito um malloc, o printf continua nil ?

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Não sei ao certo ao que respondeste "sim", mas a questão nesse exemplo que me causa dúvidas é o int* i = 0;

No meu entender, quando se faz:

int* i = 0;

já estamos a reservar o endereço de memória '0' para guardar um valor.

Depois dentro da outra função estamos de novo a alocar um bloco de memória para a variável i.

O que acontece é que está-se a tentar alterar o valor '0' para outro valor qualquer atribuído pelo malloc! (isto deve ser o que queres ouvir/ver/ler).

Mas posso dizer algo diferente que não sei também se é válido ou não que é esse código ao ser compilado, o compilador se queixar de estarmos a tentar reservar dois blocos de memória diferente para o mesmo nome 'i'.

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.