Related
I would like to integrate images on a second window of my HMI. But it gives me black screens. I loaded the images, created the canvases, and I integrated them normally. I also put them in the right format (at the size of my canvas) but nothing helps, it doesn't work.
I tried to put a fl_enable_png back, which didn't work either, I've attached my code below.
#include <stdio.h>
#include <stdlib.h>
#include <forms.h>
#include <flimage.h>
#include "poinconneuse.h"
FL_FORM *form;
FL_FORM *menu_interaction;
FL_OBJECT *obj, *quit, *logs, *bouton_retour, *id, *pwd, *login, *frame, *frame_id, *frame_pwd, *explorer, *usb_menu, *transferer_menu; /*pour menus d'acceuil*/
FL_OBJECT *importer, *exporter, *supprimer, *transferer, *text_menu[4], *bouton_menu[4];/*pour menu intéractions*/
FL_OBJECT *vaub_canv, *canv_menu[5];/*pour image*/
FL_IMAGE *icones_menu[5];
FL_IMAGE *logo_vauban, *logo_delete, *logo_importer, *logo_envoyer, *logo_transferer; /*pour les images*/
char menu_actuel[60];
int i;
/*Callback fenêtre de connexion a réseau*/
void callback_menu(FL_OBJECT *login, long data)
{
fl_hide_form(form);
fl_show_form(menu_interaction, FL_PLACE_CENTER, FL_FULLBORDER, "Interactions");
for ( i = 0; i < 4; i++)
{
flimage_display(icones_menu[i], FL_ObjWin(canv_menu[i]));
}
sprintf(menu_actuel, "Intéraction");
}
void callback_id(FL_OBJECT *id, long data)
{
}
void callback_pwd(FL_OBJECT *pwd, long data)
{
}
void callback_retour(FL_OBJECT *bouton_retour, long data)
{
fl_hide_form(menu_interaction);
fl_show_form(form, FL_PLACE_CENTER, FL_FULLBORDER, 0);
}
void callback_importerusb(FL_OBJECT *usb_menu, long data)
{
fl_show_fselector("Rechercher le nom de votre fichier", "/home/kali/Desktop", "*.c", "");
}
void callback_transferer_acceuil(FL_OBJECT *transferer_menu, long data)
{
fl_show_fselector("Rechercher le nom de votre fichier", "/home/kali/Desktop/projet", "*.c", "");
}
void callback_boutoninterac(FL_OBJECT *bouton_menu, long data)
{
switch(data)
{
case 0: /* bouton importer */
fl_show_fselector("Rechercher le nom de votre fichier", "/home/kali/Desktop/projet", "*.c", "");
break;
case 1: /* bouton exporter */
fl_show_fselector("Rechercher le nom de votre fichier", "/home/kali/Desktop/projet", "*.c", "");
break;
case 2: /* bouton supprimer */
fl_show_fselector("Rechercher le nom de votre fichier", "/home/kali/Desktop/projet", "*.c", "");
break;
case 3: /* bouton transférer */
fl_show_fselector(" le nom de votre fichier", "/home/kali/Desktop/projet", "*.c", "");
break;
}
int main(int argc, char *argv[])
{
FL_FORM *form;
fl_initialize(&argc, argv, 0, 0, 0);
form = fl_bgn_form(FL_UP_BOX, 800, 480);
fl_set_form_background_color(form, FL_LEFT_BCOL);
vaub_canv = fl_add_canvas(FL_NORMAL_CANVAS, 550, 120, 150, 114,"");
flimage_enable_png();
frame = fl_add_box(FL_NO_BOX, 200, 20, 450, 40, "T\xE9l\xE9versement vers la poinconneuse ");
fl_set_object_lsize(frame, FL_LARGE_SIZE);
fl_set_object_lstyle(frame, FL_TIMESBOLD_STYLE);
logs = fl_add_box(FL_ROUNDED3D_UPBOX, 45, 85, 710, 370, 0);
fl_set_object_color(logs, FL_WHITE, FL_WHITE);
id = fl_add_input(FL_NORMAL_INPUT, 100, 150, 350, 50, "");
fl_set_object_color(id, FL_WHITE, FL_WHITE);
fl_set_object_lsize(id, FL_LARGE_SIZE);
fl_set_object_callback(id, callback_id, 0);
frame_id = fl_add_box(FL_NO_BOX, 100, 110, 120, 30, "Utilisateur");
fl_set_object_lsize(frame_id, FL_LARGE_SIZE);
fl_set_object_lstyle(frame_id, FL_TIMESBOLD_STYLE);
pwd = fl_add_input(FL_SECRET_INPUT, 100, 260, 350, 50, "");
fl_set_object_color(pwd, FL_WHITE, FL_WHITE);
fl_set_object_lsize(pwd, FL_LARGE_SIZE);
fl_set_object_callback(pwd, callback_pwd, 0);
frame_pwd = fl_add_box(FL_NO_BOX, 100, 225, 150, 30, "Mot de passe");
fl_set_object_lsize(frame_pwd, FL_LARGE_SIZE);
fl_set_object_lstyle(frame_pwd, FL_TIMESBOLD_STYLE);
login = fl_add_button(FL_NORMAL_BUTTON, 560, 260, 100, 50, "Se connecter");
fl_set_object_color(login, FL_SPRINGGREEN, FL_MCOL);
fl_set_object_lcolor(login, FL_BLACK);
fl_set_object_callback(login, callback_menu, 0);
usb_menu = fl_add_button(FL_ROUND3DBUTTON, 150, 375, 175, 50, "Importer depuis une\n cl\xE9 usb");
fl_set_object_color(usb_menu, FL_WHITE, FL_MCOL);
fl_set_object_lcolor(usb_menu, FL_BLACK);
fl_set_object_callback(usb_menu, callback_importerusb, 0);
transferer_menu = fl_add_button(FL_ROUND3DBUTTON, 450, 375, 175, 50, "Transf\xE9rer un fichier\n vers la machine");
fl_set_object_color(transferer_menu, FL_WHITE, FL_MCOL);
fl_set_object_lcolor(transferer_menu, FL_BLACK);
fl_set_object_callback(transferer_menu,callback_transferer_acceuil, 0);
logo_vauban = flimage_load("logo_vauban.png");
fl_end_form();
menu_interaction = fl_bgn_form(FL_UP_BOX, 800, 480);
fl_set_form_background_color(menu_interaction, FL_LEFT_BCOL);
int i;
char nom_menu[4][60] = {"IMPORTER", "EXPORTER", "SUPPRIMER", "TRANSFERER"};
char label[60];
icones_menu[0] = flimage_load("importer.png");
icones_menu[1] = flimage_load("exporter.png");
icones_menu[2] = flimage_load("delete.png");
icones_menu[3] = flimage_load("transferer.png");
for (i = 0; i < 4; i++)
{
int y, x;
if ( i <= 1 )
{
y = 30;
x = 60;
if ( i == 1 )
x = 400;
}
if( i > 1)
{
y = 250;
x = 60;
if ( i == 3)
x = 400;
}
canv_menu[i] = fl_add_canvas(FL_NORMAL_CANVAS, 50 + x , y, 175, 145, "");
sprintf(label, "%s", nom_menu[i]);
bouton_menu[i] = fl_add_button(FL_NORMAL_BUTTON, 50 + x, y, 175, 165, "");
fl_set_object_color(bouton_menu[i], FL_WHITE, FL_WHITE);
fl_set_object_callback(bouton_menu[i], callback_boutoninterac, i);
text_menu[i] = fl_add_text(FL_NORMAL_TEXT, 75 + x, y + 175, 110, 30, label);
fl_set_object_color(text_menu[i], FL_LEFT_BCOL, FL_LEFT_BCOL);
fl_set_object_align(text_menu[i], FL_ALIGN_CENTER);
fl_set_object_lstyle(text_menu[i], FL_TIMESBOLD_STYLE);
}
bouton_retour = fl_add_button(FL_NORMAL_BUTTON, 680, 15, 100, 75, "Page de\n connexion");
fl_set_object_color(bouton_retour, FL_LEFT_BCOL, FL_LEFT_BCOL);
fl_set_object_callback(bouton_retour, callback_retour, 0);
fl_end_form();
fl_show_form(form, FL_PLACE_CENTER, FL_FULLBORDER, NULL);
flimage_display(logo_vauban, FL_ObjWin(vaub_canv));
fl_do_forms();
fl_hide_form(form);
fl_finish();
return 0;
}
I've been trying to solve a segmentation fault since yesterday, it's driving me crazy...
So I've got this program that I use to implement the sokoban game, in which a map is given, and a plan like "NSEW" is given, meaning that I want the player to move north, then south, then etc... on the map given.
map* replay(map* map_loaded, int length, char* plan){
map* new_map=move(map_loaded,plan[0]);
map* old_map=deep_copy(new_map);
for (int i=1 ; i<length ; i++){
free(new_map->p_char);
free(new_map);
new_map=move(old_map,plan[i]);
free(old_map->p_char);
free(old_map);
old_map=deep_copy(new_map);
}
free(old_map->p_char);
free(old_map);
return new_map;
}
Map is a structure defined as following :
typedef struct map map;
struct map{
int width;
int height;
char* p_char;
};
The move function does one movement ;
The deep_copy makes a deep copy of a map struct :
map* deep_copy(map* map_loaded){
map* new_map=malloc(sizeof(map));
char* p_array=map_loaded->p_char;
int width=map_loaded->width;
int height=map_loaded->height;
new_map->width=width;
new_map->height=height;
char* p_new=malloc(sizeof(char)*width*height);
for (int i=0 ; i<width*height ; i++){
p_new[i]=p_array[i];
}
new_map->p_char=p_new;
return(new_map);
}
And what happens is that if I leave the code like that, if the length chosen ( the number of movements I want the player to do) is too high (depends on the map and the movements), when executing a replay.c program :
int main(int argc, char *argv[]){
if (argc != 4) {
fprintf(stderr, "You must provide a file name or enough elements!\n");
exit(EXIT_FAILURE);
}
map* map_loaded=load(argv[1]);
int length=atoi(argv[2]);
char* plan=argv[3];
map* new_map=replay(map_loaded,length,plan);
print_map(new_map);
free(new_map->p_char);
free(new_map);
free(map_loaded->p_char);
free(map_loaded);
return 1;
}
I get a segmentation fault... But if I do :
//free(old_map->p_char);
//free(old_map);
Everything works perfect !!
I really don't understand why... The problem is if I do those free valgrind tells me I don't have as many free as allocs, which is normal...
I would really appreciate any help given...
Thanks in advance if you've been brave enough to read me until this point !
Edit :
Here is my move function ;
map* move(map* map_loaded, char dir){
int pos=Position(map_loaded);
int width=map_loaded->width;
map* new_map=deep_copy(map_loaded);
char* p_new_array=new_map->p_char;
switch(dir){
case 'N':
if (p_new_array[pos-width]=='#'){ // Si il y a un mur au dessus
return(map_loaded);
}
if ((p_new_array[pos-width]=='$' && p_new_array[pos-2*width]=='$')
||(p_new_array[pos-width]=='$' && p_new_array[pos-2*width]=='*')
||(p_new_array[pos-width]=='*' && p_new_array[pos-2*width]=='$')
||(p_new_array[pos-width]=='*' && p_new_array[pos-2*width]=='*')){ //s'il y a 2 caisses au dessus
return(map_loaded);
}
if ((p_new_array[pos-width]=='$' && p_new_array[pos-2*width]=='#') //s'il y a une caisse au niveau -1 et un mur au niveau -2
||(p_new_array[pos-width]=='*' && p_new_array[pos-2*width]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos-width]=='$' || p_new_array[pos-width]=='*'){
if (p_new_array[pos-2*width]=='.'){
p_new_array[pos-2*width]='*';
}
else {
p_new_array[pos-2*width]='$';
}
if (p_new_array[pos-width]=='*'){
p_new_array[pos-width]='.';
}
else{
p_new_array[pos-width]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos-width]='#';
p_new_array[pos]='.';
}
else if (p_new_array[pos-width]=='.'){
p_new_array[pos-width]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos-width]='#';
p_new_array[pos]=' ';
}
break;
case 'S':
if (p_new_array[pos+width]=='#'){ // Si il y a un mur en dessous
return(map_loaded);
}
if ((p_new_array[pos+width]=='$' && p_new_array[pos+2*width]=='$')
||(p_new_array[pos+width]=='$' && p_new_array[pos+2*width]=='*')
||(p_new_array[pos+width]=='*' && p_new_array[pos+2*width]=='$')
||(p_new_array[pos+width]=='*' && p_new_array[pos+2*width]=='*')){//s'il y a 2 caisses au dessus
return(map_loaded);
}
if ((p_new_array[pos+width]=='$' && p_new_array[pos+2*width]=='#') //s'il y a une caisse au niveau +1 et un mur au niveau +2
||(p_new_array[pos+width]=='*' && p_new_array[pos+2*width]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos+width]=='$' || p_new_array[pos+width]=='*'){
if (p_new_array[pos+2*width]=='.'){
p_new_array[pos+2*width]='*';
}
else {
p_new_array[pos+2*width]='$';
}
if (p_new_array[pos+width]=='*'){
p_new_array[pos+width]='.';
}
else{
p_new_array[pos+width]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos+width]='#';
p_new_array[pos]='.';
}
else if (p_new_array[pos+width]=='.'){
p_new_array[pos+width]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos+width]='#';
p_new_array[pos]=' ';
}
break;
case 'W':
if (p_new_array[pos-1]=='#'){ // Si il y a un mur en dessous
return(map_loaded);
}
if ((p_new_array[pos-1]=='$' && p_new_array[pos-2]=='$')
||(p_new_array[pos-1]=='$' && p_new_array[pos-2]=='*')
||(p_new_array[pos-1]=='*' && p_new_array[pos-2]=='$')
||(p_new_array[pos-1]=='*' && p_new_array[pos-2]=='*')){ //s'il y a 2 caisses à gauche
return(map_loaded);
}
if ((p_new_array[pos-1]=='$' && p_new_array[pos-2]=='#') //s'il y a une caisse au niveau -1 et un mur au niveau -2
||(p_new_array[pos-1]=='*' && p_new_array[pos-2]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos-1]=='$' || p_new_array[pos-1]=='*'){
if (p_new_array[pos-2]=='.'){
p_new_array[pos-2]='*';
}
else {
p_new_array[pos-2]='$';
}
if (p_new_array[pos-1]=='*'){
p_new_array[pos-1]='.';
}
else{
p_new_array[pos-1]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos-1]='#';
p_new_array[pos]='.';
}
else if (p_new_array[pos-1]=='.'){
p_new_array[pos-1]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos-1]='#';
p_new_array[pos]=' ';
}
break;
case 'E':
if (p_new_array[pos+1]=='#') {// Si il y a un mur à droite
return(map_loaded);
}
if ((p_new_array[pos+1]=='$' && p_new_array[pos+2]=='$')
||(p_new_array[pos+1]=='$' && p_new_array[pos+2]=='*')
||(p_new_array[pos+1]=='*' && p_new_array[pos+2]=='$')
||(p_new_array[pos+1]=='*' && p_new_array[pos+2]=='*')){ //s'il y a 2 caisses à droite
return(map_loaded);
}
if ((p_new_array[pos+1]=='$' && p_new_array[pos+2]=='#') //s'il y a une caisse au niveau +1 et un mur au niveau +2
||(p_new_array[pos+1]=='*' && p_new_array[pos+2]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos+1]=='$' || p_new_array[pos+1]=='*'){
if (p_new_array[pos+2]=='.'){
p_new_array[pos+2]='*';
}
else {
p_new_array[pos+2]='$';
}
if (p_new_array[pos+1]=='*'){
p_new_array[pos+1]='.';
}
else{
p_new_array[pos+1]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos+1]='#';
p_new_array[pos]='.';
}
else if (p_new_array[pos+1]=='.'){
p_new_array[pos+1]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos+1]='#';
p_new_array[pos]=' ';
}
break;
}
return(new_map);
}
And here is the load function ;
char* Array_Creator(char* filename){
FILE* p_file = fopen(filename, "r");
char* p_array = NULL;
if (p_file == NULL) {
exit(EXIT_FAILURE);
}
else{
size_t size=1;
int c;
while (getc(p_file)!=EOF) {
size++;
}
fseek(p_file,0,SEEK_SET);
while ((c=getc(p_file))!='\n' && c!=EOF) { //on se débarasse de la première ligne
size--;
}
p_array=(char*)malloc(sizeof(char)*size);
if (p_array!=NULL) { //si jamais le malloc ne fonctionne pas
for(size_t i=0; i<size-1; i++) {
p_array[i]=(char)getc(p_file);
if (p_array[i] == '\n') { // si le caractère est une nouvelle ligne, on s'en sépare
i--; // on ajuste alors la taille et l'indice
size--;
}
}
p_array[size-1]='\0';
}
fclose(p_file);
}
return p_array;
}
//La fonction Dimensions permet de récupérer les dimensions d'une map
couple Dimensions(char *p_char){
FILE *p_file = NULL;
p_file=fopen(p_char, "r");
if (p_file == NULL) {
fprintf(stderr, "Cannot read file %s!\n", p_char);
exit(EXIT_FAILURE);
}
couple dim={0,0}; //la structure couple est déf dans le loader.h
int width = 0;
int height = 0;
int fscanf_result = 0;
fscanf_result = fscanf(p_file, "%d %d\n", &width, &height);
if (fscanf_result != 2) {
fprintf(stderr, "First line is not syntactically correct!\n");
exit(EXIT_FAILURE);
}
dim.x=width;
dim.y=height;
fclose(p_file);
return dim;
}
//La fonction Load est celle demandée et permettant de charger une carte ; elle utilise Dimensions et Array_Creator
map* load(char *filename){
map* map_loaded=malloc(sizeof(map)); //on alloue dynamiquement la map
//Dans un premier temps on récupère les dimensions
couple map_dim={0,0};
map_dim=Dimensions(filename);
map_loaded->width=map_dim.x;
map_loaded->height=map_dim.y;
//Dans un second temps on définit le tableau 1D contenant l'ensemble des éléments de la map
char* p_char=Array_Creator(filename);
map_loaded->p_char=p_char;
return map_loaded;
}
The command line is, for example :
./replay ./data/soko.in 4 7"NSWSESNWW"
In the move function, should change all
return(map_loaded); => return(new_map);
It will map_loaded to be freed twice when the move function returns map_loaded
Code analysis
map *replay(map *map_loaded, int length, char *plan)
{
map *new_map = move(map_loaded, plan[0]); // [2] set new_map to map_loaded
map *old_map = deep_copy(new_map);
for (int i = 1 ; i < length ; i++) {
free(new_map->p_char);
free(new_map); // [3] new_map be freed,
// equivalent map_loaded be freed
new_map = move(old_map, plan[i]);
...
}
...
return new_map;
}
int main(int argc, char *argv[])
...
map *map_loaded = load(argv[1]); // [1] map_loaded be malloc
...
map *new_map = replay(map_loaded, length, plan);
...
free(map_loaded->p_char);
free(map_loaded); // [4] map_loaded be freed
...
}
I'm creating a menu in my game (available when I hit escape on the keyboard)
But the black background created with SDL_Rect and the text aren't showing and I don't understand why.
When I run my program I can change the background images by pressing on the arrows (up, down, left and right), and when I hit esc, i can't do anything until I hit esc another time, and then I can continue changing the background color with the arrows on my keyboard.
Does anybody can help me with this?
#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL_image.h>
#include <SDL2/SDL_ttf.h>
#define CHOICEMENU 2
void errorMessage(const char *message);
void errorMessageImg(const char *message);
void errorMessageTtf(const char *message);
int printTextTtf(SDL_Surface* window, TTF_Font* mainFont, const char* text);
int displayMenu(SDL_Surface* window, TTF_Font* font);
int main( int argc, char **argv)
{
//Pointeurs de la SDL :
SDL_Window *window = NULL;
SDL_Surface *windowSurface = NULL;
SDL_Surface *image1,*image2, *image3, *image4 = NULL;
SDL_Surface *currentImage = NULL;
SDL_Surface *icon = NULL;
SDL_Renderer *renderer = NULL;
int menu;
int running;
TTF_Init(); //initialisation des textes
TTF_Font *mainFont = NULL;
mainFont = TTF_OpenFont("couriernew.ttf",30);
icon = IMG_Load("img/flask.png");
SDL_SetWindowIcon(window,icon);
if(SDL_Init(SDL_INIT_VIDEO) != 0){ //retourne 0 si Ok
errorMessage("Erreur lors de la creation de la fenêtre et du rendu");
}
window = SDL_CreateWindow("Jeu Antoine et Robin", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
windowSurface = SDL_GetWindowSurface(window);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC);
//texture = SDL_LoadBMP("ici.bmp");
image1 = SDL_LoadBMP("img/image1.bmp");
if(image1 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 1");
}
image2 = SDL_LoadBMP("img/image2.bmp");
if(image2 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 2");
}
image3 = SDL_LoadBMP("img/image3.bmp");
if(image3 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 3");
}
image4 = SDL_LoadBMP("img/image4.bmp");
if(image4 == NULL){
SDL_DestroyWindow(window);
errorMessage("Impossible de charger l'image 4");
}
currentImage = image1;
int isRunning = 1;
SDL_Event ev;
while(isRunning == 1){
while(SDL_PollEvent(&ev) != 0 ){
if(ev.type == SDL_QUIT){
isRunning = false;
}else if(ev.type == SDL_KEYDOWN){
switch(ev.key.keysym.sym){
case SDLK_UP:
currentImage = image1;
break;
case SDLK_RIGHT:
currentImage = image2;
break;
case SDLK_LEFT:
currentImage = image3;
break;
case SDLK_DOWN:
currentImage = image4;
break;
case SDL_QUIT:
isRunning = 0;
break;
case SDLK_ESCAPE:
menu = displayMenu(windowSurface,mainFont);
if(menu == 1){
isRunning = false;
}
break;
}
}
}
SDL_BlitSurface(currentImage, NULL, windowSurface, NULL);
SDL_UpdateWindowSurface(window);
}
TTF_CloseFont(mainFont);
SDL_FreeSurface(image1);
SDL_FreeSurface(image2);
SDL_FreeSurface(image3);
SDL_FreeSurface(image4);
SDL_DestroyWindow(window);
SDL_FreeSurface(icon);
SDL_DestroyRenderer(renderer);
currentImage = image1 = image2 = image3 = NULL;
window = NULL;
SDL_Quit();
return 0;
}
int displayMenu(SDL_Surface* window, TTF_Font* font){
int x,y; // coordonées de la souris
int i;
int nMenu = CHOICEMENU; //nb de choix
const char* choice[CHOICEMENU] = {"Continuer","Quitter"};
SDL_Surface* menus[CHOICEMENU]; // surface des menus
int selected[CHOICEMENU]={0,0}; // 0 car aucun selectionné pour le moment
SDL_Color colorMenu[2]={{127,122,204},{49,100,226}};
menus[0] = TTF_RenderText_Solid(font, choice[0], colorMenu[0]);
menus[1] = TTF_RenderText_Solid(font, choice[1], colorMenu[1]);
SDL_Rect pos[CHOICEMENU];
pos[0].x = window->clip_rect.w/2 /*= centre */ - menus[0]->clip_rect.w/2;
pos[0].y = window->clip_rect.h/2 - menus[0]->clip_rect.h;
pos[1].x = window->clip_rect.w/2 - menus[0]->clip_rect.w/2;
pos[1].y = window->clip_rect.h/2 + menus[0]->clip_rect.h;
SDL_FillRect(window,&window->clip_rect,SDL_MapRGB(window-
>format,0x00,0x00,0x00));
SDL_Event ev;
while(1){
while(SDL_PollEvent(&ev)){
switch(ev.type){
case SDL_QUIT:
for(i = 0; i < CHOICEMENU ; i++){
SDL_FreeSurface(menus[i]);
}
return 1;
case SDL_MOUSEMOTION: // coordonée souris
x = ev.motion.x;
y = ev.motion.y;
for(i = 0; i < CHOICEMENU; i++){
if(x >= pos[i].x && x<= pos[i].x+pos[i].w && y>=pos[i].y &&
y<=pos[i].y+pos[i].h){
if(!selected[i]){
selected[i] = 1;
SDL_FreeSurface(menus[i]); // on suppr l'ancienne
surface
menus[i] = TTF_RenderText_Solid(font, choice[i],
colorMenu[1]);
} else {
if(selected[i]){
selected[i] = 0;
SDL_FreeSurface(menus[i]); // on suppr
l'ancienne surface
menus[i] = TTF_RenderText_Solid(font, choice[i],
colorMenu[0]);
}
}
}
case SDL_MOUSEBUTTONDOWN: //si qqn a cliquer sur la souris :
x = ev.button.x;
y = ev.button.y;
for (i = 0; i < CHOICEMENU; i+=1){
if(x >= pos[i].x && x<= pos[i].x+pos[i].w && y>=pos[i].y &&
y<=pos[i].y+pos[i].h){
for(i = 0 ;i < CHOICEMENU; i++){
SDL_FreeSurface(menus[i]);
}
return i; // On retourne la valeur actuelle : ex : si je
clique sur "continue" ça return 1
}
}
break;
case SDL_KEYDOWN:
if(ev.key.keysym.sym == SDLK_ESCAPE){
for(i = 0 ;i < CHOICEMENU; i++){
SDL_FreeSurface(menus[i]);
}
return 0;
}
}
}
for(i = 0; i < CHOICEMENU; i+=1){
SDL_BlitSurface(menus[i],NULL,window,&pos[i]);
}
}
}
}
So, I have an image that I open in a window with SDL2. I want to implement a zoom function for the image that works as following: I click on two points of the image and I make a rectangle with those points as opposite corners. Then I make a copy of the rectangle and update the window to show the part of the image I selected, and this new image has a bigger width and height than the rectangle I chose because it will be the height and the width of the whole window.
I can detect the mouse clicks, and from the mouse clicks calculate the top left corner of the rectangle in x and y coordinates. However, I don't know how to make a copy of the pixels in those rectangles, nor how to make the window now show the zoomed in part. I've been googling a lot but I don't know what functions to use or how to code my own. How would I write such a function?
Here's what I have so far. The image I want to be able to zoom into is "map.jpg"
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = NULL;
window = SDL_CreateWindow("WarmingUp", TOP_LEFT_CORNER_X,
TOP_LEFT_CORNER_Y, IMAGE_WIDTH, IMAGE_HEIGHT, 0);
if(window == NULL){
printf("Erro a abrir janela gráfica\n");
exit(EXIT_FAILURE);
}
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL){
printf("Erro a criar renderer\n");
exit(EXIT_FAILURE);
}
SDL_Surface *jpgSurface = NULL;
jpgSurface = IMG_Load("map.jpg");
if(jpgSurface == NULL){
printf("Erro a abrir imagem\n");
exit(EXIT_FAILURE);
}
SDL_Texture *jpgTexture = NULL;
jpgTexture = SDL_CreateTextureFromSurface(renderer, jpgSurface);
if(jpgTexture == NULL){
printf("Erro a criar superfície através de imagem\n");
exit(EXIT_FAILURE);
}
SDL_FreeSurface(jpgSurface);
SDL_Event e;
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, jpgTexture, NULL, NULL);
while(!quit){
while(SDL_PollEvent(&e)){
if(e.type == SDL_QUIT)
quit = 1;
SDL_RenderPresent(renderer);
SDL_Delay(15);
SDL_DestroyTexture(jpgTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
I know that to make the mouse interaction in my while &eventloop I need to check for if ( event.type == SDL_MOUSEBUTTONUP ), and I can also show you the code to calculate the top left corner x and y position of the desired rectangle to be cropped, but I really can't go any further.
Here is modified code from question:
#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
#define IMAGE_WIDTH 1024
#define IMAGE_HEIGHT 768
int main(int argc, char **argv) {
(void)argc, (void)argv;
int quit = 0;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = NULL;
window = SDL_CreateWindow("WarmingUp",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
IMAGE_WIDTH, IMAGE_HEIGHT, 0);
if(window == NULL){
printf("Erro a abrir janela gráfica\n");
exit(EXIT_FAILURE);
}
SDL_Renderer *renderer = NULL;
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL){
printf("Erro a criar renderer\n");
exit(EXIT_FAILURE);
}
SDL_Surface *jpgSurface = NULL;
jpgSurface = IMG_Load("map.jpg");
if(jpgSurface == NULL){
printf("Erro a abrir imagem\n");
exit(EXIT_FAILURE);
}
SDL_Texture *jpgTexture = NULL;
jpgTexture = SDL_CreateTextureFromSurface(renderer, jpgSurface);
if(jpgTexture == NULL){
printf("Erro a criar superfície através de imagem\n");
exit(EXIT_FAILURE);
}
SDL_FreeSurface(jpgSurface);
SDL_Event e;
// rectangle to upscale in second window
const SDL_Rect srcrect = {600, 500, 250, 250};
SDL_Window *second_window = NULL;
SDL_Renderer *second_renderer = NULL;
SDL_Texture *magnified_fragment_texture = NULL;
while(!quit){
while(SDL_PollEvent(&e)){
if(e.type == SDL_QUIT ||
(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) {
quit = 1;
} else if(e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_t &&
!second_window) {
// create empty surface of adequate size
SDL_Surface *const surf = SDL_CreateRGBSurface(0, srcrect.w, srcrect.h, 32,
0xff000000, 0xff0000, 0xff00, 0xff);
SDL_FillRect(surf, NULL, 0);
// copy pixels
SDL_RenderReadPixels(renderer, &srcrect, SDL_PIXELFORMAT_RGBA8888,
surf->pixels, surf->pitch);
// error checking should be done...
second_window = SDL_CreateWindow("mag",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
srcrect.w*2, srcrect.h*2, 0);
second_renderer = SDL_CreateRenderer(second_window, -1, SDL_RENDERER_ACCELERATED);
magnified_fragment_texture = SDL_CreateTextureFromSurface(second_renderer, surf);
SDL_FreeSurface(surf);
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, jpgTexture, NULL, NULL);
SDL_RenderPresent(renderer);
if(second_renderer) {
const SDL_Rect dstrect = {0, 0, srcrect.w*2, srcrect.h*2};
SDL_RenderClear(second_renderer);
// RenderCopy scales texture to destination rect
SDL_RenderCopy(second_renderer, magnified_fragment_texture, NULL, &dstrect);
SDL_RenderPresent(second_renderer);
}
SDL_Delay(15);
}
SDL_DestroyTexture(jpgTexture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
In keypress event handler it creates second window/renderer/texture (not the best place for it), and later it renders second window if it exists.
I´m working on a small Microsoft paint-like program to learng VGA 256 color programming on C.
I have been able to plot a pixel when the user clicks on the screen and keep ploting the pixels while the mouse button is pressed. However if I move the mouse fast across the screen, I don´t get a continous line. Instead I get this result
How can I make the line be continous even when there are fast mouse movements?
Heres the code I have until now:
/**************************************************************************
* paint_screen *
* show main screen paint *
**************************************************************************/
void paint_screen(BITMAP *fondo){
int mantenido;
BITMAP barra,barra_color,normal_ptr_image;
int anterior_presionado;
word last_time;
word redraw,press,release;
sword dx,dy=0;
MOUSEBITMAP *mouse_new=NULL;
int i,done = 0;
accion =1;
/*Pintando fondo blanco*/
clear_screen();
/*Pintando barra de herramientas*/
load_bmp("normal.bmp",&normal_ptr_image);
load_bmp("mainbar.bmp",&barra);
load_bmp("colores.bmp",&barra_color);
set_pallete(fondo->pallete);
draw_bitmap(&barra,0,0);
draw_bitmap(&barra_color,0,180);
load_mouse(&mouse_g);
show_mouse(&mouse_g);
wait(50);
while(!done){
do { // check mouse status
anterior_presionado = press;
get_mouse_motion(&dx,&dy);
press = get_mouse_press(LEFT_BUTTON);
release = get_mouse_release(LEFT_BUTTON);
//Si el estado estaba presionado y no se ha soltado.. el boton esta mantenido
if(anterior_presionado==1 &&release==0){
mantenido =1;
}
} while (dx==0 && dy==0 && press==0 && release==0&&*my_clock==last_time);
if (release){
mouse_g.button1=0;
mantenido=0;
boton_soltado();
}
if (press){
mouse_g.button1=1;
boton_presionado();
}
//El boton se mantiene presionado
else if(mantenido){
boton_mantenido();
}
else{
release=1;
}
if (dx || dy) // calculate movement
{
new_x1 = mouse_g.x+dx;
new_y1 = mouse_g.y+dy; //Actualizamos posicion mouse
if (new_x1<0) new_x1=0;
if (new_y1<0) new_y1=0;
if (new_x1>319) new_x1=319;
if (new_y1>199) new_y1=199;
redraw=1;
}
if(redraw){
wait_for_retrace();
hide_mouse(&mouse_g);
if (mouse_new!=NULL) mouse_g.bmp=mouse_new;
mouse_g.x = new_x1;
mouse_g.y=new_y1;
show_mouse(&mouse_g);
redraw=0;
mouse_new=NULL;
}
if(new_x1>=287 && new_x1 <320
&& new_y1>=180 && new_y1 < 200 &&press){
set_mode(TEXT_MODE);
printf("Adios!!");
wait(25);
done=0;
return;
}
}
}
void realizar_accion(){
/*Caso1: Pintar pixel simple (lapiz)*/
if(accion==1){
plot_pixel(mouse_g.x,mouse_g.y,2);
plot_pixel(mouse_g.x-1,mouse_g.y,2);
plot_pixel(mouse_g.x,mouse_g.y-1,2);
plot_pixel(mouse_g.x-1,mouse_g.y-1,2);
}
}
void realizar_accion_mantenido(){
if(accion==1){
plot_pixel(mouse_g.x,mouse_g.y,2);
plot_pixel(mouse_g.x-1,mouse_g.y,2);
plot_pixel(mouse_g.x,mouse_g.y-1,2);
plot_pixel(mouse_g.x-1,mouse_g.y-1,2);
}
}
int sobre_barra(){
if(new_x1>0 && new_x1<33 &&new_y1>0 &&new_y1<181){
return 1;
}
else{
return -1;
}
}
void boton_mantenido(){
/*Verificar que este dento del buffer de dibujo....*/
if(sobre_barra()!=1){
realizar_accion_mantenido();
}
}
void boton_presionado(){
if(sobre_barra()==1){
cambiar_herramienta();
}
else{
realizar_accion();
}
}