Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SDL(1.2)]Clicker dans une zone précise

Sujet résolu
19 juin 2020 à 18:14:21

Bonjour, 

je code en C depuis un certain temps, et j'en viens maintenant à utiliser la SDL. pour un programme censé m'aider à résoudre plus facilement mais exercices en trigonométrie, j'ai besoin de détecter si l'utilisateur clic sur une zone précise du triangle. Pour l'instant, je me suis occupé que d'un seul cas : s'il clic sur l'angle ABC. mais, même si j'ai vérifié moi même que les coordonnées coïncident, il n'entre pas dans la boucle if...

le code :

/*Résolveur d'exercice trigonométrie*/

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "pause.h"

void affTriangle(SDL_Surface *ecran,
		 SDL_Surface *triangle,
		 SDL_Rect positionTriangle){
  SDL_FillRect(ecran,NULL, SDL_MapRGB(ecran->format, 255,255,255));
  triangle = IMG_Load("/home/alexandre/C/math/triangle-rect.png");
  positionTriangle.x = LENGTH/2 - triangle->w/2;
  positionTriangle.y = WIDTH/2 - triangle->h/2;
  positionTriangle.y -= WIDTH/6;
  SDL_BlitSurface(triangle, NULL, ecran, &positionTriangle);
}
 
void main(){
  SDL_Surface *ecran = NULL;
  SDL_Surface *triangle = NULL, *texte = NULL;
  SDL_Rect positionTriangle, positionTexte;
  TTF_Font *police = NULL;
  SDL_Color noir = {0,0,0};

  

  TTF_Init();
  SDL_Init(SDL_INIT_VIDEO);
  ecran = SDL_SetVideoMode(LENGTH,WIDTH,32,SDL_HWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF);

  affTriangle(ecran, triangle, positionTriangle);

  police = TTF_OpenFont("/home/alexandre/C/SDL/polices/vibur.ttf", 25);
  texte = TTF_RenderText_Blended(police, "Voici le triangle ABC, rectangle en A",noir);
  positionTexte.x = LENGTH/2 - texte->w/2;
  positionTexte.y = WIDTH/2 - texte->h/2;
  positionTexte.y += WIDTH/5 - WIDTH/12;
  SDL_BlitSurface(texte, NULL, ecran, &positionTexte);  
  SDL_Flip(ecran);
  SDL_Delay(5000);

  int continuer = 1;
  int change = 0;
  SDL_Event event;

  while(continuer){
    SDL_PollEvent(&event);
    switch(event.type){
    case SDL_QUIT:                        //clic sur la croix rouge 
      continuer = 0;
      break;
    case SDL_KEYDOWN:                      //on a pressé une touche du clavier
      switch(event.key.keysym.sym){
      case SDLK_ESCAPE:                     //touche Échap
	continuer = 0;
	break;
      }
      break;
    case SDL_MOUSEBUTTONUP:              //on a cliqué avec la souris
      switch(event.button.button){
      case SDL_BUTTON_LEFT:            //clic gauche
        if(event.button.x <= 214 && event.button.x >= 172
	   && event.button.y <= 249 && event.button.y >=224){
	  change = 1;
	  affTriangle(ecran, triangle, positionTriangle);
	}
	  
	break;
      }
      break;
    }
      if(!change){
	affTriangle(ecran,triangle,positionTriangle);
	SDL_FreeSurface(texte);
	texte = TTF_RenderText_Blended(police,"Veuillez clicker sur l'angle ou la longueur à calculer.", noir);
        positionTexte.x = LENGTH/2 - texte->w/2;
	positionTexte.y = WIDTH/2 - texte->h/2;
	positionTexte.y += WIDTH/5 - WIDTH/12;
	SDL_BlitSurface(texte,NULL,ecran,&positionTexte);
	SDL_Flip(ecran);
      }
  }

  TTF_CloseFont(police);
  TTF_Quit();
  SDL_FreeSurface(texte);
  SDL_FreeSurface(triangle);
  SDL_Quit();
}

une solution ????

-
Edité par alexpatt 19 juin 2020 à 18:15:43

  • Partager sur Facebook
  • Partager sur Twitter
19 juin 2020 à 19:34:34

Salut,

Je suis quasi-sûr que l.65 c'est non pas SDL_MOUSEBUTTONUP mais SDL_MOUSEBUTTONDOWN.

