Encore un pong (linux, curses) [gcc]

Soyez le premier à donner votre avis sur cette source.

Snippet vu 9 988 fois - Téléchargée 36 fois

Contenu du snippet

Ben oui, encore un clone de pong...! Bah, si on peut appeler sa un clone... C'est encore plus laid!!
Et comme j'utilise les curses, bah pour que la balle bouge, faut appuyer sur une touche :S
Enfin... utilisez 'w' et 's' pour le pad de gauche, et 'o' et 'l' pour le pad de droit.
Le jeu quitte lorsque vous marquez un point.
    • Petite amelioration : La balle continue de bouger meme sans appuyer sur un touche. J'ai trouver comment continuer un traitement dans une boucle tout en reagissant si une touche est enfoncee!!

Source / Exemple :


/****************************************\
| Pong - main.c                          |
|    Jeu tres simple base sur le         |
|    classique pong. Utilise les curses. |
|                                        |
| Auteur: Martin Boulianne               |
| e-mail: frzburn@gmail.com            	 |
\****************************************/

#include <unistd.h>
#include <stdlib.h>
#include <curses.h>
#include <termios.h>
#include <term.h>

/* Constants definitions */
#define SCREEN_HEIGHT 		40	/* Set the screen height */
#define SCREEN_WIDTH 		120	/* Set the screen width */
#define LOCAL_ESCAPE_KEY	27	/* Local escape key code */
#define BALL_SPEED		1	/* Set the ball movement speed */

static struct termios initial_settings, new_settings;
static int peek_character = -1;

/* Functions prototypes */
void printTable(char table[SCREEN_HEIGHT + 1][SCREEN_WIDTH + 1]);
void init_keyboard();
void close_keyboard();
int move_ball(char table[SCREEN_HEIGHT + 1][SCREEN_WIDTH + 1]);
int kbhit();
int readch();

/* Global variables */
int pad1, pad2;		/* Actual pads position */
int pad1_, pad2_;	/* Old pads position */
int ball_x, ball_y;	/* Actual ball position */
int ball_xi, ball_yi;	/* Ball deplacement vector */
int ball_x_, ball_y_;	/* Old ball position */

int main(int argc, char *argv[])
{
    int i, j, key;
    char table[SCREEN_HEIGHT + 1][SCREEN_WIDTH + 1];

    /* Variables initialisation */
    pad1 = SCREEN_HEIGHT / 2 - 2;
    pad2 = pad1;
    pad1_ = pad1;
    pad2_ = pad1;
    ball_y = 16;
    ball_x = 70;
    ball_y_ = ball_y;
    ball_x_ = ball_x;
    ball_xi = -2;		/* Giving initial ball movement */
    ball_yi = -1;

    /* Puts empty character in each table case */
    for(i = 0; i < SCREEN_HEIGHT; i++) {
        for(j = 0; j < SCREEN_WIDTH; j++) {
            table[i][j] = ' ';
        }
    }

    /* Make the borders of the table */
    for(i = 0; i <= SCREEN_HEIGHT; i++) {
       table[i][0] = 'X';
       table[i][SCREEN_WIDTH] = 'X'; 
    }

    for(i = 0; i <= SCREEN_WIDTH; i++) {
       table[0][i] = 'X';
       table[SCREEN_HEIGHT][i] = 'X';
    }

    /* Put the ball in the table */
    table[ball_y][ball_x] = 'O';

    /* Put the pads in the table */
    for(i = 0; i < 8; i++) {
	table[pad1 + i][SCREEN_WIDTH - 4] = 'H';
	table[pad2 + i][4] = 'H';
    }

    initscr();

    printTable(table);

    /* Now we're ready to manage the keys pressed */
    crmode();
    keypad(stdscr, TRUE);
    noecho();

    key = getch();
    init_keyboard();

    while(1) {
        clrtoeol();

	if(kbhit())
		key = readch();

        switch(key) {
            case 'o':
		if(pad1 > 1)
		    pad1 -= 1;
		break;
	    case 'l':
		if(pad1 < SCREEN_HEIGHT - 8)
		    pad1 += 1;
		break;
	    case 'w':
		if(pad2 > 1)
		    pad2 -= 1;
		break;
	    case 's':
	        if(pad2 < SCREEN_HEIGHT - 8)
			pad2 += 1;
 	        break;
        }

	switch(move_ball(table)) {
	     case 1:
		move(SCREEN_HEIGHT + 3, 5);
		printw("%s", "Player 1 won!");
		getch();
		endwin();
		exit(EXIT_SUCCESS);
	    case 2:
		move(SCREEN_HEIGHT + 3, 5);
                printw("%s", "Player 2 won!");
		getch();
		endwin();
		exit(EXIT_SUCCESS);
	}

        printTable(table);

        pad1_ = pad1;
	pad2_ = pad2;
	ball_y_ = ball_y;
	ball_x_ = ball_x;

	key = 0;

	usleep(100000);
   }
   close_keyboard();

    getch();
    endwin();
    exit(EXIT_SUCCESS);
}

