4FCNES游戏开发教程CC65版本四字符串的输入.docx
- 文档编号:10496522
- 上传时间:2023-02-14
- 格式:DOCX
- 页数:29
- 大小:152.75KB
4FCNES游戏开发教程CC65版本四字符串的输入.docx
《4FCNES游戏开发教程CC65版本四字符串的输入.docx》由会员分享,可在线阅读,更多相关《4FCNES游戏开发教程CC65版本四字符串的输入.docx(29页珍藏版)》请在冰豆网上搜索。
4FCNES游戏开发教程CC65版本四字符串的输入
这节主要讲NES中字符(串)的输入。
在正式讲之前,我再添加几个和手柄输入相关的内容。
上一节我们定义了两各和按键状态相关的宏:
#definepresskey(k)(key&(k))
#defineiskey(k)(key==(k))
要求我们要判断的按键值是存放在变量key中,所以我们一般可以把key定义为全局变量,这样一来我们在要求手柄输入的函数中就不用再定义key了,而且可以节省一部分内存,要知道在NES中内存是十分有限的,能省则省嘛(可能是这久闹干旱,省的观念有所加深)。
。
。
还有,十分发现在有些游戏中某种动作(或事件)是只在我们按下按钮时发生的,如果我们一直按着它也不会再发生,只有当我们松开按钮再按下去时才会再次发生。
我们约定这种事件叫做downkey(),它和presskey()、iskey()是一样的。
下面我们来完成downkey():
聪明的你也许会发现了,要判断按键是不是刚按下而不是刚才就一直按着的话我们还需要一个保存上一次判断时按键的键值,我们再约定这个变量是okey,它是oldkey的简写(以后你会发现用于保存上一次值的变量我一般都是用o开头的),同样它和key一样可以声明为全局变量。
下面是实现的代码:
#definedownkey(k)(okey!
=key&&(k)&key)//okey不等于key并且当前按下了按钮k
同样我们可以实现按钮释放的判断:
#defineupkey(k)(okey!
=key&&(k)&okey)//okey不等于key并且当前没按下k
下面来做一个简单的应用,我们只用来测试按键A,代码如下:
#include"conio.h"
#include"nes.h"
#include"stdio.h"
typedefunsignedcharu8;
#defineaddress(add)(*(u8*)(add))
#definebutton_A0x80
#definebutton_B0x40
#definebutton_SELECT0x20
#definebutton_START0x10
#definebutton_UP0x08
#definebutton_DOWN0x04
#definebutton_LEFT0x02
#definebutton_RIGHT0x01
#definepresskey(k)(key&(k))
#defineiskey(k)(key==(k))
#definedownkey(k)(okey!
=key&&(k)&key)
#defineupkey(k)(okey!
=key&&(k)&okey)
u8key=0,okey=0;//定义全局变量key和okey
u8read_joystick_1()//读手柄1
{
u8n=8,joy_state=0;
address(0x4016)=01;
address(0x4016)=00;
while(n){
joy_state=(joy_state<<1)|address(0x4016)&1;
--n;
}
returnjoy_state;
}
voidmain()//主函数
{
inti;
while
(1){
key=read_joystick_1();//读取手柄一的键值
if(presskey(button_RIGHT))i++;//presskey()事件
if(presskey(button_LEFT))i--;
if(downkey(button_UP))i++;//downkey()事件
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
如果你理解了这个程序那说明你对这几个事件是理解了。
下面是这几个按钮事件的宏定义:
#definepresskey(k)(key&(k))
#defineiskey(k)(key==(k))
#definedownkey(k)(okey!
=key&&(k)&key)
#defineupkey(k)(okey!
=key&&(k)&okey)
要注意上面讲的,将key和okey定义为全局变量,并且在每次按钮事件判断结束后用okey=key;来刷新okey的值。
说实话,上面的事件判断也不是完全正确,但至少是可以应付一下,当你发现我的定义是错误的时候,希望你可以自己想一下如何去实现它。
要补充的内容算是补充完了,下面开始字符(串)的输入。
在cc65的函数库中是有字符(串)的输入函数的但是我一开始就说过了CC65不是针对NES而写的,所以它对NES的支持也特少,所有和输入相关的函数都没法用,所以我们不得不自己来写一下了。
首先是字符的输入,一个简单的函数:
charTgetc()//为了和系统库中的getc()相区分,我们在前面加一个T作为标志
{
charc='A';//一开始我们让c='A'
while
(1){
key=read_joystick_1();
if(downkey(button_UP))c++;//上一个
if(downkey(button_DOWN))c--;//下一个
if(downkey(button_A))returnc;//返回字符c
gotoxy(0,27);//跳到左下角
cprintf("%c",c);//输出表示当前的字符c
delay(5);//延时
okey=key;//刷新okey
}
}
编写如下主程序:
voidmain()//主函数
{
charinc;
inc=Tgetc();
gotoxy(1,1);
cprintf("Youinput:
%c",inc);
while
(1){
}
}
编译,运行结果如图:
一开始在左下角出现了A,按上下选择字母,在按A按钮选中,屏幕上面出现了你输入的字母。
这样选中是不是有点费力,我们就在修改一下吧。
在修改之前,我再介绍一下cc65的Ascii码,cc65提供256个字符的显示,从0到127符合ASCII码表(就是C语言课本附录中的ASCII码表),后128个事对前面128个的反显(原来白的现在变黑,原来黑的现在变白)。
下面是我得到的CC65提供的256个字符:
好吧,知道了后128个字符时对前面128个的反显了,现在我们就可以做一个新的字符输入函数了:
charTgetc()//为了和系统库中的getc()相区分,我们在前面加一个T作为标志
{
charc='A';//一开始我们让c='A'
staticu8x=1,y=1;//定义字符选取坐标为静态变量,让它开始时指向第一行第一列,即字符'A'
constcharcmap[][29]={//定义字符表,包括大小写字母,数字和部分标点
{
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,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-=`~!
@#$%^&*()_+
//[]\;',./{}|:
"<>?
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))returnc;//返回字符c
if(y<1)y=4;//合法判断
if(y>4)y=1;
if(x<1)x=27;
if(x>27)x=1;
gotoxy(0,27);//跳到左下角,显示字符表
cputs(cmap[y-1]);
delay(3);//延时
c=cmap[y-1][x-1];
gotoxy(x-1,27);//反显当前选中的字符
cputc(c+128);
delay(3);//延时
okey=key;//刷新okey
}
}
其他部分不变,编译运行,得到如下结果:
按动左右横向选择,上下纵向选择,A确定。
。
。
至此,字符的输入已经告一段落了,下面是串的输入。
聪明的你应该是知道字符串是有多个(或一个)字符构成的,所以我们的字符串输入行数可以通过调用字符输入函数(Tgetc())来实现,为了得到输入的状态(退格、确定。
。
。
)我们的Tgetc()的稍微修改一下,下面是实现和测试的代码:
#include"conio.h"
#include"nes.h"
#include"stdio.h"
typedefunsignedcharu8;
#defineaddress(add)(*(u8*)(add))
#definebutton_A0x80
#definebutton_B0x40
#definebutton_SELECT0x20
#definebutton_START0x10
#definebutton_UP0x08
#definebutton_DOWN0x04
#definebutton_LEFT0x02
#definebutton_RIGHT0x01
#definepresskey(k)(key&(k))
#defineiskey(k)(key==(k))
#definedownkey(k)(okey!
=key&&(k)&key)
#defineupkey(k)(okey!
=key&&(k)&okey)
u8key=0,okey=0;//定义全局变量key和okey
voiddelay(inti)//延时函数
{
while(i--){
waitvblank();
}
}
u8read_joystick_1()//读手柄1
{
u8n=8,joy_state=0;
address(0x4016)=01;
address(0x4016)=00;
while(n){
joy_state=(joy_state<<1)|address(0x4016)&1;
--n;
}
returnjoy_state;
}
charTgetc()//为了和系统库中的getc()相区分,我们在前面加一个T作为标志
{
staticcharc='A';//一开始我们让c='A'
staticu8x=1,y=1;//定义字符选取坐标为静态变量,让它开始时指向第一行第一列,即字符'A'
constcharcmap[][29]={//定义字符表,包括大小写字母,数字和部分标点
{
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,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-=`~!
@#$%^&*()_+
//[]\;',./{}|:
"<>?
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(downkey(button_A))returnc;//返回字符c
if(downkey(button_B))return8;//返回退格标志,我们默认为8
if(downkey(button_START))return0;//返回输入结束标志
if(y<1)y=4;//合法判断
if(y>4)y=1;
if(x<1)x=27;
if(x>27)x=1;
gotoxy(0,27);//跳到左下角,显示字符表
cputs(cmap[y-1]);
delay(3);//延时
c=cmap[y-1][x-1];
gotoxy(x-1,27);//反显当前选中的字符
cputc(c+128);
delay(3);//延时
okey=key;//刷新okey
}
}
char*Tgets(char*s,u8len)//传入参数,字符串缓冲区s和字符串最大长度len
{
char*os=s,c;
u8x,y;
x=wherex();
y=wherey();
while(c=Tgetc()){
if(c==1){//是否是退格标志,是的话则向前移一格,并赋值为0
s--;
*s=0;
}
else{//不是退格标志则赋值为c,并向后移一格
*s=c;
s++;
}
*s=0;
if(s if(s>(os+len-1))*s=0,s=os+len-1;//后端合法检测 gotoxy(x,y);//显示 cprintf("%s",os); delay(6);//延时 } returnos; } voidmain()//主函数 { chars[15]; waitvblank(); cprintf("Input: "); Tgets(s,15);//要求输入字符串 gotoxy(0,5); cprintf("Youinput: %s",s); while (1){ } } 编译运行的结果: A选择字符,B退格,START确定。 。 。 你可能会发现SELECT键还没有任何作用,我也不想给它定义什么意思了,这关键在于你的设计,你可以根据自己的设计给它附上一个意义(快捷键啊、代表空格啊。 。 。 。 ) 好了完成了基本输入,现在我们可以来做一个小小的应用了。 。 。 我们将完成输入任意年月日,返回这一天是星期几。 。 。 。 首先是求星期∏的算法,XX一下,有一大堆,也可以到我的空间上,那上面有我自己写的算法,下面是我的算法: #defineisleap(_year)(! (_year%100? _year%4: _year%400))//求是否闰年的宏 chargetweek(unsignedintyear,unsignedcharmonth,unsignedcharday)//求星期的算法,传入年月日 { unsignedintweek,i; constintmonthweek[12]={0,3,0,3,2,3,2,3,3,2,3,2}; week=day%7+5; for(i=1;i<(unsignedint)month;++i){ week+=monthweek[i]; } week+=(year%7); for(i=0;i if(isleap(i))++week; } if(month>2&&isleap(year))++week; returnweek%7; } 不懂的地方可以和我联系。 。 。 。 下面是整个求任意日期的星期的全部代码: #include"conio.h" #include"nes.h" #include"stdio.h" typedefunsignedcharu8; #defineaddress(add)(*(u8*)(add)) #definebutton_A0x80 #definebutton_B0x40 #definebutton_SELECT0x20 #definebutton_START0x10 #definebutton_UP0x08 #definebutton_DOWN0x04 #definebutton_LEFT0x02 #definebutton_RIGHT0x01 #definepresskey(k)(key&(k)) #defineiskey(k)(key==(k)) #definedownkey(k)(okey! =key&&(k)&key) #defineupkey(k)(okey! =key&&(k)&okey) u8key=0,okey=0;//定义全局变量key和okey voiddelay(inti)//延时函数 { while(i--){ waitvblank(); } } u8read_joystick_1()//读手柄1 { u8n=8,joy_state=0; address(0x4016)=01; address(0x4016)=00; while(n){ joy_state=(joy_state<<1)|address(0x4016)&1; --n; } returnjoy_state; } charTgetc()//为了和系统库中的getc()相区分,我们在前面加一个T作为标志 { staticcharc='A';//一开始我们让c='A' staticu8x=1,y=1;//定义字符选取坐标为静态变量,让它开始时指向第一行第一列,即字符'A' constcharcmap[][29]={//定义字符表,包括大小写字母,数字和部分标点 { 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,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-=`~! @#$%^&*()_+
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- FCNES 游戏 开发 教程 CC65 版本 字符串 输入