EDIT : Je dis n'importe quoi en fait, faut que je dorme :lol: Je continue de regarder

EDIT 2 : Essaie quand même ce que j'ai dit, et sinon l.68 ça me paraît bizarre de tester la position du bouton, il n'existe pas une autre propriété ?

-
Edité par 23antoine03 19 juin 2020 à 19:37:22

  • Partager sur Facebook
  • Partager sur Twitter

Vous ne pouvez pas comprendre la récursivité sans d’abord avoir compris la récursivité 

19 juin 2020 à 19:37:20

Hello,

if(!change), ça teste if(change==0). Comme tu mets change à 1, pas de danger que ça rentre dans le if. C'est comme si tu écrivais if(1==0)

-
Edité par edgarjacobs 19 juin 2020 à 19:40:43

  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

19 juin 2020 à 19:38:02

Bonjour,


La gestion des évènements n’est pas correcte : il faut mettre la fonction SDL_PollEvent(&event) à l’intérieur d’un bloc while { } en testant ainsi le retour de la fonction ce qui permet de ne rentrer dans le switch que lorsque il y a eu un événement.
Actuellement tu passes en boucle sur la ligne 67 même sans clic car les switchs se font sur l’état du dernier événement.

-
Edité par picosoft 19 juin 2020 à 19:40:21

  • Partager sur Facebook
  • Partager sur Twitter
Architecture SDL                     Multithreading         
19 juin 2020 à 19:50:52

De fait, une bonne indentation du code serait appréciable. Autant pour nous que pour toi.
  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

21 juin 2020 à 10:43:06

edgarjacobs a écrit:

Hello,

if(!change), ça teste if(change==0). Comme tu mets change à 1, pas de danger que ça rentre dans le if. C'est comme si tu écrivais if(1==0)

-
Edité par edgarjacobs il y a environ 23 heures


justement c'est ce que je veux 

quand je met change à 1, c'est pour qu'il n'entre plus dans cette boucle 

mais c'est dans la boucle qui teste la position qu'il ne rentre jamais

  • Partager sur Facebook
  • Partager sur Twitter
21 juin 2020 à 10:52:24

Passe à SDL 2.0, la SDL 1.2 est obsolète depuis plus de 7 ans et plus supportée.
  • Partager sur Facebook
  • Partager sur Twitter

git is great because Linus did it, mercurial is better because he didn't.

21 juin 2020 à 16:36:25

edgarjacobs a écrit:

De fait, une bonne indentation du code serait appréciable. Autant pour nous que pour toi.



  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

21 juin 2020 à 19:16:48

/*Résolveur d'exercice trigonométrie*/

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "pause.h"

void affTriangle(SDL_Surface *ecran,
		 SDL_Surface *triangle,
		 SDL_Rect positionTriangle)
{
  SDL_FillRect(ecran,NULL, SDL_MapRGB(ecran->format, 255,255,255));
  triangle = IMG_Load("/home/alexandre/C/math/triangle-rect.png");
  positionTriangle.x = LENGTH/2 - triangle->w/2;
  positionTriangle.y = WIDTH/2 - triangle->h/2;
  positionTriangle.y -= WIDTH/6;
  SDL_BlitSurface(triangle, NULL, ecran, &positionTriangle);
}
 
