1、4FCNES游戏开发教程CC65版本四字符串的输入这节主要讲NES中字符(串 )的输入。在正式讲之前,我再添加几个和手柄输入相关的内容。上一节我们定义了两各和按键状态相关的宏:#define presskey(k) (key & (k)#define iskey(k) (key = (k)要求我们要判断的按键值是存放在变量key中,所以我们一般可以把key定义为全局变量,这样一来我们在要求手柄输入的函数中就不用再定义key了,而且可以节省一部分内存,要知道在NES中内存是十分有限的,能省则省嘛(可能是这久闹干旱,省的观念有所加深)。还有,十分发现在有些游戏中某种动作(或事件)是只在我们按下按钮
2、时发生的,如果我们一直按着它也不会再发生,只有当我们松开按钮再按下去时才会再次发生。我们约定这种事件叫做downkey(),它和presskey()、iskey()是一样的。下面我们来完成downkey():聪明的你也许会发现了,要判断按键是不是刚按下而不是刚才就一直按着的话我们还需要一个保存上一次判断时按键的键值,我们再约定这个变量是okey,它是oldkey的简写(以后你会发现用于保存上一次值的变量我一般都是用o 开头的),同样它和key一样可以声明为全局变量。下面是实现的代码:#define downkey(k) (okey!=key & (k)&key) /okey不等于key并且当前
3、按下了按钮k同样我们可以实现按钮释放的判断:#define upkey(k) (okey!=key & (k)&okey) /okey不等于key并且当前没按下k下面来做一个简单的应用,我们只用来测试按键A,代码如下:#include conio.h#include nes.h#include stdio.htypedef unsigned char u8;#define address(add) (*(u8 *)(add)#define button_A 0x80#define button_B 0x40#define button_SELECT 0x20#define button_STA
4、RT 0x10#define button_UP 0x08#define button_DOWN 0x04#define button_LEFT 0x02#define button_RIGHT 0x01#define presskey(k) (key & (k)#define iskey(k) (key = (k)#define downkey(k) (okey!=key & (k)&key)#define upkey(k) (okey!=key & (k)&okey)u8 key=0,okey=0; /定义全局变量key和okeyu8 read_joystick_1() /读手柄1 u8
5、n=8,joy_state=0; address(0x4016)=01; address(0x4016)=00; while(n) joy_state=(joy_state1)|address(0x4016)&1; -n; return joy_state;void main() /主函数 int i; while(1) key=read_joystick_1(); /读取手柄一的键值 if(presskey(button_RIGHT)i+; /presskey()事件 if(presskey(button_LEFT)i-; if(downkey(button_UP)i+; /downkey(
6、)事件 if(downkey(button_DOWN)i-; if(upkey(button_A)i+; /upkey()事件 if(upkey(button_B)i-; gotoxy(1,1); cprintf(i=%d ,i); /输出i okey=key; /刷新okey的值,方便下一次判断 编译,运行,没错误的话会得到如下运行结果:当你按下或松开不同的按钮时会i的值会发生不同的变化:按下UP或DOWN时,i值增加或减少1按着LEFT或RIGHT不动时,i值连续变化松开A或B时,i值变化1如果你理解了这个程序那说明你对这几个事件是理解了。下面是这几个按钮事件的宏定义:#define pr
7、esskey(k) (key & (k)#define iskey(k) (key = (k)#define downkey(k) (okey!=key & (k)&key)#define upkey(k) (okey!=key & (k)&okey)要注意上面讲的,将key和okey定义为全局变量,并且在每次按钮事件判断结束后用okey=key;来刷新okey的值。说实话,上面的事件判断也不是完全正确,但至少是可以应付一下,当你发现我的定义是错误的时候,希望你可以自己想一下如何去实现它。要补充的内容算是补充完了,下面开始字符(串)的输入。在cc65的函数库中是有字符(串)的输入函数的但是我一
8、开始就说过了CC65不是针对NES而写的,所以它对NES的支持也特少,所有和输入相关的函数都没法用,所以我们不得不自己来写一下了。首先是字符的输入,一个简单的函数:char Tgetc() /为了和系统库中的getc()相区分,我们在前面加一个T作为标志 char c=A; /一开始我们让c=A while(1) key=read_joystick_1(); if(downkey(button_UP)c+; /上一个 if(downkey(button_DOWN)c-; /下一个 if(downkey(button_A)return c;/返回字符c gotoxy(0,27);/跳到左下角 c
9、printf(%c,c);/输出表示当前的字符c delay(5);/延时 okey=key;/刷新okey 编写如下主程序:void main() /主函数 char inc; inc=Tgetc(); gotoxy(1,1); cprintf(You input :%c,inc); while(1) 编译,运行结果如图:一开始在左下角出现了A,按上下选择字母,在按A按钮选中,屏幕上面出现了你输入的字母。这样选中是不是有点费力,我们就在修改一下吧。在修改之前,我再介绍一下cc65的Ascii码,cc65提供256个字符的显示,从0到127符合ASCII码表(就是C语言课本附录中的ASCII码
10、表),后128个事对前面128个的反显(原来白的现在变黑,原来黑的现在变白)。下面是我得到的CC65提供的256个字符:好吧,知道了后128个字符时对前面128个的反显了,现在我们就可以做一个新的字符输入函数了:char Tgetc() /为了和系统库中的getc()相区分,我们在前面加一个T作为标志 char c=A; /一开始我们让c=A static u8 x=1,y=1;/定义字符选取坐标为静态变量,让它开始时指向第一行第一列,即字符A const char cmap29= /定义字符表,包括大小写字母,数字和部分标点 0x41,0x42,0x43,0x44,0x45,0x46,0x4
11、7,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e, 0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x20,0x00, 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e, 0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x63,0x77,0x78,0x79,0x7a,0x20,0x00, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39
12、,0x2d,0x3d,0x60,0x7e, 0x21,0x40,0x23,0x24,0x25,0x5e,0x26,0x2a,0x28,0x29,0x5f,0x2b,0x20,0x00, 0x5b,0x5d,0x5c,0x3b,0x27,0x2c,0x2e,0x2f,0x7b,0x7d,0x7c,0x3a,0x22,0x3c, 0x3e,0x3f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00 ; /字符表如下: /ABCDEFGHIJKLMNOPQRSTUVWXYZ /abcdefghijklmnopqrstucwxyz
13、/0123456789-=!#$%&*()_+ /;,./|:? while(1) key=read_joystick_1(); if(downkey(button_UP)y-; /上一行 if(downkey(button_DOWN)y+; /下一行 if(presskey(button_LEFT)x-; /上一行 if(presskey(button_RIGHT)x+; /下一行 if(presskey(button_A)return c;/返回字符c if(y4)y=1; if(x27)x=1; gotoxy(0,27);/跳到左下角,显示字符表 cputs(cmapy-1); dela
14、y(3);/延时 c=cmapy-1x-1; gotoxy(x-1,27);/反显当前选中的字符 cputc(c+128); delay(3);/延时 okey=key;/刷新okey 其他部分不变,编译运行,得到如下结果:按动左右横向选择,上下纵向选择,A确定。至此,字符的输入已经告一段落了,下面是串的输入。聪明的你应该是知道字符串是有多个(或一个)字符构成的,所以我们的字符串输入行数可以通过调用字符输入函数(Tgetc())来实现,为了得到输入的状态(退格、确定。)我们的Tgetc()的稍微修改一下,下面是实现和测试的代码:#include conio.h#include nes.h#in
15、clude stdio.htypedef unsigned char u8;#define address(add) (*(u8 *)(add)#define button_A 0x80#define button_B 0x40#define button_SELECT 0x20#define button_START 0x10#define button_UP 0x08#define button_DOWN 0x04#define button_LEFT 0x02#define button_RIGHT 0x01#define presskey(k) (key & (k)#define is
16、key(k) (key = (k)#define downkey(k) (okey!=key & (k)&key)#define upkey(k) (okey!=key & (k)&okey)u8 key=0,okey=0; /定义全局变量key和okeyvoid delay(int i) /延时函数 while(i-) waitvblank(); u8 read_joystick_1() /读手柄1 u8 n=8,joy_state=0; address(0x4016)=01; address(0x4016)=00; while(n) joy_state=(joy_state1)|addre
17、ss(0x4016)&1; -n; return joy_state;char Tgetc() /为了和系统库中的getc()相区分,我们在前面加一个T作为标志 static char c=A; /一开始我们让c=A static u8 x=1,y=1;/定义字符选取坐标为静态变量,让它开始时指向第一行第一列,即字符A const char cmap29= /定义字符表,包括大小写字母,数字和部分标点 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e, 0x4f,0x50,0x51,0x52,0x53,0
18、x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x20,0x00, 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e, 0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x63,0x77,0x78,0x79,0x7a,0x20,0x00, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2d,0x3d,0x60,0x7e, 0x21,0x40,0x23,0x24,0x25,0x5e,0x26,0x2a,0x
19、28,0x29,0x5f,0x2b,0x20,0x00, 0x5b,0x5d,0x5c,0x3b,0x27,0x2c,0x2e,0x2f,0x7b,0x7d,0x7c,0x3a,0x22,0x3c, 0x3e,0x3f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00 ; /字符表如下: /ABCDEFGHIJKLMNOPQRSTUVWXYZ /abcdefghijklmnopqrstucwxyz /0123456789-=!#$%&*()_+ /;,./|:? while(1) key=read_joystick_1();
20、 if(downkey(button_UP)y-; /上一行 if(downkey(button_DOWN)y+; /下一行 if(presskey(button_LEFT)x-; /上一行 if(presskey(button_RIGHT)x+; /下一行 if(downkey(button_A)return c;/返回字符c if(downkey(button_B)return 8;/返回退格标志,我们默认为8 if(downkey(button_START)return 0;/返回输入结束标志 if(y4)y=1; if(x27)x=1; gotoxy(0,27);/跳到左下角,显示字符
21、表 cputs(cmapy-1); delay(3);/延时 c=cmapy-1x-1; gotoxy(x-1,27);/反显当前选中的字符 cputc(c+128); delay(3);/延时 okey=key;/刷新okey char *Tgets(char *s,u8 len)/传入参数,字符串缓冲区s和字符串最大长度len char *os=s,c; u8 x,y; x=wherex(); y=wherey(); while(c=Tgetc() if(c=1) /是否是退格标志,是的话则向前移一格,并赋值为0 s-; *s=0; else /不是退格标志则赋值为c,并向后移一格 *s=
22、c; s+; *s=0; if(s(os+len-1)*s=0,s=os+len-1;/后端合法检测 gotoxy(x,y); /显示 cprintf(%s ,os); delay(6); /延时 return os;void main() /主函数 char s15; waitvblank(); cprintf(Input:); Tgets(s,15); /要求输入字符串 gotoxy(0,5); cprintf(You input:%s,s); while(1) 编译运行的结果:A选择字符,B退格,START确定。你可能会发现SELECT键还没有任何作用,我也不想给它定义什么意思了,这关键
23、在于你的设计,你可以根据自己的设计给它附上一个意义(快捷键啊、代表空格啊。)好了完成了基本输入,现在我们可以来做一个小小的应用了。我们将完成输入任意年月日,返回这一天是星期几。首先是求星期的算法,XX一下,有一大堆,也可以到我的空间上,那上面有我自己写的算法,下面是我的算法:#define isleap(_year) (!(_year%100 ? _year%4 : _year%400) /求是否闰年的宏char getweek(unsigned int year,unsigned char month,unsigned char day) /求星期的算法,传入年月日 unsigned int
24、 week,i; const int monthweek12=0,3,0,3,2,3,2,3,3,2,3,2; week=day%7+5; for(i=1; i(unsigned int)month; +i) week+=monthweeki; week+=(year%7); for(i=0; i2 & isleap(year)+week; return week%7;不懂的地方可以和我联系。下面是整个求任意日期的星期的全部代码:#include conio.h#include nes.h#include stdio.htypedef unsigned char u8;#define addr
25、ess(add) (*(u8 *)(add)#define button_A 0x80#define button_B 0x40#define button_SELECT 0x20#define button_START 0x10#define button_UP 0x08#define button_DOWN 0x04#define button_LEFT 0x02#define button_RIGHT 0x01#define presskey(k) (key & (k)#define iskey(k) (key = (k)#define downkey(k) (okey!=key & (
26、k)&key)#define upkey(k) (okey!=key & (k)&okey)u8 key=0,okey=0; /定义全局变量key和okeyvoid delay(int i) /延时函数 while(i-) waitvblank(); u8 read_joystick_1() /读手柄1 u8 n=8,joy_state=0; address(0x4016)=01; address(0x4016)=00; while(n) joy_state=(joy_state1)|address(0x4016)&1; -n; return joy_state;char Tgetc() /为
27、了和系统库中的getc()相区分,我们在前面加一个T作为标志 static char c=A; /一开始我们让c=A static u8 x=1,y=1;/定义字符选取坐标为静态变量,让它开始时指向第一行第一列,即字符A const char cmap29= /定义字符表,包括大小写字母,数字和部分标点 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e, 0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x20,0x00, 0x61,
28、0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e, 0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x63,0x77,0x78,0x79,0x7a,0x20,0x00, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2d,0x3d,0x60,0x7e, 0x21,0x40,0x23,0x24,0x25,0x5e,0x26,0x2a,0x28,0x29,0x5f,0x2b,0x20,0x00, 0x5b,0x5d,0x5c,0x3b,0x27,0x2c,0x2e,0x2f,0x7b,0x7d,0x7c,0x3a,0x22,0x3c, 0x3e,0x3f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00 ; /字符表如下: /ABCDEFGHIJKLMNOPQRSTUVWXYZ /abcdefghijklmnopqrstucwxyz /0123456789-=!#$%&*()_+
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2