#define NOWHERE 0 #define LEFT_ 1 #define RIGHT_ 2 #define UP_ 3 #define DOWN_ 4 #define STANDING 1 #define JUMPING 2 #define FALLING 3 #define JUMP_HEIGHT 11 #define TIMESTEP 100000 typedef struct { char l; int r,c; } body_part; typedef struct __f{ char w; int r,c; struct __f *next; } scenery; typedef struct { body_part head, body, rarm, larm, rleg, lleg; int state, r, c, rj, w, h; } character; FILE *map=0; int usemap=0; character mainChar; scenery *scene=0; int get_w (character we) { if (we.rarm.c - we.larm.c > we.rleg.c - we.lleg.c) return we.rarm.c - we.larm.c; else return we.rleg.c - we.lleg.c; } int get_h (character we) { return we.lleg.r-we.head.r; } void init_curses() { initscr (); keypad (stdscr, TRUE); noecho (); cbreak (); curs_set (0); clear (); refresh (); } void add (scenery **m, char a, int r, int c) { scenery *amf = (scenery*) malloc (sizeof (scenery)); amf->r = r; amf->c = c; amf->w = a; amf->next = *m; (*m) = amf; } void draw_scenery (scenery *node) { if (node) { mvaddch (node->r,node->c,node->w); draw_scenery (node->next); } } void init_scenery (scenery **s) { if (!usemap) { int temp; for (temp = 15; temp < 23; ++temp) add (s, '_', LINES-5, temp); for (temp = 25; temp < 45; ++temp) add (s, '_', LINES-12, temp); draw_scenery (*s); } else { int mn, r=0,c=0; while ((mn = fgetc (map)) != EOF) { if (mn != '*' && mn != '\n') add (s,mn,r,c); if (mn != '\n') { ++c; if (c>=COLS || mn == '\n') { ++r; c=0; } } if (r >= LINES) break; } } } void init_character (character *m) { m->head.l = 'o'; m->head.r = 0; m->head.c = 1; m->body.l = '|'; m->body.r = 1; m->body.c = 1; m->larm.l = '/'; m->larm.r = 1; m->larm.c = 0; m->rarm.l = '\\'; m->rarm.r = 1; m->rarm.c = 2; m->lleg.l = '/'; m->lleg.r = 2; m->lleg.c = 0; m->rleg.l = '\\'; m->rleg.r = 2; m->rleg.c = 2; m->state = FALLING; m->r = LINES-get_h(*m)-1; m->c = 4; m->rj = m->r; } void draw (character v) { mvaddch (v.r+v.head.r,v.c+v.head.c,v.head.l); mvaddch (v.r+v.body.r,v.c+v.body.c,v.body.l); mvaddch (v.r+v.larm.r,v.c+v.larm.c,v.larm.l); mvaddch (v.r+v.rarm.r,v.c+v.rarm.c,v.rarm.l); mvaddch (v.r+v.lleg.r,v.c+v.lleg.c,v.lleg.l); mvaddch (v.r+v.rleg.r,v.c+v.rleg.c,v.rleg.l); } void undraw (character v) { mvaddch (v.r+v.head.r,v.c+v.head.c,32); mvaddch (v.r+v.body.r,v.c+v.body.c,32); mvaddch (v.r+v.larm.r,v.c+v.larm.c,32); mvaddch (v.r+v.rarm.r,v.c+v.rarm.c,32); mvaddch (v.r+v.lleg.r,v.c+v.lleg.c,32); mvaddch (v.r+v.rleg.r,v.c+v.rleg.c,32); } scenery *collision (int r, int c, int w, int h, scenery *s) { if (s) if (s->r >= r && s->r <= r+h && s->c >= c && s->c <= c+w) return s; else return collision (r,c,w,h,s->next); else return 0; } void move_char (character *cc, int wh,scenery *cenery) { draw_scenery (cenery); undraw (*cc); switch (wh) { case LEFT_: if (cc->c > 0 && cc->state != FALLING && !collision(cc->r,cc->c-1,get_w(*cc),get_h(*cc)-1,cenery)) --cc->c; if (cc->state != JUMPING) cc->state = FALLING; break; case RIGHT_: if (cc->c+get_w(*cc) < COLS-1 && cc->state != FALLING && !collision(cc->r,cc->c,get_w(*cc)+1,get_h(*cc)-1,cenery)) ++cc->c; if (cc->state != JUMPING) cc->state = FALLING; break; case UP_: if (cc->state!=JUMPING && cc->state!=FALLING) { cc->state = JUMPING; cc->rj = cc->r; cc->larm.l = '\\'; cc->larm.r = 0; cc->larm.c = 0; cc->rarm.l = '/'; cc->rarm.r = 0; cc->rarm.c = 2; } break; } if (cc->state == JUMPING) { --cc->r; if (cc->rj-cc->r >= JUMP_HEIGHT || collision(cc->r,cc->c,get_w(*cc),get_h(*cc)-1,cenery)) cc->state = FALLING; } else if (cc->state == FALLING) { ++cc->r; if (cc->r >= LINES-get_h(*cc) || collision(cc->r,cc->c,get_w(*cc),get_h(*cc),cenery)) { cc->state = STANDING; if (cc->r >= LINES-get_h(*cc)) --cc->r; else { scenery *tmp = collision(cc->r,cc->c,get_w(*cc),get_h(*cc),cenery); cc->r = tmp->r-get_h(*cc)-1; } cc->rarm.l = '/'; cc->rarm.r = 1; cc->rarm.c = 0; cc->larm.l = '\\'; cc->larm.r = 1; cc->larm.c = 2; } } draw (*cc); } void handler (int a) { switch (a) { case SIGALRM: move_char (&mainChar,NOWHERE,scene); refresh (); break; case SIGTERM: case SIGINT: endwin (); exit (0); break; } } void init_singal() { struct itimerval it; timerclear(&it.it_interval); timerclear(&it.it_value); it.it_interval.tv_usec = TIMESTEP; it.it_value.tv_usec = TIMESTEP; setitimer(ITIMER_REAL, &it, NULL); struct sigaction sa; sa.sa_handler = handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGALRM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction(SIGTSTP, &sa, NULL); }