void main()
{
  SDL_Surface *ecran = NULL;
  SDL_Surface *triangle = NULL, *texte = NULL;
  SDL_Rect positionTriangle, positionTexte;
  TTF_Font *police = NULL;
  SDL_Color noir = {0,0,0};

  TTF_Init();
  SDL_Init(SDL_INIT_VIDEO);
  ecran = SDL_SetVideoMode(LENGTH,WIDTH,32,SDL_HWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF);

  affTriangle(ecran, triangle, positionTriangle);

  police = TTF_OpenFont("/home/alexandre/C/SDL/polices/vibur.ttf", 25);
  texte = TTF_RenderText_Blended(police, "Voici le triangle ABC, rectangle en A",noir);
  
  positionTexte.x = LENGTH/2 - texte->w/2;
  positionTexte.y = WIDTH/2 - texte->h/2;
  positionTexte.y += WIDTH/5 - WIDTH/12;
  SDL_BlitSurface(texte, NULL, ecran, &positionTexte);
      
  SDL_Flip(ecran);
  SDL_Delay(5000);

  int continuer = 1;
  int change = 0;
  SDL_Event event;

  while(continuer)
    {
    SDL_PollEvent(&event);
    
    switch(event.type)
      {
    case SDL_QUIT:                        //clic sur la croix rouge 
      continuer = 0;
      break;
    case SDL_KEYDOWN:                      //on a pressé une touche du clavier
      
      switch(event.key.keysym.sym)
	{
      case SDLK_ESCAPE:                     //touche Échap
	continuer = 0;
	break;
      }
      break;
      
    case SDL_MOUSEBUTTONUP:              //on a cliqué avec la souris
      switch(event.button.button)
	{
      case SDL_BUTTON_LEFT:            //clic gauche
        if(event.button.x <= 214 && event.button.x >= 172
	   && event.button.y <= 249 && event.button.y >=224)
	  {
	  change = 1;
	  affTriangle(ecran, triangle, positionTriangle);
	}
	break;
      }
      break;
      
    }
    
      if(!change)
	{
	affTriangle(ecran,triangle,positionTriangle);
	
	SDL_FreeSurface(texte);
	texte = TTF_RenderText_Blended(police,"Veuillez clicker sur l'angle ou la longueur à calculer.", noir);
	
        positionTexte.x = LENGTH/2 - texte->w/2;
	positionTexte.y = WIDTH/2 - texte->h/2;
	positionTexte.y += WIDTH/5 - WIDTH/12;
	
	SDL_BlitSurface(texte,NULL,ecran,&positionTexte);
	SDL_Flip(ecran);
      }
  }

  TTF_CloseFont(police);
  TTF_Quit();
  
  SDL_FreeSurface(texte);
  SDL_FreeSurface(triangle);
  SDL_Quit();
}
  • Partager sur Facebook
  • Partager sur Twitter
21 juin 2020 à 19:53:33

Re,-

/*Résolveur d'exercice trigonométrie*/
 
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "pause.h"
 
void affTriangle(SDL_Surface *ecran,
				 SDL_Surface *triangle,
				 SDL_Rect positionTriangle) {
	SDL_FillRect(ecran,NULL, SDL_MapRGB(ecran->format, 255,255,255));
	triangle = IMG_Load("/home/alexandre/C/math/triangle-rect.png");
	positionTriangle.x = LENGTH/2 - triangle->w/2;
	positionTriangle.y = WIDTH/2 - triangle->h/2;
	positionTriangle.y -= WIDTH/6;
	SDL_BlitSurface(triangle, NULL, ecran, &positionTriangle);
}
  
void main(int argc,char *argv[]) {
	SDL_Surface *ecran = NULL;
	SDL_Surface *triangle = NULL, *texte = NULL;
	SDL_Rect positionTriangle, positionTexte;
	TTF_Font *police = NULL;
	SDL_Color noir = {0,0,0};
	
	TTF_Init();
	SDL_Init(SDL_INIT_VIDEO);
	ecran = SDL_SetVideoMode(LENGTH,WIDTH,32,SDL_HWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF);
	
	affTriangle(ecran, triangle, positionTriangle);
	
	police = TTF_OpenFont("/home/alexandre/C/SDL/polices/vibur.ttf", 25);
	texte = TTF_RenderText_Blended(police, "Voici le triangle ABC, rectangle en A",noir);
	
	positionTexte.x = LENGTH/2 - texte->w/2;
	positionTexte.y = WIDTH/2 - texte->h/2;
	positionTexte.y += WIDTH/5 - WIDTH/12;
	SDL_BlitSurface(texte, NULL, ecran, &positionTexte);
		
	SDL_Flip(ecran);
	SDL_Delay(5000);
	
	int continuer = 1;
	int change = 0;
	SDL_Event event;
	
	while(continuer) {
		SDL_PollEvent(&event);
		switch(event.type) {
			case SDL_QUIT:
				continuer = 0;
				break;
			case SDL_KEYDOWN:
				/* Alternative au switch(event.key.keysym.sym) -- lignes 64 à 69
				if(event.key.keysym==SDLK_ESCAPE)
					continer=0;
				break;
				*/
				switch(event.key.keysym.sym) {
					case SDLK_ESCAPE:
						continuer = 0;
						break;
					}
				break;
			case SDL_MOUSEBUTTONUP:
				/* Alternative au switch(event.button.button) -- lignes 81 à 90
				if(event.button.button==SDL_BUTTON_LEFT) {
					if(event.button.x <= 214 && event.button.x >= 172
					   && event.button.y <= 249 && event.button.y >=224) {
						change = 1;
						affTriangle(ecran, triangle, positionTriangle);
					}
				}
				break;
				*/
				switch(event.button.button) {
					case SDL_BUTTON_LEFT:
						if(event.button.x <= 214 && event.button.x >= 172
						   && event.button.y <= 249 && event.button.y >=224) {
							change = 1;
							affTriangle(ecran, triangle, positionTriangle);
						}
						break;
				}	
				break;
		}
		if(!change) {
			affTriangle(ecran,triangle,positionTriangle);
			SDL_FreeSurface(texte);
			texte = TTF_RenderText_Blended(police,"Veuillez clicker sur l'angle ou la longueur à calculer.", noir);
			positionTexte.x = LENGTH/2 - texte->w/2;
			positionTexte.y = WIDTH/2 - texte->h/2;
			positionTexte.y += WIDTH/5 - WIDTH/12;
			SDL_BlitSurface(texte,NULL,ecran,&positionTexte);
			SDL_Flip(ecran);
		}
	}
	
	TTF_CloseFont(police);
	TTF_Quit();
	
	SDL_FreeSurface(texte);
	SDL_FreeSurface(triangle);
	SDL_Quit();
}

