第三课
编程入门
编写程序的技巧。PSP上的C语言基础速成教程。
读过第一课和第二课后,你现在应该已经有了一个开发环境,并且已经编译了你的第一个基础的PSP应用程序。现在该是时候写点更大更好的东西了。一个"hello world"程序非常的好,通过学习它大大地丰富了我们的经验,但是它什么也没做。这篇导学就来讲一讲如何来做些东西。
你需要知道的是这篇导学不意味着PSP编程的全部。与其说是“如何建立一个游戏”不如说是一只脚踏入PSP编程之门的教程。你将在这里获得PSP(和C)编程的基础材料。你必须重新整理并把这些基础材料整合起来,才能构建出有用的程序。
阅读过第二课,或者知道如何建立一个基本的程序是这篇导学的必要条件。我们不会把建立程序的过程再进行一遍。所以,为了测试下边的代码,替换掉第二课中的
printf("Hello World.");
因为其他的代码只是用来建立我们的程序,我们不需要再讲一遍它们做了些什么。
这篇导学的最终产品是这样一个程序:计数器显示的数值不断增加直到用户按下一个按钮,或者计数器达到了实现定义好的上限。这就是这篇导学的完美程序,它组合了一些C语言编程的核心元素,来建立一个简单但是有用的程序,而不含有任何特殊的程序函数。本篇导学涵盖了:变量、if/then语句、循环、文本格式化,和按钮输入。
首先,我们需要再include两个头文件。第一个能使我们对屏幕进行一些控制(我们不久用到的一个函数会需要它)。第二个使我们能够获取按钮输入。所以要添加这两个文件(pspdisplay.h and pspctrl.h),我们需要向原先代码中的两个"#include"语句下面添加如下代码:
#include
#include
在程序创建过程中我们所要做的就只有这些。现在我们来放进有功能的代码。从这开始,所有列出的代码应该放到你的main函数中,替换第二课中的"printf"语句。我们要做的第一件事是声名在程序中要用的变量。一个变量的声名采用如下的格式:
//示例代码
//不要添加到你的程序中
type name=value;
type是变量的数据类型。每种数据类型能且仅能包含一种数据。比如:"int"(指整数)类型(type)可以存放任何一个-32767 到 32767之间的非小数的数。"float"与"int"类似,但是可以存放小数。"char"类型可以存放字母。对我们的程序来说,我们仅用到内建的"int"类型和一个PSP所特有的类型"SceCtrlData"(它是用来存放控制PSP的按钮状态的)。
所以,为了声名我们要用的这两个变量,我们插入如下两行代码到程序中(它们应该在第二课的"printf("Hello World.");"这一行的位置,就在"SetupCallbacks();"下边)
int counter = 0;
int i = 0; SceCtrlData pad;
现在我们有了3个可用的变量。两个"int"类型,名字是"counter"和"i",现在它们的值都为零。还有一个"SceCtrlData"类型名为"pad"的变量,现在的值是不可预知的(因为我们尚未对他初始化)。这是在你写程序的时候需要记住的事。如果你声名一个变量却没有初始化它(就像我们的pad变量),它不是一个空值。它含有的是那块内存中上一次的信息。声名变量仅仅是分配能够存贮它的一定量的内存空间。初始化是将它清除干净并允许我们使用它。我们声名"pad"却没有将它初始化时因为它不表示什么意义。因为它用来接受按钮输入,你不能够通过敲入一个值来初始化它。我们将在一会儿用它之前对它初始化。
现在我们为用户给出一些说明信息。我们是通过"printf"输出一句话来实现的。所以把这行代码放到变量声名之后:
printf("Press [X] To Start the Timer");
眼熟?对了。它就是我们在第二课用来输出"Hello World"的函数。所以如果你把程序运行到这里,它就像"hello world"程序一样,只不过它打印出来的是"Press [X] To Start the Timer"而不是"Hello World"。
现在我们需要程序一直等待直到用户按下[X]按钮。现在,这似乎是很难,几乎是不可能完成的事。幸运的是,我们拥有一个完美的东西来处理它。这个东西叫做循环。本质上说,它所做到就是执行一段代码很多次。你可以使用的循环有很多种(for循环、while循环、do while循环等),但是这篇导学中将只介绍两种,"while"循环和"for"循环。循环是这样工作的:你给出一个语句(控制语句),当它返回true时,循环将会重复的执行一段代码。举例来说,如果你有一段代码,每次运行时都使一个变量i(从0开始)增加1,你传给循环的控制语句是"i<10",那么它将执行你的代码10遍,因为在第11次时,i的值是10,所以控制语句"i<10"返回false。另外一个你需要掌握的重要概念是"true"和"false"分别于"1"和"0"同义。
我们的循环不是典型格式的循环。它可以是这种典型格式,但是我浏览了一些PSP工程的代码,他们大都是写成这种格式,所以我估计把它写成你会经常见到的格式应该好一点。总之,本质上说我们要做的是一个"无限循环"。但是它不是真正的无限循环,因为(我在前面没有提到)除了控制语句返回false外,还有另外一种退出循环的方法。那就是"break"语句。每当允许到这条语句时,它将退出你当前所在的循环,程序将继续运行这个循环之后的代码。所以,我们的循环这样开始:
while(1) {
正如你所看到的,控制语句的值总等于"true",因为"1"等同于"true"。所以下面的代码(在大括号之间的)将被重复执行直到遇到一个"break"语句。
下一行中我们设置"pad"的值。它利用了一个定义在"pspctrl.h"(我们在前面inclued进来的)文件中的函数。这是一个如第二课所示的函数调用,但是它看起来有点别扭。首先,我们传给它了两个值。这没什么,你只要用一个逗号把两个值分开即可。第二个有点不同的是我们传递了一个变量。这也没什么大不了的,只要用变量名替换一个数字或者字符串或者其他什么的即可。第三件奇怪的事是我们在传递的参数前加了一个"&"操作符。这实际上是"取地址"操作符,当你深入编程时,你就会熟悉它。本质上来说,它所做的是传递变量的内存地址而不是传递变量的值本身。就现在来说,只要知道为了使一个函数能够你传递给它的变量的值,你需要用"&"操作符。那么,这就是我们如何保存PSP控制的当前状态的:
sceCtrlReadBufferPositive(&pad, 1);
如果你对"1"代表什么感到疑惑,别担心。它设置了要读取的缓存数,但是我只见过"1"被用在这里。说实话,我不知道你为什么想在那用其它值(如果有人有理由的话,请提醒我,我会把它加到这里的)。
下一行是一个"if"语句。这里是你如何将逻辑编入你的程序中。它所做的是"如果"("if")语句等价于true就执行一段代码。所以,我们想做的是如果[X]按钮被按下时,就"跳出"("break")循环。这将有效地使我们的程序度过"暂停"的状态,进入下一个阶段。如果语句等价于false,它就会跳过这段代码,并且,如果有"else"语句就执行那段代码,如果没有就继续。我们没有"else"语句,所以它将再走一遍循环,继续检查按钮的状态,并且观察[X]按钮是否被按下。如此同时,我们用一个右大括号结束循环。
if(pad.Buttons & PSP_CTRL_CROSS) {
break;
}
}
"if()"中的语句翻译成中文就是"如果[X]按钮被按下"。所以如果那个按钮被按下,循环将停止,如果没有按下,它将继续循环。现在来看看计数器。
按下[X]按钮后,我们将打开计数器,它直到用户按下[O]按钮后停止。那么我们将怎么做呢?你猜,另一个循环!所以我们开始这个循环,并加入用来退出的代码(其中用"PSP_CTRL_CIRCLE"替换了"PSP_CTRL_CROSS")。
while(1) {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons & PSP_CTRL_CIRCLE) {
break;
}
现在,我们需要用一个新函数。它所做的是清除屏幕。因为"Press [X] To Start the Timer"这句话仍然显示在屏幕上,我们需要擦掉它。另外,下次循环运行到这里并且这行代码被执行时,我们需要其他的要显示到屏幕上的文字。我们需要清除掉它。所以我们要这样做:
pspDebugScreenClear();
这将清除掉屏幕上的内容,所以现在我们准备好显示计时器了(并且告诉用户如何停止计数器并且退出程序)。
第一行应该看起来很熟悉。它只是个简单"printf"语句。看起来稍微怪一点的东西是在字符串结束"/n"。"/n"是一个特殊符号,代表着换行。所以换行符等价于你在键盘上按"ENTER"键。第二个"printf"语句就有些不同了。我们需要打印出"counter"变量。为了这么做,我们要用到"%"操作符。本质上这表示你要显示一个变量,并且"%"后面的字符告诉了程序这个变量的类型。因为是整数,我们用"i"(integer; 懂了?)。我们传递的第二个参数是我们要打印出的变量。在我们这里,我们希望打印"counter"变量。所以将下面两行加入你的程序中:
printf("Press [O] To Stop the Timer/n");
printf("Counter: %i", counter);
现在我们需要把我们的计数器增加1,这样下一次循环的时候屏幕上显示的数字才会增加1。如果我们不这么做,它就不会是一个真正的计数器。我们可以用两种方式这么做。首先,一种不太普遍的做法是"counter = counter+1;"这种做法很完美,但是有一种更简单的方法。只要用"++"操作符即可为把一个变量的值加一:
counter++;
它和"counter = counter +1;"做的是同样的事,但是要更优雅一点,你不认为么?
现在我们需要插入一个短暂的停顿来使"HOME"键工作。这里我们使用一个"for"循环。这种循环仅与"while"循环有微小的差别。它有3个参数。第一个十初始化;它为循环的开始设置变量。第二个是控制语句,它与"while"循环中的控制语句完成相同的功能。第三个是在每次循环结束时,你想对你的变量做的操作。
for(i=0; i<5; i++) {
sceDisplayWaitVblankStart();
}
这将执行我们的代码5遍(当i = 0, 1, 2, 3, 和 4)。
最后,我们需要用一个简单的右打括号来结束循环运行的代码段:
}
现在只差最后的一小点了。这就是在"break"语句之后将运行的代码。我们想要显示一条简单的信息,还有我们的计数器的最终结果。所以我们清楚屏幕,并且要再用两行"printf"语句,就像我们在循环中用的那样,只不过文字不同。加入如下代码:
pspDebugScreenClear();
printf("Counter Finished.");
printf("Final Count: %i", counter);
我们终于完成了我们的代码!现在再在第二课的基础上进行一些表面上的修改。
为了反映我们的新程序,要对Makefile进行一些修改。打开它把PSP_EBOOT_TITLE改成一个你认为适合你的新程序的词。我把它命名为"Counter Program"。并且把你的TARGET改成"count"。现在请编译你的程序吧,并尝试运行。你现在应该有了创建自己程序的基本技能(至少是基于文本的应该没问题了)。你可以去看看其他的C语言编程的教材,学习如何使用更复杂的逻辑控制(if/if else/else),循环,函数,指针等。PSP程序可能会有些不同,但是基础的东西都是标准的C。祝你好运,玩得愉快!
注:原文地址http://www.scriptscribbler.com/psp/tutorials/lesson03.htm
由于原文可能不定期更新,所以本译文不保证与原文保持同步