pong game using ncurses
2015-07-12 16:48
351 查看
bounce2d2.c
bounce.h
set_ticker.c
====================================================================================================
A different version:
View Code
/* * bounce2d 1.0 * bounce a character (default is 'o') around the screen * defined by some parameters * user input: s slow down x component, S: slow y component * f speed up x component, F: speed y component * Q quit * blocks on read, but timer tick sends SIGALRM caught by ball_move * build: cc bounce2d.c set_ticker.c -lcurses -o bounce2d */ #include <curses.h> #include <string.h> #include <signal.h> #include "bounce.h" struct ppball the_ball; /** the main loop **/ //int flap_pos = RIGHT_EDGE / 2 - LEFT_EDGE; int flap_pos =0; int old_pos = 0; void set_up(); void wrap_up(); void move_flap(); int bounce_or_lose(struct ppball *); int main() { // printf("LEFT_EDGE: %d, RIGHT_EDGE: %d\n",LEFT_EDGE, RIGHT_EDGE); // printf("TOP_EDGE: %d, BOT_EDGE: %d\n",TOP_ROW, BOT_ROW); int c; set_up(); while (((c = getchar())) != 'Q') { if (c == 'f') the_ball.x_ttm--; else if (c == 's') the_ball.x_ttm++; else if (c == 'F') the_ball.y_ttm--; else if (c == 'S') the_ball.y_ttm++; else if (c == 'a'){ if (flap_pos > LEFT_EDGE){ old_pos = flap_pos; flap_pos -= FLAP_SPEED; move_flap(); } }else if (c == 'd'){ if (flap_pos + (int)strlen(FLAP) < RIGHT_EDGE){ old_pos = flap_pos; flap_pos += FLAP_SPEED; move_flap(); } } } wrap_up(); // printf("LINES: %d, COLS: %d\n",LINES, COLS); return 0; } void set_up() /* * init structure and other stuff */ { void ball_move(int); the_ball.y_pos = Y_INIT; the_ball.x_pos = X_INIT; the_ball.y_ttg = the_ball.y_ttm = Y_TIM; the_ball.x_ttg = the_ball.x_ttm = X_TIM; the_ball.y_dir = 1; the_ball.x_dir = 1; the_ball.symbol = DFL_SYMBOL; the_ball.x_moved = the_ball.y_moved = false; initscr(); noecho(); crmode(); signal(SIGINT, SIG_IGN); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); move_flap(); signal(SIGALRM, ball_move); set_ticker(1000 / TICKS_PER_SEC); } void wrap_up() { set_ticker(0); endwin(); } void move_flap() { move(BOT_ROW + 1, old_pos); addstr(FLAP); //FLAP is blank. Here it is used to clear its old existence. move(BOT_ROW + 1, flap_pos); standout(); addstr(FLAP); standend(); refresh(); } void ball_move(int signum) { int y_cur, x_cur, moved; signal(SIGALRM, SIG_IGN); x_cur = the_ball.x_pos; y_cur = the_ball.y_pos; moved = 0; if (the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1){ the_ball.y_pos += the_ball.y_dir; /* move */ the_ball.y_ttg = the_ball.y_ttm; /* reset */ the_ball.y_moved = 1; moved = 1; } if (the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1){ the_ball.x_pos += the_ball.x_dir; /* move */ the_ball.x_ttg = the_ball.x_ttm; /* reset */ the_ball.x_moved = 1; moved = 1; } if (moved){ mvaddch(y_cur, x_cur, BLANK); mvaddch(y_cur, x_cur, BLANK); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); if(bounce_or_lose(&the_ball)){ // signal(SIGALRM, SIG_IGN); move(LINES / 2, COLS / 2); addstr("GAME OVER"); refresh(); return; } move(LINES-1, COLS-1); if (the_ball.x_moved && the_ball.y_moved){ refresh(); the_ball.x_moved = the_ball.y_moved = false; /* reset */ } } signal(SIGALRM, ball_move); } int bounce_or_lose(struct ppball *bp) /* * 1 lose * 0 not lose */ { int return_val = 0; if (bp->y_pos == TOP_ROW){ bp->y_dir = 1; }else if (bp->y_pos == BOT_ROW){ bp->y_dir = -1; if (!(bp->x_pos >= flap_pos && bp->x_pos <= (flap_pos + (int)strlen(FLAP)))){ return_val = 1; } } if (bp->x_pos == LEFT_EDGE){ bp->x_dir = 1; }else if (bp->x_pos == RIGHT_EDGE){ bp->x_dir = -1; } return return_val; }
bounce.h
#define BLANK ' ' #define DFL_SYMBOL 'o' #define TOP_ROW 0 #define BOT_ROW 20 #define LEFT_EDGE 0 #define RIGHT_EDGE 81 #define X_INIT 3 #define Y_INIT 5 #define TICKS_PER_SEC 50 #define Y_TIM 8 #define X_TIM 8 #define FLAP " " //#define FLAP_LEN 21 #define FLAP_SPEED 1 struct ppball { int x_ttg; // x 轴下次重画还要等待多少个计时器 int y_ttg; // y 轴下次重画还要等待多少个计时器 int x_ttm; // x 轴移动需要等待的信号间隔 int y_ttm; // y 轴移动絮叨等待的信号间隔 int y_pos; int x_pos; int y_dir; int x_dir; int x_moved; int y_moved; char symbol; };
set_ticker.c
#include <stdio.h> #include <sys/time.h> #include <signal.h> #include <stdlib.h> /* * set_ticker.c * set_ticker( number_of_milliseconds ) * arranges for the interval timer to issue * SIGALRM's at regular intervals * returns -1 on error, 0 for ok * * arg in milliseconds, converted into micro seoncds */ set_ticker( n_msecs ) { struct itimerval new_timeset; long n_sec, n_usecs; n_sec = n_msecs / 1000 ; n_usecs = ( n_msecs % 1000 ) * 1000L ; new_timeset.it_interval.tv_sec = n_sec; /* set reload */ new_timeset.it_interval.tv_usec = n_usecs; /* new ticker value */ new_timeset.it_value.tv_sec = n_sec ; /* store this */ new_timeset.it_value.tv_usec = n_usecs ; /* and this */ return setitimer(ITIMER_REAL, &new_timeset, NULL); }
====================================================================================================
A different version:
#include <curses.h> #include <sys/time.h> #include <signal.h> #define RIGHT COLS-1 /*球所能到达的当前屏幕最大水平范围*/ #define BOTTOM LINES-1 /*球所能到达的当前屏幕最大垂直范围*/ #define BOARD_LENGTH 10 /*挡板长度*/ #define LEFT 0 /*当前屏幕的最左边*/ #define TOP 0 /*当前屏幕的最上边*/ char BALL= 'O'; /*球的形状*/ char BLANK= ' '; /*覆盖球走过的轨迹*/ int left_board; /*挡板左侧坐标*/ int right_board; /*挡板右侧坐标*/ int is_lose=0; int hdir; /*控制球水平运动的变量*/ int vdir; /*控制球垂直运动的变量*/ int pos_X; /*球的横坐标*/ int pos_Y; /*球的纵坐标*/ int delay=100; void moveBall(); void init(); void control(); int main() { //初始化 curses initscr(); crmode(); /*中断模式*/ noecho(); /*关闭回显*/ move(6,28); attron(A_BOLD); addstr("Welcome to the BallGame!"); move(8,20); attroff(A_BOLD); addstr("Help:"); move(9,23); addstr("'N':Start a new game."); move(10,23); addstr("'Q':Quit game."); move(11,23); addstr("'KEY_LEFT' :Control baffle left shift."); move(12,23); addstr("'KEY_RIGHT':Control baffle right shift."); move(13,23); addstr("'KEY_UP' :Control of the ball speed."); move(14,23); addstr("'KEY_DOWN' :Control of the ball reducer."); int flag=1; char choice; move(16,24); addstr("Please choose your choice!(n/q):"); refresh(); choice=getch(); while(flag){ if(choice=='q'||choice=='Q'||choice=='n'||choice=='N') flag=0; else choice=getch(); } if(choice=='n'||choice=='N'){ /*开始游戏*/ clear(); move(10,25); addstr("BallGame will start! Are you ready?"); refresh(); sleep(3); control(); } else if(choice=='q'||choice=='Q'){ /*退出游戏*/ clear(); move(10,25); addstr("You quit the game successfully!"); refresh(); sleep(3); endwin(); } endwin(); /*结束 curses*/ return 0; } void init(){ int i,j; clear(); if(start_color()==OK){ /*改变球和挡板的颜色*/ attron(A_BOLD); /*打开粗体*/ init_pair(1,COLOR_YELLOW,COLOR_BLACK); attron(COLOR_PAIR(1)); } //初始球 pos_X =22; /*球初始的横坐标*/ pos_Y = BOTTOM-1; /*球初始的纵坐标*/ //初始化球的运动方向,朝右上方运动 hdir=1; vdir=-1; //初始挡板 left_board=20; right_board=left_board+BOARD_LENGTH; for(i=left_board;i<=right_board;i++){ /*显示挡板*/ move(BOTTOM,i); addch('-'); } //初始刷新时间 signal(SIGALRM,moveBall); set_ticker(delay); keypad(stdscr,TRUE); /*打开 keypad 键盘响应*/ attroff(A_BLINK); /*关闭 A_BLINK 属性*/ is_lose=0; move(pos_Y,pos_X); addch(BALL); move(LINES-1, COLS-1); refresh(); usleep(100000); /*睡眠*/ move(LINES-1,COLS-1); refresh(); } void moveBall(){ if(is_lose) return; signal(SIGALRM,moveBall); move(pos_Y,pos_X); addch(BLANK); pos_X += hdir; pos_Y += vdir; //改变球的方向时 if(pos_X >= RIGHT) { /*当球横坐标大于右边边缘时,球反弹朝左运动*/ hdir = -1; beep(); /*球撞墙时,发出声音*/ } if(pos_X <= LEFT) { /*当球横坐标大于左边边缘时,球反弹朝右运动*/ hdir = 1; beep(); /*球撞墙时,发出声音*/ } if(pos_Y <= TOP) { /*当球纵坐标大于顶部边缘时,球反弹朝下运动*/ vdir = 1; beep(); /*球撞墙时,发出声音*/ } //当球在底部的时候进行额外的处理 if(pos_Y >= BOTTOM-1){ if(pos_X>=left_board&&pos_X<=right_board) /*球在挡板处*/ vdir=-1; else{ /*球不在挡板处*/ is_lose=1; move(pos_Y,pos_X); addch(BALL); move(LINES-1, COLS-1); refresh(); usleep(delay*1000); /*睡眠*/ move(pos_Y,pos_X); addch(BLANK); pos_X += hdir; pos_Y += vdir; move(pos_Y,pos_X); addch(BALL); move(LINES-1, COLS-1); refresh(); } } //不改变球的方向时 move(pos_Y,pos_X); addch(BALL); move(LINES-1, COLS-1); refresh(); } void control(){ init(); int cmd; while (1) { if(!is_lose){ cmd=getch(); if(cmd=='q'||cmd=='Q'||cmd==27) break; //强制退出游戏 //挡板左移 if(cmd==KEY_LEFT){ if(left_board>0){ move(BOTTOM,right_board); addch(' '); right_board--; left_board--; move(BOTTOM,left_board); addch('-'); move(BOTTOM,RIGHT); refresh(); } } //挡板右移 else if(cmd==KEY_RIGHT){ if(right_board<RIGHT){ move(BOTTOM,left_board); addch(' '); right_board++; left_board++; move(BOTTOM,right_board); addch('-'); move(BOTTOM,RIGHT); refresh(); } } //给球加速 else if(cmd==KEY_UP){ delay/=2; set_ticker(delay); } //给球减速 else if(cmd==KEY_DOWN){ delay*=2; set_ticker(delay); } } else{ //输掉球后的处理 int flag=1; char choice; move(8,15); addstr("Game Over!try again?(y/n):"); refresh(); choice=getch(); while(flag){ if(choice=='y'||choice=='Y'||choice=='n'||choice=='N') flag=0; else choice=getch(); } if(choice=='y'||choice=='Y'){ /*游戏重新开始*/ delay=100; /*恢复球的初始速度*/ init(); continue; } else if(choice=='n'||choice=='N'){ /*结束游戏*/ break; } } } } //设置定时器 int set_ticker(int n_msecs){ struct itimerval new_timeset; long n_sec,n_usecs; n_sec=n_msecs/1000; n_usecs=(n_msecs%1000)*1000L; new_timeset.it_interval.tv_sec=n_sec; new_timeset.it_interval.tv_usec=n_usecs; new_timeset.it_value.tv_sec=n_sec; new_timeset.it_value.tv_usec=n_usecs; return setitimer(ITIMER_REAL,&new_timeset,NULL); }
View Code
相关文章推荐
- 【Cocos游戏实战】功夫小子第六课之游戏主功能场景的分析和实现
- TC SRM662 div 2
- Android Studio SDK Download interrupted: Read timed out解决
- Java的多线程
- JavaScript 中值得注意的要点(1)
- window.event
- using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin
- vs2012连接sql2012,SQLDriverConnect问题
- 1025.反转链表
- Mac下Android studio 之NDK配置教程(二)
- php运行机制
- ios开发 uiwebview加载网页时阻止禁止取消图片下载
- C&C++函数指针
- 解决Xcode编译 malformed or corrupted AST file: 'Unable to load module "错误
- Linux-6.1-网络概述
- linux学习总结之基本命令
- 基于Solr的HBase实时查询方案
- 数据的存储和界面的展现一
- XCODE 6.1 创建新白空应用
- 【剑指offer 面试题38】数字在排序数组中出现的次数