Ce n'est peut-être pas la meilleure des indentations, mais au moins on y voit clairement les blocs. L'insertion de default: break; dans les swich serait encore un plus.

Et pour ton problème avec change, tu ferais mieux d'utliser stdbool.h (bool change) et les valeurs true et false. Ou alors, les SDL_TRUE et SDL_FALSE et SDL_bool change

-
Edité par edgarjacobs 21 juin 2020 à 20:14:09

  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

21 juin 2020 à 21:30:53

changer 1 par true et 0 par false ne change pas le fait qu'il ne rentre jamais dans la boucle if ligne 83...
  • Partager sur Facebook
  • Partager sur Twitter
21 juin 2020 à 22:50:28

Je n'ai pas vu ça plus tot, mais à chaque fois que tu appelles ta fonction, tu charges ton image, et tu ne la libères pas. Ça peut vite saturer la mémoire. Il faut charger les ressources en début de programme, et les libérer en fin de programme (comme tu fais pour police)

-
Edité par edgarjacobs 21 juin 2020 à 22:51:01

  • Partager sur Facebook
  • Partager sur Twitter

On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

21 juin 2020 à 22:50:36

Commence par corriger la ligne 53 pour switcher sur l'évènement désiré ...
  • Partager sur Facebook
  • Partager sur Twitter
Architecture SDL                     Multithreading         
21 juin 2020 à 22:56:36

picosoft a écrit:

Commence par corriger la ligne 53 pour switcher sur l'évènement désiré ...


SDL_PollEvent(&event);
???

edgarjacobs a écrit:

Je n'ai pas vu ça plus tot, mais à chaque fois que tu appelles ta fonction, tu charges ton image, et tu ne la libères pas. Ça peut vite saturer la mémoire. Il faut charger les ressources en début de programme, et les libérer en fin de programme (comme tu fais pour police)

-
Edité par edgarjacobs il y a 5 minutes

il faut que je libère le texte et le triangle avant l'appel de la fonction ???

-
Edité par alexpatt 21 juin 2020 à 22:58:44

  • Partager sur Facebook
  • Partager sur Twitter
22 juin 2020 à 8:50:50

Pour le premier point :

Voir la bonne et la mauvaise façon de gérer les évènements à la fin de ce post :

http://www.siteduzero.com/forum/sujet/comprehension-de-la-fonction-pollevent

Pour le second point :

La ligne 17 doit être sortie de la fonction et placée avant la ligne 52 (pour ne l’exécuter qu’une seule fois au début du programme).

  • Partager sur Facebook
  • Partager sur Twitter
Architecture SDL                     Multithreading         
26 juin 2020 à 18:55:21

j'ai fait ça :

/*Résolveur d'exercice trigonométrie*/

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "pause.h"

