Sabetodo
Messages postés120Date d'inscriptionsamedi 1 mars 2008StatutMembreDernière intervention18 août 2010
-
19 févr. 2010 à 16:06
yves004
Messages postés9Date d'inscriptionvendredi 19 février 2010StatutMembreDernière intervention19 février 2010
-
19 févr. 2010 à 16:16
Bonjour,
Salut à tous le monde. J s8 un passionne des jeux vidéo j'ai décide de me lancer dans la 2D. Alors j'ai suivi le tuto de Mathéo en C sur la création des jeux 2D en SDL. Maintenant pour me faire plaisir j'ai décide de programmer le fameux jeu pong. Apparemment le code marche sans problème puisqu'il ne signale pas d'erreur, mais lors du chargement de la fenêtre rien ne s'affiche. Pour ceux qui sont déjà bien avance la dessus, merci de me donner un coup de main. voici le code en entier bien commenté pour vous aider à m'aider:
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <SDL/SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
using namespace std;
/****************WELCOME*****TO***MY****FIRST**GAME****PONG***********/
/**********************COMMENT CELA MARCHE****************************/
/*
Joueur de gauche: Monter = T
Descendre = G
Missile = Espace
Joueur de droite: Monter, Descendre = Flêches
Missile = Entrer
*/
// Constantes
const int SCREEN_WIDTH = 800;// Largeur de la Fenêtre
const int SCREEN_HEIGHT = 600;// Hauteur de la Fenêtre
const int VITESSE_BALLE = 2;// Vitesse de la balle
const int VITESSE_BARRE = 2;// Vitesse des barres
const int VITESSE_COUP_SPE = 2;// Vitesse du missile
const int DELAY = 4;// Delay du Fps
// *** Structure Objet ***
//- Elle contient une surface pour y mettre l'image et un SDL_Rect pour donner ses positions.
struct Objet
{
SDL_Surface* surface;
SDL_Rect position;
};
//************************
// ********************************************* Mouvements balle ********************************************
//- Modifie selon les données les positions de la balle
int moveBalle(Objet &balle, Objet barreGauche, Objet barreDroit, int &mov_x, int &mov_y)
{
/* -- Vérifie que la balle touche une barre -- */
// On rajoute +- VITESSE_BALLE dans les condition pour pouvoir changer librement la vitesse de la balle
// Si la balle touche la barre de droite, on multiplie par (-1) le mouvement de la balle pour la faire repartir dans l'autre sens
if( ( ((balle.position.x + balle.surface->w) >= (SCREEN_WIDTH - barreDroit.surface->w - 20)) && ((balle.position.x + balle.surface->w) < (SCREEN_WIDTH - barreDroit.surface->w - 20 + VITESSE_BALLE)))
&&
((balle.position.y <= (barreDroit.position.y + barreDroit.surface->h)) && ((balle.position.y + balle.surface->h) >= barreDroit.position.y)) )
mov_x *= -1;
// De même pour la barre de gauche
else if( ((balle.position.x <= (barreGauche.surface->w + 20)) && (balle.position.x > (barreGauche.surface->w + 20 - VITESSE_BALLE)))
&&
((balle.position.y <= (barreGauche.position.y + barreGauche.surface->h)) && ((balle.position.y + balle.surface->h) >= barreGauche.position.y)) )
mov_x *= -1;
/* ------------------------------------------- */
// Vérifie si la balle touche les mur d'en haut ou d'en bas et si oui change le sens de mouvement
if((balle.position.y + balle.surface->h) >= SCREEN_HEIGHT)
mov_y *= -1;
else if(balle.position.y <= 0)
mov_y *= -1;
// Change les positions
balle.position.x += mov_x;
balle.position.y += mov_y;
/* On vient de changer les positions de la balle. Donc si elle passe les conditions suivantes
c'est qu'elles n'est pas en face d'une barre et qu'elle est sortie.
Le joueur de gauche est 1, celui de droite est 2*/
// On rajoute +- VITESSE_BALLE dans les condition pour pouvoir changer librement la vitesse de la balle
if((balle.position.x) > (SCREEN_WIDTH - 20 - barreDroit.surface->w + VITESSE_BALLE))// Sort vers la droite, donc renvoie 1 car le joueur de gauche (1) a gagné
return 1;
else if((balle.position.x) < (barreGauche.surface->w + 20 - VITESSE_BALLE))// Sort vers la gauche, donc renvoie 2 car le joueur de droite (2) a gagné
return 2;
else
return 0;// On renvoi 0 si personne gagne comme çà le jeux continue
}
// *********************************************************************************************************
// ********************************************* Mouvements des barres ********************************************
//- Modifie les positions des barres si on appuis sur les touches du clavier appropriées
void moveBarre(Objet &barreGauche, Objet &barreDroit, Uint8* keystates)
{
if(keystates[SDLK_UP] && (barreDroit.position.y - VITESSE_BARRE >= 0))// La fléche du HAUT est appuié, donc on fait remonter la barre de droite
barreDroit.position.y -= VITESSE_BARRE;
if(keystates[SDLK_DOWN] && (barreDroit.position.y + barreDroit.surface->h + VITESSE_BARRE <= SCREEN_HEIGHT))// La fléche du BAS est appuié, donc on fait redescendre la barre de droite
barreDroit.position.y += VITESSE_BARRE;
if(keystates[SDLK_t] && (barreGauche.position.y - VITESSE_BARRE >= 0))// La touche T est appuié, donc on fait remonter la barre de gauche
barreGauche.position.y -= VITESSE_BARRE;
if(keystates[SDLK_g] && (barreGauche.position.y + barreGauche.surface->h + VITESSE_BARRE <= SCREEN_HEIGHT))// La touche G est appuié, donc on fait redescendre la barre de gauche
barreGauche.position.y += VITESSE_BARRE;
}
// ************************************** Attend qu'une touche soit appuyé ***************************************
void waitEvent(SDL_Event event, bool &continuer)
{
bool attendre = true;
while(attendre)
{
SDL_WaitEvent(&event);// Attend un événement
switch(event.type)
{
case SDL_QUIT:// On click sur la croix de la fenétre donc on annule le booléen de la boucle d'attente et celui de la boucle principale
continuer = false;
attendre = false;
break;
case SDL_KEYDOWN:// Une touche est préssé donc on quitte cette boucle et sortons de la fonction
attendre = false;
break;
}
}
}
// ***************************************************************************************************************
// ******************************************* Colle les Img à l'écran *******************************************
void blit(SDL_Surface* screen, Objet fond, Objet balle, Objet barreGauche, Objet barreDroit, Objet score, Objet coupSpe, bool scoreOK, int coupSpeBool)
{
// Blitages
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255)); // On efface l'écran (ici fond blanc)
SDL_BlitSurface(fond.surface, NULL, screen, &fond.position);// Colle l'img de fond
SDL_BlitSurface(balle.surface, NULL, screen, &balle.position);// Colle la balle
SDL_BlitSurface(barreGauche.surface, NULL, screen, &barreGauche.position);// Colle la barre gauche
SDL_BlitSurface(barreDroit.surface, NULL, screen, &barreDroit.position);// Colle la barre droite
if(scoreOK)// Si on a indiqué de coller le score, on le fait
SDL_BlitSurface(score.surface, NULL, screen, &score.position);// Colle le Score
if(coupSpeBool)// De même pour le coup spécial
SDL_BlitSurface(coupSpe.surface, NULL, screen, &coupSpe.position);// Colle le coup special
SDL_Flip(screen);// Mise à jour de l'écran
}
// ***************************************************************************************************************
// ******************************************* Gère les coups Spéciaux *******************************************
//- On regarde si une touche pour les coups spéciaux n'est pas préssé. Si oui, on affiche le coup spécial en changeant ses coordonnées à chaques appels de cette fonction
void coupSpecial(SDL_Event event, bool &continuer, Objet &coupSpe, int &coupSpeBarre, int &mov_coupSpe, Objet barreGauche, Objet barreDroit, int &gagnant)
{
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:// On click sur la croix de la fenétre donc on annule le booléen de la boucle principale
continuer = false;
break;
case SDL_KEYDOWN:// Une touche est préssé
switch (event.key.keysym.sym)
{
case SDLK_SPACE:// Espace préssé
if(coupSpeBarre == 0)// Si le coup spécial n'existe pas, on le donne donc au joueur de gauche (coupSpeBarre = 1); on place le missile
{
coupSpeBarre = 1;
coupSpe.position.y = barreGauche.position.y + (barreGauche.surface->h/2);
coupSpe.position.x = barreGauche.surface->w + 20;
}
break;
case SDLK_RETURN:// Entrer préssé
if(coupSpeBarre == 0)// Si le coup spécial n'existe pas, on le donne donc au joueur de droite (coupSpeBarre = 2); on place le missile
{
coupSpeBarre = 2;
coupSpe.position.y = barreDroit.position.y + (barreDroit.surface->h/2);
coupSpe.position.x = SCREEN_WIDTH - barreDroit.surface->w - 20;
mov_coupSpe *= -1; // Pour aller vers l'arrière
}
break;
}
break;
}
// Si un coup spécial est déjà en cours, donc différent de 0, on l'affiche
if(coupSpeBarre != 0)
{
// --- Sort vers la droite
if( ((coupSpe.position.x + coupSpe.surface->w) >= (SCREEN_WIDTH - barreDroit.surface->w - 20)) && (coupSpeBarre == 1) )
{
// Le joueur de gauche (1) a gagné car la balle a touché la barre de droite
if((coupSpe.position.y <= (barreDroit.position.y + barreDroit.surface->h)) && ((coupSpe.position.y + coupSpe.surface->h) >= barreDroit.position.y))
{
gagnant = 1;
coupSpeBarre = 0;// On remet le coup spécial à 0 pour dire qu'aucun missiles n'est en jeux
}
else // Sinon le missile est sortie mais n'a rien touché. On ne l'affiche plus
coupSpeBarre = 0;
}
// --- Sort vers la gauche
else if ( ((coupSpe.position.x) <= (barreGauche.surface->w + 20)) && (coupSpeBarre == 2) )
{
// Le joueur de droite (2) a gagné car la balle a touché la barre de gauche
if((coupSpe.position.y <= (barreGauche.position.y + barreGauche.surface->h)) && ((coupSpe.position.y + coupSpe.surface->h) >= barreGauche.position.y))
{
gagnant = 2;
coupSpeBarre = 0;// On remet le coup spécial à 0 pour dire qu'aucun missiles n'est en jeux
mov_coupSpe *= -1; // Remet le mouvement dans le bon sens
}
else// Sinon le missile est sortie mais n'a rien touché. On ne l'affiche plus
{
coupSpeBarre = 0;
mov_coupSpe *= -1; // Remet le mouvement dans le bon sens
}
}
// --- Sinon rien ne se passe, donc le missile est en action
else
coupSpe.position.x += mov_coupSpe;
}
}
// ***************************************************************************************************************
// **************************************************** MENU *****************************************************
//- Affiche le menu. Si on clique sur quitter, on modifie les booléens pour quitter le jeux et si on click sur jouer, pour afficher le jeux
bool menu(SDL_Surface* screen, Objet fond, SDL_Event event, bool &continuer)
{
// Objets temporairement affichés pour le menu.
struct Objet titre = {IMG_Load("titre.png")}, jouer = {IMG_Load("jouer.png")}, quitter = {IMG_Load("quitter.png")};
// Positions des Objets précedement définis
titre.position.x = (SCREEN_WIDTH / 2) - (titre.surface->w / 2); titre.position.y = 100;
jouer.position.x = (SCREEN_WIDTH / 2) - (jouer.surface->w / 2); jouer.position.y = (SCREEN_HEIGHT / 2);
quitter.position.x = (SCREEN_WIDTH / 2) - (quitter.surface->w / 2); quitter.position.y = (SCREEN_HEIGHT / 2) + 100;
// Affichage du Menu
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255)); // On efface l'écran (ici fond blanc)
SDL_BlitSurface(fond.surface, NULL, screen, &fond.position);// Colle l'img de fond
SDL_BlitSurface(titre.surface, NULL, screen, &titre.position);// Colle le titre
SDL_BlitSurface(jouer.surface, NULL, screen, &jouer.position);// Colle le bouton "jouer"
SDL_BlitSurface(quitter.surface, NULL, screen, &quitter.position);// Colle le bouton "quitter"
SDL_Flip(screen); // Mise à jour de l'écran
bool attendre = true;// Booléen pour rester dans la boucle du Menu
int clickDispo = 0; // Vaut 0 pour un click non disponible, 1 pour jouer et 2 pour quitter
while(attendre)
{
SDL_WaitEvent(&event);// Attend un événement
switch(event.type)
{
case SDL_QUIT:// On click sur la croix de la fenétre donc on annule le booléen de la boucle du menu et celui de la boucle principale
continuer = false;
attendre = false;
return 0;
break;
case SDL_MOUSEMOTION:// Lorsque la souris bouge
// Si la souris est sur le bouton "jouer", on change l'img du bouton
if(event.motion.y >= jouer.position.y && event.motion.y <= (jouer.position.y + jouer.surface->h) &&
event.motion.x >= jouer.position.x && event.motion.x <= (jouer.position.x + jouer.surface->w))
{
jouer.surface = IMG_Load("jouerOver.png");
clickDispo = 1;
}
// Sinon si la souris est sur le bouton "quitter", on change l'img du bouton
else if(event.motion.y >= quitter.position.y && event.motion.y <= (quitter.position.y + quitter.surface->h) &&
event.motion.x >= quitter.position.x && event.motion.x <= (quitter.position.x + quitter.surface->w))
{
quitter.surface = IMG_Load("quitterOver.png");
clickDispo = 2;
}
// Sinon on remet les boutons d'origines et on met la disponibilité du click à 0 car on est sur aucun boutons
else
{
jouer.surface = IMG_Load("jouer.png");
quitter.surface = IMG_Load("quitter.png");
clickDispo = 0;
}
// Affichage du Menu
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255)); // On efface l'écran (ici fond blanc)
SDL_BlitSurface(fond.surface, NULL, screen, &fond.position);// Colle l'img de fond
SDL_BlitSurface(titre.surface, NULL, screen, &titre.position);// Colle le titre
SDL_BlitSurface(jouer.surface, NULL, screen, &jouer.position);// Colle le bouton "jouer"
SDL_BlitSurface(quitter.surface, NULL, screen, &quitter.position);// Colle le bouton "quitter"
SDL_Flip(screen); // Mise à jour de l'écran
break;
case SDL_MOUSEBUTTONUP:// Lorsqu'un click est effectué
// Si on est sur le bouton "jouer" (car clickDispo vaut 1 pour ce bouton), on libéres les surfaces qu'on utilisera plus,
// on arrête la boucle du menu et on accépte de rentrer dans la boucle principale avec le booléen "continuer" à true.
if(clickDispo == 1)
{
continuer = true;
attendre = false;
SDL_FreeSurface(titre.surface);
SDL_FreeSurface(jouer.surface);
SDL_FreeSurface(quitter.surface);
return 1;
}
// De même, mais on quitte le menu et mettons le booléen "continuer" à false pour quitter définitivement le programme
else if(clickDispo == 2)
{
continuer = false;
attendre = false;
SDL_FreeSurface(titre.surface);
SDL_FreeSurface(jouer.surface);
SDL_FreeSurface(quitter.surface);
return 0;
}
break;
}
}
}
// ***************************************************************************************************************
// ********************************************* Fonction principale *********************************************
int main(int argc, char* argv[])
{
// Prend un nombre aléatoire pour définir l'ordonnée de la balle entre 0 et 200
srand(time(NULL));// Initialise pour une pioche aléatoire
int ordonneAleatoire = (rand() % 200);
//--------------------------------------------- Definition SDL ---------------------------------------------//
SDL_Init(SDL_INIT_VIDEO); // Initialisation de la SDL
// Définition des structures Objets (on y charge l'image de fond), puis des positions de ces structures
struct Objet fond = {IMG_Load("fond.png")}, balle = {IMG_Load("balle.png")}, barreGauche = {IMG_Load("barreGauche.png")},
barreDroit = {IMG_Load("barreDroit.png")}, score = {NULL}, coupSpe = {IMG_Load("missile.png")};
fond.position.x = 0; fond.position.y = 0;// Fond
balle.position.x = SCREEN_WIDTH / 2 - 100; balle.position.y = ordonneAleatoire;// Balle
barreGauche.position.x = 20; barreGauche.position.y = (SCREEN_HEIGHT / 2) - (barreGauche.surface->h / 2);// Barre de Gauche
barreDroit.position.x = SCREEN_WIDTH - barreDroit.surface->w - 20; barreDroit.position.y = (SCREEN_HEIGHT / 2) - (barreDroit.surface->h / 2);// Barre de Droite
coupSpe.position.x = SCREEN_WIDTH - barreDroit.surface->w - 20;coupSpe.position.y = barreDroit.position.y + (barreDroit.surface->h/2);// Coup Spéciale
SDL_Surface* screen = NULL;// Définie la surface "screen" principale
SDL_Event event;// Définie le nom pour les événements
Uint8 *keystates = SDL_GetKeyState(NULL);// Pour le clavier
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_HWSURFACE | SDL_DOUBLEBUF); // Définitions de la fenêtre, caractéristiques
SDL_WM_SetCaption("Mon Super Pong", NULL);// Titre
// Définition des polices etc ...
TTF_Init();// Initialisation pour les Polices
TTF_Font *police = TTF_OpenFont("nightmareheronormal.ttf", 70);// Indique la police, et la taille
SDL_Color couleurBlanche = {255, 255, 255};// Indique la couleur
score.surface = TTF_RenderText_Blended(police, "Score: 0 - 0", couleurBlanche);// Ecriture du texte
score.position.x = (SCREEN_WIDTH / 2) - (score.surface->w / 2); score.position.y = (SCREEN_HEIGHT / 2) - (score.surface->h / 2);// Positions du score
//----------------------------------------------------------------------------------------------------------//
//----------------------------------------------- Variables ------------------------------------------------//
bool continuer = true;// Bool qui va permettre de continuer le jeu
int mov_x = VITESSE_BALLE, mov_y = VITESSE_BALLE, mov_coupSpe = VITESSE_COUP_SPE;// Mouvement de la balle et du coup special
int gagnant = 0, scoreGauche = 0, scoreDroit = 0;// Scores, gagnant
char scoreText[20] = "";// Texte du score
int coupSpeBarre = 0;// Nbr pour savoir qui lance le coup spécial
int tempsPrecedent = 0, tempsActuel = 0;// Temps pour le fps
//----------------------------------------------------------------------------------------------------------//
if(menu(screen, fond, event, continuer))// Si menu() renvoi 1, on affiche le jeux et on met le programme en pause
{
blit(screen, fond, balle, barreGauche, barreDroit, score, coupSpe, 1, coupSpeBarre);// Affiche le jeux
waitEvent(event, continuer);// Attend qu'on appuie sur une touche pour commencer
}
// ***---____________________ Coeur du programme ____________________---*** //
while(continuer)// Tourne tant que le booléen "continuer" est vrai
{
tempsActuel = SDL_GetTicks();// A chaques retours de boucles, on met a jours "tempsActuel"
// Si la différence entre tempsActuel et tempsprecedent est > 5, donc qu'un certains temp c'est écoulé, on rafraichie le jeux
if((tempsActuel - tempsPrecedent) > DELAY)
{
moveBarre(barreGauche, barreDroit, keystates);// On appel la fonction qui bouge les barres
gagnant = moveBalle(balle, barreGauche, barreDroit, mov_x, mov_y);// On bouge la balle. Si elle est dehors, moveBall() renvoi le gagnant et on modifie le score
coupSpecial(event, continuer, coupSpe, coupSpeBarre, mov_coupSpe, barreGauche, barreDroit, gagnant);// On regarde si il n'y a pas de coup spécial lancé
if(gagnant != 0)// S'il y a un gagnant, on change le scores et on re-initialise les positions
{
if(gagnant == 1)// gagnant = 1 donc le joueur de gauche a gagné. On lui incrémente son score
scoreGauche++;
else if(gagnant == 2)// De même mais on remet le mouvement de la balle dans le bon sens (vers la droite)
{
scoreDroit++;
mov_x *= -1;
}
sprintf(scoreText, "Score : %ld - %ld", scoreGauche, scoreDroit);// Change le texte du score
score.surface = TTF_RenderText_Blended(police, scoreText, couleurBlanche);// Edition du texte sur la surface "score"
score.position.x = (SCREEN_WIDTH / 2) - (score.surface->w / 2); score.position.y = (SCREEN_HEIGHT / 2) - (score.surface->h / 2);// Positions du texte
// Re-Initialise les positions des barres
barreGauche.position.y = (SCREEN_HEIGHT / 2) - (barreGauche.surface->h / 2);barreDroit.position.y = (SCREEN_HEIGHT / 2) - (barreDroit.surface->h / 2);
// Repioche un nombre aléatoire
srand(time(NULL));// Initialise pour une pioche aléatoire
ordonneAleatoire = (rand() % 200);
// Re-Initialise la position de la balle avec le nombre aléatoire
balle.position.x = SCREEN_WIDTH / 2 - 100; balle.position.y = ordonneAleatoire;
coupSpeBarre = 0;// Si il y a un gagnant, on se doit d'annuler un éventuel coup spécial en cours
mov_coupSpe = VITESSE_COUP_SPE;// On remet le missile dans le bon sens (vers la droite)
mov_x = VITESSE_BALLE; mov_y = VITESSE_BALLE;// On remet la balle dans le bon sens également
// Affiche le jeux avec les scores
blit(screen, fond, balle, barreGauche, barreDroit, score, coupSpe, 1, coupSpeBarre);
waitEvent(event, continuer);// Attend qu'on appuie sur une touche pour continuer
}
// De même, on blit
blit(screen, fond, balle, barreGauche, barreDroit, score, coupSpe, 0, coupSpeBarre);
tempsPrecedent = tempsActuel;// On actualise le temps précédent au temps actuel
}
// Sinon, on attend que le temps s'écoule pour économiser le processeur
else
SDL_Delay(DELAY - (tempsActuel - tempsPrecedent));// Economise le processeur
}
//***--- _______________________________________________________________ ---***//
// On quitte la boucle, donc on ferme le programme proprement
TTF_Quit();
SDL_FreeSurface(screen);
SDL_FreeSurface(fond.surface);
SDL_FreeSurface(balle.surface);
SDL_FreeSurface(barreGauche.surface);
SDL_FreeSurface(barreDroit.surface);
SDL_FreeSurface(score.surface);
SDL_FreeSurface(coupSpe.surface);
SDL_Quit();
return EXIT_SUCCESS;
}
// ********************************************************************//
Trouvez des réponses à vos questions sur les langages, les frameworks et les astuces de codage. Échangez avec d'autres développeurs passionnés pour améliorer vos compétences en programmation et rester au fait des dernières tendances du secteur.