/* Refresh the ball position in the table and manage collisions */
int move_ball(char table[SCREEN_HEIGHT + 1][SCREEN_WIDTH + 1])
{
    /* If the ball reches the top or the bottom */
    if(((ball_y + ball_yi * BALL_SPEED) <= 0) || ((ball_y + ball_yi * BALL_SPEED) >= (SCREEN_HEIGHT)))
	ball_yi = -ball_yi;

    /* If the ball hit the left paddle */
    if(((ball_x + ball_xi * BALL_SPEED) <= 4) && (((ball_y + ball_yi * BALL_SPEED) >= pad2))) { 
        if((ball_y + ball_yi * BALL_SPEED) <= pad2 + 8)
	    ball_xi = -ball_xi;
    }

    /* If the ball hit the right paddle */
    if(((ball_x + ball_xi * BALL_SPEED) >= SCREEN_WIDTH - 4) && (((ball_y + ball_yi * BALL_SPEED) >= pad1))) {
        if((ball_y + ball_yi * BALL_SPEED) <= pad1 + 8)
            ball_xi = -ball_xi;
    }

    /* If it passes either paddle */
    if((ball_x + ball_xi * BALL_SPEED) <= 0)
	return 1;

    if((ball_x + ball_xi * BALL_SPEED) >= SCREEN_WIDTH)
	return 2;

    ball_y += ball_yi * BALL_SPEED;
    ball_x += ball_xi * BALL_SPEED;

    table[ball_y_][ball_x_] = ' ';
    table[ball_y][ball_x] = 'O';

    return 0;
}

/* Print the whole table on the screen */
void printTable(char table[SCREEN_HEIGHT + 1][SCREEN_WIDTH + 1])
{
    int i, j;

    /* Refresh pads position */
    for(i = 0; i < 8; i++) {
        table[pad1_ + i][SCREEN_WIDTH - 4] = ' ';
        table[pad2_ + i][4] = ' ';
    }
    for(i = 0; i < 8; i++) {
        table[pad1 + i][SCREEN_WIDTH - 4] = 'H';
        table[pad2 + i][4] = 'H';
    }

    /* Print the whole table on the screen */
    for(i = 0; i <= SCREEN_HEIGHT; i++) {
        for(j = 0; j <= SCREEN_WIDTH; j++) {
            move(i, j);
            addch(table[i][j]);
        }
    }

    /* Move the cursor away from the table */
    move(SCREEN_HEIGHT + 5, SCREEN_WIDTH + 5);
    addch(' ');

    refresh();
}

void init_keyboard()
{
    tcgetattr(0,&initial_settings);
    new_settings = initial_settings;
    new_settings.c_lflag &= ~ICANON;
    new_settings.c_lflag &= ~ECHO;
    new_settings.c_lflag &= ~ISIG;
    new_settings.c_cc[VMIN] = 1;
    new_settings.c_cc[VTIME] = 0;
    tcsetattr(0, TCSANOW, &new_settings);
}