void affTriangle(SDL_Surface *ecran,
		 SDL_Surface *triangle,
		 SDL_Rect positionTriangle)
{
  SDL_FillRect(ecran,NULL, SDL_MapRGB(ecran->format, 255,255,255));
  positionTriangle.x = LENGTH/2 - triangle->w/2;
  positionTriangle.y = WIDTH/2 - triangle->h/2;
  positionTriangle.y -= WIDTH/6;
  SDL_BlitSurface(triangle, NULL, ecran, &positionTriangle);
}
 
void main()
{
  SDL_Surface *ecran = NULL;
  SDL_Surface *triangle = NULL, *texte = NULL;
  SDL_Rect positionTriangle, positionTexte;
  TTF_Font *police = NULL;
  SDL_Color noir = {0,0,0};

  TTF_Init();
  SDL_Init(SDL_INIT_VIDEO);
  ecran = SDL_SetVideoMode(LENGTH,WIDTH,32,SDL_HWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF);

  triangle = IMG_Load("/home/alexandre/C/math/triangle-rect.png");

  affTriangle(ecran, triangle, positionTriangle);

  police = TTF_OpenFont("/home/alexandre/C/SDL/polices/vibur.ttf", 25);
  texte = TTF_RenderText_Blended(police, "Voici le triangle ABC, rectangle en A",noir);

  
  positionTexte.x = LENGTH/2 - texte->w/2;
  positionTexte.y = WIDTH/2 - texte->h/2;
  positionTexte.y += WIDTH/5 - WIDTH/12;
  SDL_BlitSurface(texte, NULL, ecran, &positionTexte);
      
  SDL_Flip(ecran);
  SDL_Delay(5000);

  int continuer = 1;
  int change = 0;
  SDL_Event event;

  while(continuer)
    {
      while(SDL_PollEvent(&event)){
    
	switch(event.type)
	  {
	  case SDL_QUIT:                        //clic sur la croix rouge 
	    continuer = 0;
	    break;
	  case SDL_KEYDOWN:                      //on a pressé une touche du clavier
      
	    switch(event.key.keysym.sym)
	      {
	      case SDLK_ESCAPE:                     //touche Échap
		continuer = 0;
		break;
	      }
	    break;
	    
	  case SDL_MOUSEBUTTONUP:              //on a cliqué avec la souris
	    switch(event.button.button)
	      {
	      case SDL_BUTTON_LEFT:            //clic gauche
		if(event.button.x <= 214 && event.button.x >= 172
		   && event.button.y <= 249 && event.button.y >=224)
		  {
		    change = 1;
		    affTriangle(ecran, triangle, positionTriangle);
		  }
		break;
	      }
	    break;
	  }
      }    
    
      if(!change)
	{
	affTriangle(ecran,triangle,positionTriangle);
	
	SDL_FreeSurface(texte);
	texte = TTF_RenderText_Blended(police,"Veuillez clicker sur l'angle ou la longueur à calculer.", noir);
	
        positionTexte.x = LENGTH/2 - texte->w/2;
	positionTexte.y = WIDTH/2 - texte->h/2;
	positionTexte.y += WIDTH/5 - WIDTH/12;
	
	SDL_BlitSurface(texte,NULL,ecran,&positionTexte);
	SDL_Flip(ecran);
      }
  }

  TTF_CloseFont(police);
  TTF_Quit();
  
  SDL_FreeSurface(texte);
  SDL_FreeSurface(triangle);
  SDL_Quit();
}

mais toujours aucune réaction quand on clique sur la zone censée réagir...

  • Partager sur Facebook
  • Partager sur Twitter
27 juin 2020 à 22:26:38

Il faut débugger (pardon si j'ai dis un gros mot) !

Quelques idées :

Mettre un "printf" entre les lignes 82 et 83 pour afficher simplement si on entre ou non dans le if{ }

Sortir la ligne 103 du if{ } car si change=1 alors on n'affiche rien de plus (la ligne 103 n'est plus exécutée !)

...

  • Partager sur Facebook
  • Partager sur Twitter
Architecture SDL                     Multithreading         
28 juin 2020 à 14:41:28

c'est bon, j'avais en effet oublié un SDL_Flip....

Merci beaucoup

  • Partager sur Facebook
  • Partager sur Twitter