tron

le jeu des motos dans tron - retour accueil

git clone git://bebou.netlib.re/tron

Log | Files | Refs | README |

tron.c (6975B)


      1 #define TB_IMPL
      2 #include "termbox2.h"
      3 #include <time.h>
      4 
      5 #define TAIL 100
      6 #define MAX_CAR_NUMBER 3
      7 #define NB_DEFAULT_PLAYERS 2
      8 
      9 enum direction { UP, RIGHT, DOWN, LEFT };
     10 enum status { DEAD, ALIVE };
     11 
     12 typedef struct {
     13 	int x;
     14 	int y;
     15 } coord;
     16 
     17 struct bike {
     18 	coord position;
     19 	coord* path;
     20 	int direction;
     21 	int color;
     22 	int status;
     23 };
     24 
     25 struct arena {
     26 	int width;
     27 	int height;
     28 };
     29 
     30 struct bikes {
     31 	struct bike* list;
     32 	int count;
     33 };
     34 
     35 /*Helper functions*/
     36 
     37 int rd(int min, int max) { return (rand()%(max-min+1))+min; }
     38 int remain(int a, int b) { return ((a%b)+b)%b; }
     39 
     40 /*Display functions*/
     41 
     42 void display_title_screen(int height, int width) {
     43 	tb_printf(width/2-35/2-5,height/2-5/2,0,0,"\
     44 ████████ ██████   ██████  ███    ██\n\
     45    ██    ██   ██ ██    ██ ████   ██\n\
     46    ██    ██████  ██    ██ ██ ██  ██\n\
     47    ██    ██   ██ ██    ██ ██  ██ ██\n\
     48    ██    ██   ██  ██████  ██   ████");
     49 
     50 	tb_printf(width/2-35/2-5,height/2-5/2+5+2,0,0,"\
     51 Espace pour continuer ou mettre en pause\n\
     52 Echap pour quitter\n\
     53 \n\
     54 + pour ajouter un vélo\n\
     55 - pour retirer un vélo\n\
     56 \n\
     57 Vélo 1 ←→\n\
     58 Vélo 2 qd\n\
     59 Vélo 3 jl\n");
     60 }
     61 
     62 
     63 void display(struct bikes bikes, int ticks, struct arena arena, int timeout) {
     64 	for (int i=0;i<bikes.count;i++) {
     65 		if(bikes.list[i].status==DEAD) continue;
     66 		tb_printf(bikes.list[i].position.x,bikes.list[i].position.y,bikes.list[i].color,0,"●");
     67 		for (int j=0;j<TAIL;j++)
     68 			if(bikes.list[i].path[j].x!=0 && bikes.list[i].path[j].y!=0)
     69 				tb_printf(bikes.list[i].path[j].x,bikes.list[i].path[j].y,bikes.list[i].color,0,"▒");
     70 		tb_printf(arena.width+1,i*5,bikes.list[i].color,0,"vélo %d\nx: %d\ny: %d\ndir %d\n",i+1,bikes.list[i].position.x,bikes.list[i].position.y,bikes.list[i].direction);
     71 	}
     72 	tb_printf(arena.width+1,arena.height-2,0,0,"t %d\ns %d",ticks,timeout);
     73 	tb_print(0,0,0,0,"╭");
     74 	tb_print(0,arena.height,0,0,"╰");
     75 	tb_print(arena.width,0,0,0,"╮");
     76 	tb_print(arena.width,arena.height,0,0,"╯");
     77 	for (int i=1;i<arena.width;i++) {
     78 		tb_print(i,0,0,0,"─");
     79 		tb_print(i,arena.height,0,0,"─");
     80 	}
     81 	for (int i=1;i<arena.height;i++) {
     82 		tb_print(0,i,0,0,"│");
     83 		tb_print(arena.width,i,0,0,"│");
     84 	}
     85 }
     86 
     87 /*Logic functions*/
     88 
     89 void update(struct bike *bike, coord *incs) {
     90 	for(int i=TAIL-1;i>0;i--) bike->path[i]=bike->path[i-1];
     91 	bike->path[0]=bike->position;
     92 	bike->position.x=bike->position.x+incs[bike->direction].x;
     93 	bike->position.y=bike->position.y+incs[bike->direction].y;
     94 }
     95 
     96 void createbike(int color, struct bikes *bikes, struct arena a) {
     97 	struct bike c;
     98 	c.status=ALIVE;
     99 	c.path=malloc(sizeof(coord)*TAIL);
    100 	for (int i=0;i<TAIL;i++) {
    101 		coord p; p.x=0; p.y=0;
    102 		c.path[i]=p;
    103 	}
    104 	c.color=color;
    105 	c.position.x=rd(10,a.width-10); c.position.y=rd(10,a.height-10);
    106 	if(c.position.x<a.width/2) c.direction=RIGHT; else c.direction=LEFT;
    107 	bikes->list[bikes->count]=c;
    108 	bikes->count++;
    109 }
    110 
    111 void kill_bikes(struct bikes *bikes, struct arena arena) {
    112 	for (int i=0;i<bikes->count;i++) {
    113 		if(bikes->list[i].status==DEAD) continue;
    114 		if(bikes->list[i].position.x<=0 || bikes->list[i].position.x>=arena.width || bikes->list[i].position.y<=0 || bikes->list[i].position.y>=arena.height)
    115 			bikes->list[i].status=DEAD;
    116 		for (int j=0;j<TAIL;j++)
    117 			for (int k=0;k<bikes->count;k++)
    118 				if (bikes->list[i].position.x==bikes->list[k].path[j].x && bikes->list[i].position.y==bikes->list[k].path[j].y && bikes->list[k].status==ALIVE)
    119 					bikes->list[i].status=DEAD;
    120 	}
    121 }
    122 
    123 int main(int argc, char **argv) {
    124 
    125 	/* On init des trucs */
    126 
    127 	int ticknb=0;
    128 
    129 	coord up;    up.x=0;    up.y=-1;
    130 	coord right; right.x=1; right.y=0;
    131 	coord down;  down.x=0;  down.y=1;
    132 	coord left;  left.x=-1; left.y=0;
    133 	coord incs[4] = { up, right, down, left };
    134 
    135 	srand(time(NULL));
    136 
    137 	tb_init();
    138 	tb_hide_cursor();
    139 	tb_set_input_mode(TB_INPUT_ESC | TB_INPUT_MOUSE);
    140 	struct tb_event ev;
    141 
    142 	int height=tb_height(); int width=tb_width();
    143 	struct arena arena;
    144 	arena.width=width-10; arena.height=height-1;
    145 
    146 	struct bikes bikes; bikes.count=0;
    147 	bikes.list=malloc(MAX_CAR_NUMBER*sizeof(struct bike));
    148 	for(int i=0;i<NB_DEFAULT_PLAYERS;i++)
    149 		createbike(bikes.count%8+6, &bikes, arena);
    150 
    151 	int timeout=80;
    152 	int input=0;
    153 
    154 	/*TITRE*/
    155 
    156 	/*Comme ça on sait dans quelle direction vont les vélos*/
    157 	for(int i=0;i<bikes.count;i++)
    158 		if(bikes.list[i].status==ALIVE)
    159 			update(&bikes.list[i],incs);
    160 
    161 	while(ev.ch!=32) {
    162 		tb_clear();
    163 		display_title_screen(arena.height, arena.width);
    164 		display(bikes,ticknb,arena,timeout);
    165 		tb_present();
    166 		tb_poll_event(&ev);
    167 		switch(ev.ch) {
    168 			case 43: /*+*/
    169 				if (bikes.count<MAX_CAR_NUMBER) {
    170 					createbike(bikes.count%8+6,&bikes,arena);
    171 					update(&bikes.list[bikes.count-1],incs);
    172 				} else
    173 					for (int i=0;i<bikes.count;i++)
    174 						if(bikes.list[i].status==DEAD) {
    175 							bikes.list[i].status=ALIVE;
    176 							break;
    177 						}
    178 				break;
    179 			case 45: /*-*/
    180 				for (int i=bikes.count-1;i>=0;i--)
    181 					if(bikes.list[i].status==ALIVE) {
    182 						bikes.list[i].status=DEAD;
    183 						break;
    184 					}
    185 		}
    186 		if (ev.type==TB_EVENT_RESIZE) {
    187 			arena.width=ev.w-10;
    188 			arena.height=ev.h-1;
    189 		}
    190 		if(ev.key==27) {
    191 			for (int i=0;i<bikes.count;i++) free(bikes.list[i].path);
    192 			free (bikes.list);
    193 			tb_shutdown();
    194 			return 0;
    195 		}
    196 	}
    197 
    198 	/*On joue*/
    199 
    200 	while(1) {
    201 		for(int i=0;i<bikes.count;i++)
    202 			update(&bikes.list[i],incs);
    203 		kill_bikes(&bikes,arena);
    204 		tb_clear();
    205 		display(bikes,ticknb,arena,timeout);
    206 		tb_present();
    207 		tb_peek_event(&ev, timeout);
    208 		if(ev.ch!=0) input=ev.ch;
    209 		else if (ev.key!=0) input=ev.key;
    210 		/* On accélère tous les 10 ticks */
    211 		if(ticknb%10==0 && timeout>30) timeout--;
    212 		switch(input) {
    213 			case 32: /*space*/
    214 				display_title_screen(height,width);
    215 				display(bikes,ticknb,arena,timeout);
    216 				tb_present();
    217 				do {
    218 					tb_poll_event(&ev);
    219 					if (ev.key==27) {
    220 						for (int i=0;i<bikes.count;i++) free(bikes.list[i].path);
    221 						free (bikes.list);
    222 						tb_shutdown();
    223 						return 0;
    224 					}
    225 				} while(ev.ch!=32);
    226 				break;
    227 			case 100: /*d*/
    228 				bikes.list[1].direction=remain(bikes.list[1].direction+1,4);
    229 				break;
    230 			case 113: /*q*/
    231 				bikes.list[1].direction=remain(bikes.list[1].direction-1,4);
    232 				break;
    233 			case 108: /*l*/
    234 				bikes.list[2].direction=remain(bikes.list[2].direction+1,4);
    235 				break;
    236 			case 106: /*j*/
    237 				bikes.list[2].direction=remain(bikes.list[2].direction-1,4);
    238 				break;
    239 			case 27: /*echap*/
    240 				for (int i=0;i<bikes.count;i++) free(bikes.list[i].path);
    241 				free (bikes.list);
    242 				tb_shutdown();
    243 				return 0;
    244 			case 65514: /*right*/
    245 				bikes.list[0].direction=remain(bikes.list[0].direction+1,4);
    246 				break;
    247 			case 65515: /*left*/
    248 				bikes.list[0].direction=remain(bikes.list[0].direction-1,4);
    249 				break;
    250 			default:
    251 				break;
    252 		}
    253 		input=0;
    254 		tb_printf(0,3,0,0,"ticknb : %d",ticknb++);
    255 	}
    256 	return 0;
    257 }