void close_keyboard()
{
    tcsetattr(0, TCSANOW, &initial_settings);
}

int kbhit()
{
    char ch;
    int nread;

    if(peek_character != -1)
        return 1;
    new_settings.c_cc[VMIN]=0;
    tcsetattr(0, TCSANOW, &new_settings);
    nread = read(0, &ch, 1);
    new_settings.c_cc[VMIN]=1;
    tcsetattr(0, TCSANOW, &new_settings);

    if(nread == 1) {
        peek_character = ch;
        return 1;
    }
    return 0;
}

int readch()
{
    char ch;

    if(peek_character != -1) {
        ch = peek_character;
        peek_character = -1;
        return ch;
    }
    read(0, &ch, 1);
    return ch;
}

Conclusion :


Bon, c'est encore incomplet, je viens tout juste de finir de le faire fonctionner.
Et le code pourrait etre optimisé, sa ne fait aucun doute =P
Ha, ya les characteres aussi que je veux changer, mettre un rectangle plein a place des 'X' et des 'H'...
Mais pour l'instant c'est ca... Je suis tanné pour aujourd'hui....
Pour compiler, oubliez pas de mettre les curses. Sa devrait ressembler a :
cc main.c -o pong -lcurses (et -Wall et tout ca si vous voulez =P)

A voir également

Ajouter un commentaire Commentaires
Messages postés
5
Date d'inscription
lundi 23 août 2004
Statut
Membre
Dernière intervention
3 juin 2011

Je tiens à dire qu'il fonctionne très bien sur Mac Os X :)
Messages postés
9
Date d'inscription
vendredi 25 avril 2003
Statut
Membre
Dernière intervention
11 mars 2008

Hey allo! J'avais complètement oublié que j'avais poster des sources ici depuis le temps :O
Pour l'alignement dans les switch, tout semble correct. Je crois qu'à l'origine le code était mal aligné, comme si il y avait trop de 'tab' ou pas assez. Mais peu importe, tout est bien là.

Pour les commentaires en anglais, et bien essentiellement tout ce que je fais est en anglais. Mon OS est en anglais, mes logiciels, je travail en anglais et c'est comme ça que j'aime ça. Et oui, en même temps ça rend le code (les commentaires en fait) compréhensibles pour plus de monde.

Pour les X changés en rectangle, sérieusement je ne sais pas, du moins je ne me rapelle plus :O Probablement que je ne savais pas comment faire!! ;P

Finalement, c'est noté pour le nom de l'auteur original. Voilà donc mon vrai nom plutôt que mon 'nickname'.


Merci!
Messages postés
4
Date d'inscription
mercredi 31 octobre 2007
Statut
Membre
Dernière intervention
10 mars 2008

1 ans aprés...
Je suis tombé sur cette source (d'autres aussi) et ça me choque enfin c'est plutôt louche...

Pourquoi commenter en anglais ? Aprés si c'est pour que plus de monde puissent en profiter...
Pourquoi aprés avoir codé tu dis que tu aimerais changer les X en rectangles moi perso je l'aurais fait au moment venu pas aprés la source enfin...
Le commentaire perdu pour le switch ?

Bref mettez au moins le nom du programmeur original ;)
Messages postés
121
Date d'inscription
mercredi 26 octobre 2005
Statut
Membre
Dernière intervention
14 mars 2009
1
Qu'est-ce qu'il a, l'alignement dans les switch ?
Messages postés
9
Date d'inscription
vendredi 25 avril 2003
Statut
Membre
Dernière intervention
11 mars 2008

Désolé pour l'alignement (dans les switch), je sais pas pourquoi, mais c'est tout croche une fois posté ici... Et quand je regarde pour l'editer, ben c'est correct...
En tout cas...

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.