
/**************************************************************************
COLLISIONS: 2 éléments rectangulaires bougent avec la souris (drag and throw)
on détecte leur collision et l'état de collision
est signalée par un changement de couleur
Ce code reprend des fonctions de 1_0 et 1_1 du cours 3
on a enlevé la gestion du tableau d'acteurs (seulement 2 acteurs)
La détection proprement dite des collisions est faite
par une fonction auxilliaire : collisionActeurs
Voir tout en bas du code.
**************************************************************************/
#include <allegro.h>
#include <time.h>
/****************************/
/* STRUCTURE ACTEUR */
/****************************/
// données personnelles de chaque acteur qui se déplace
typedef struct acteur
{
int x, y; // coordonnée (du coin sup. gauche)
int dx, dy; // vecteur deplacement
int tx,ty; // tailles : horizontal/vertical
int couleur; // couleur de l'élément graphique
} t_acteur;
/*****************************/
/* PROTOTYPES */
/*****************************/
// Fonctions principales (appelées depuis le main)
// Allouer et initialiser un acteur
t_acteur * creerActeur();
// Actualiser un acteur (bouger ...)
void actualiserActeur(t_acteur *acteur);
// Dessiner un acteur sur une bitmap bmp
void dessinerActeur(BITMAP *bmp, t_acteur *acteur);
// Fonctions annexes
// voir ci dessous pour des manières alternatives d'écrire la même fonction
int sousSourisActeur(t_acteur *acteur);
// Déterminer si les rectangles de 2 acteurs s'intersectent
// Fonction booléenne : retourne 1 si collision 0 sinon
int collisionActeurs(t_acteur *a1, t_acteur *a2);
/******************************************/
/* PROGRAMME PRINCIPAL */
/* initialisation puis boucle de jeu */
/******************************************/
int main()
{
// 2 acteurs (à créer)
t_acteur *actA, *actB;
// BITMAP servant de buffer d'affichage (double buffer)
BITMAP *page;
// Mouvement Mouse en x et y (mouvement = changement de position)
int mmx,mmy;
// On va utiliser du hasard
srand(time(NULL));
// Lancer allegro et le mode graphique
allegro_init();
install_keyboard();
install_mouse();
set_color_depth(desktop_color_depth());
if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,800,600,0,0)!=0)
{
allegro_message("prb gfx mode");
allegro_exit();
exit(EXIT_FAILURE);
}
// Montrer la souris à l'écran
show_mouse(screen);
// CREATION DU BUFFER D'AFFICHAGE à la taille de l'écran
page=create_bitmap(SCREEN_W,SCREEN_H);
clear_bitmap(page);
// Initialisation aléatoire des paramètres des acteurs :
actA=creerActeur();
actB=creerActeur();
// Boucle de jeu
while (!key[KEY_ESC])
{
// EFFACER POSITIONs ACTUELLEs SUR LE BUFFER
clear_bitmap(page);
// GESTION INTERFACE
// Le "mickey" est l'unité de déplacement du curseur souris
// la fonction suivante récupère le vecteur déplacement depuis son dernier appel
get_mouse_mickeys(&mmx,&mmy);
if ( mouse_b&1 && sousSourisActeur(actA) ){
actA->dx=mmx;
actA->dy=mmy;
}
if ( mouse_b&1 && sousSourisActeur(actB) ){
actB->dx=mmx;
actB->dy=mmy;
}
// DETERMINER NOUVELLEs POSITIONs
actualiserActeur(actA);
actualiserActeur(actB);
// COLLISION ?
if ( collisionActeurs(actA,actB) )
{
actA->couleur=makecol(255,80,80);
actB->couleur=makecol(255,80,80);
}
else
{
actA->couleur=makecol(80,255,80);
actB->couleur=makecol(80,255,80);
}
// AFFICHAGE NOUVELLEs POSITIONs SUR LE BUFFER
dessinerActeur(page,actA);
dessinerActeur(page,actB);
// AFFICHAGE DU BUFFER MIS A JOUR A L'ECRAN
blit(page,screen,0,0,0,0,SCREEN_W,SCREEN_H);
// ON FAIT UNE PETITE PAUSE
rest(10);
}
return 0;
}
END_OF_MAIN();
/************************************************/
/* DEFINITIONS DES SOUS-PROGRAMMES */
/************************************************/
// Allouer et initialiser (aléatoirement) un acteur
t_acteur * creerActeur()
{
// pointeur sur l'acteur qui sera créé (et retourné)
t_acteur *acteur;
// Création (allocation)
acteur = (t_acteur *)malloc(1*sizeof(t_acteur));
// Initialisation
acteur->tx = rand()%100+100;
acteur->ty = rand()%100+100;
// Position aléatoire (on tient compte de la taille...)
acteur->x = rand()%(SCREEN_W - acteur->tx);
acteur->y = rand()%(SCREEN_H - acteur->ty);
// Pour ce programme on veut des acteurs initialement immobiles
acteur->dx = 0;
acteur->dy = 0;
// Couleur blanche (mais ce sera modifié dans le main...)
acteur->couleur = makecol(255,255,255);
// on retourne cet acteur fraichement créé
// ( en fait on retourne le POINTEUR sur lui )
return acteur;
}
// Actualiser un acteur (bouger ...)
void actualiserActeur(t_acteur *acteur)
{
// contrôle des bords : ici on décide de rebondir sur les bords
if ( ( acteur->x < 0 && acteur->dx < 0 ) ||
( acteur->x + acteur->tx > SCREEN_W && acteur->dx > 0) )
acteur->dx = -acteur->dx;
if ( ( acteur->y < 0 && acteur->dy < 0 ) ||
( acteur->y + acteur->ty > SCREEN_H && acteur->dy > 0) )
acteur->dy = -acteur->dy;
// calculer nouvelle position
// nouvelle position = position actuelle + deplacement
acteur->x = acteur->x + acteur->dx;
acteur->y = acteur->y + acteur->dy;
}
// Dessiner un acteur sur une bitmap bmp
void dessinerActeur(BITMAP *bmp, t_acteur *acteur)
{
rectfill(bmp,acteur->x,acteur->y,acteur->x+acteur->tx,acteur->y+acteur->ty,acteur->couleur);
}
// Déterminer si un acteur est sous la souris
// Fonction booléenne : retourne 1 pour oui 0 pour non
// voir ci dessous pour des manières alternatives d'écrire la même fonction
int sousSourisActeur(t_acteur *acteur)
{
int retour=0;
if ( mouse_x >= acteur->x && mouse_x <= acteur->x + acteur->tx &&
mouse_y >= acteur->y && mouse_y <= acteur->y + acteur->ty )
retour=1;
return retour;
}
// On pourrait aussi écrire (moins "rigoureux" car plusieurs return):
/*
int sousSourisActeur(t_acteur *acteur)
{
if ( mouse_x >= acteur->x && mouse_x <= acteur->x + acteur->tx &&
mouse_y >= acteur->y && mouse_y <= acteur->y + acteur->ty )
return 1;
else
return 0;
}
*/
// On pourrait aussi écrire (rigoureux et compact mais à réserver aux cas simples)
/*
int sousSourisActeur(t_acteur *acteur)
{
// On peut retourner directement le résultat d'une expression booléenne
return mouse_x >= acteur->x && mouse_x <= acteur->x + acteur->tx &&
mouse_y >= acteur->y && mouse_y <= acteur->y + acteur->ty ;
}
*/
// Déterminer si les rectangles de 2 acteurs s'intersectent
// Fonction booléenne : retourne 1 si collision 0 sinon
int collisionActeurs(t_acteur *a1, t_acteur *a2)
{
int retour=0;
// Si collision mettre valeur retour à 1
if ( a1->x <= a2->x + a2->tx && a2->x <= a1->x + a1->tx &&
a1->y <= a2->y + a2->ty && a2->y <= a1->y + a1->ty )
retour=1;
return retour;
}