首页 资讯中心 硬件周边 攻略中心 秘籍中心 在线动漫 CG壁纸  
专题栏目: PSP NDS GBA PS2 PS3 XBOX XBOX360 WII
PSP 游戏资料 | 玩家宝典
您的位置:游狐网 >> PSP >> 玩家宝典 >> 软件教程

菜鸟也能为PSP编程 - Lua Player 编程初级指南

[ 时间:2008-5-6 9:40:37 | 来源:电玩巴士 | 收藏本文 ] 【

5——使用数据表编写程序

  Lua中的数据表(tables)很像变量。主要区别是数据表可以用来存储多个数据,而变量只能存一个。你把它想象成一个带有很多“抽屉”存放不同内容的容器就行了。你今后编写的游戏很可能会用到数个数据表。在Lua中使用数据表基本相当于其他编程语言中使用的数列(arrays)。本课我们还会顺便学一些别的内容。

  假设我们要写一个小游戏,共有5类敌兵,2个玩家。为此我们要让程序知道这些角色的相关信息。你觉得玩家和敌兵需要什么信息呢?我相信你会有成堆的想法,不过既然你是初学,还是简单点好。首先敌兵得有生命值(health),这样才能被杀死。因此我们需要给程序提供信息以跟踪敌兵的生命值。我们还需要信息以区分我们使用的敌兵种类。对于玩家生命值自然也是不可少的。还要什么信息?比如玩家拥有的武器种类怎样!有了这些信息我们应该可以开始了。

  现在开始数据表的学习。下文中的代码只有我们明确说明的才需要添加到你的程序中去。因为本课我会给出几个你并不需要的参考代码。

  数据表的定义方式:

代码:

tablename = { }

  首先是数据表名(任何你喜欢的名字),然后是等号,然后是左右(开闭)尖括号。这样就创建了一个空的数据表。要为数据表赋值,只要把数据放进括号里就行,用逗号隔开。这里有个例子:

代码:

myTable = { 12, 14, 16, 18, 20 }

  记住它的用法跟变量完全相同。只是看起来有点不一样。现在叫你使用方法。数据表内的每个数据作为一个数列元素而被索引,这样我们只需使用数据表名加上内有索引号的开闭方括号就能调用该数据。没搞懂?!看看下例吧:

代码:

luckyNumber = myTable[1]

  此处我们将数据表的第一个数据的值(12)赋予了变量luckyNumber。再回看一下我们刚创建的数据表,总共有几个数据在内?如果你说5就对了。第一个是12,第二个是14,依次下去。用上述方法我们可以轻松的调用里面的数据。索引以 1 起始,而不像某些语言那样以 0 开始。下面列出了该表所有可用的数据元素:

代码:

myTable[1]
myTable[2]
myTable[3]
myTable[4]
myTable[5]

  到此我想你应该试着用数据表写自己的程序了。还记得第一课我们学过打印一行到屏幕吧?现在不用变量,而是创建一个数据表并使用print命令将其中一个元素打印出来。你也可以用多个打印语句让它打印数个或全部元素。但是记得要修改print命令的Y参数,不然就像我们之前说过的,打印结果会堆叠起来。你无需更改X参数,因为该参数只影响水平位置。程序不会自动打印到下一行,你必须告诉它这么做。你必须告诉程序向下多少个像素,以避免交叠或相距太远。就像你之前用变量打印时一样做法,只不过这次换成数据表元素:tablename[number]。去尝试一下吧,我发誓我会在这等你的!

  好了,我希望你做的不错。我还想指出,你可以先创建空的数据表,稍后再在程序中为它赋值。下面是一个示例:

代码:

myTable = { } myTable[1] = "apple" myTable[2] = "orange" myTable[3] = "banana"

  你一定注意到了,赋值除了数字,字符串也是可以的,只要你用引号括起来。

  译者注:此处你也看到不同语句可以写在一行内,只要用空格分开就行了。当然这样不利于阅读,所以我建议最好还是分行写。

  接下来我们再学一个更复杂点的数据表。你可以给数据表原属添加额外的属性,有时又被称为字典或类型。这是非常非常有用的,可以让你的代码齐整易读。让我们来看个例子。我将创建一个空数据表并在下一行引入这一方法。

代码:

shirt = { }
shirt[1] = { color = "blue", size = "small" }

  我们做的就是创建一个数据表,并在其中的shirt[1]元素中创建了另一个数据表。现在假设程序要获取衬衫的颜色和尺寸。方法如下:

代码:

shirt[1].color
shirt[1].size

  如果我们在print语句中或者任何其他命令中使用,shirt[1].color 的结果将是 blue,而 shirt[1].size 的结果将是 small。这个搭配不是很糟啦,不用想太多!

  现在回到我们的程序上来。首先,我们要创建一个数据表存放我们的敌兵信息。这包括敌兵的生命值和敌兵类型。这是我们程序的第一行代码(终于!),所以赶紧复制到新的script.lua文件中去吧。第一行仍旧是我们的老朋友,色彩对象。你可以随意改用绿色以外的颜色。

代码:

green = Color.new(0, 255, 0)
Enemy = { }
Enemy[1] = { type = "gargoyle", health = 100 }
Enemy[2] = { type = "vampire", health = 100 }
Enemy[3] = { type = "goomba", health = 100 }
Enemy[4] = { type = "ghost", health = 100 }
Enemy[5] = { type = "zombie", health = 100 }

  就是这样。现在我们创建了5个敌兵元素,并告诉程序它们的种类和总生命值。现在添加关于玩家的代码。

代码:

Player = { }
Player[1] = { weapon = "sword", health = 100 }
Player[2] = { weapon = "knife", health = 100 }

  这样我们的示例程序所需的信息就都有了。请注意,在一个能移动的真正游戏中,Player数据表将是存储玩家在屏幕上所处位置的完美之处,敌兵则利用Enemy数据表。本例中不会有任何角色移动,所以我们还是留待以后再讨论这个问题。我们将要做的是将玩家和敌兵的信息打印到屏幕上,并在按下 X 键时取走敌兵的生命值。我们只选一个敌兵和玩家 1 做这件事。可怜的玩家 2 就得坐冷板凳了,还有除了敌兵 1 外的其他敌兵,等待下一个教程吧。

  接下来我们就要进入我们的游戏循环。其中我们还会用到按钮的设置代码,你应该还记得吧。复制下述代码到你的程序:

代码:

while true do
pad = Controls.read()

  现在添加清屏命令以便每次循环时清空屏幕。

代码:

screen:clear()

  然后在每次循环中打印玩家的生命值和武器信息到屏幕上。

代码:

screen:print(5,10,"Player 1 Health: " .. Player[1].health,green)
screen:print(5,20,"Player 1 Weapon: " .. Player[1].weapon,green)

  以免你又迷失了,我们解释一下。第一条print语句表明将在X坐标值5、Y坐标值10的地方打印,也就是距屏幕左端5个像素、顶端10个像素的位置。PSP的屏幕是宽480像素,高272像素。后面的"Player 1 Health: "即表明在该位置打印此字符串,然后我们将数据表元素 Player[1].health 串联(还记得吗?)其后,这样它的值将打印在该字符串右侧。还记得Player[1].health 里存储的是什么吗?你应该记得!最后,是我们用了数次的色彩对象。第二句在屏幕稍低的位置,就是第一行下方,用同样的方法打印不同的信息。

  现在让我们在屏幕另一侧打印我们的敌兵信息。添加下述代码:

代码:

screen:print(250,10,"Enemy Health: " .. Enemy[1].health,green)
screen:print(250,20,"Enemy Type: " .. Enemy[1].type,green)

  接下来我们使用按钮输入命令侦测X键是否按下,如果是则从敌兵生命值中减去5。添加下述代码:

代码:

if pad:cross() then
Enemy[1].health = Enemy[1].health - 5
end

  这是说如果 X 键按下则从 Enemy[1].health 元素的值中减去5。

  最后,让我们缓存、翻屏并终止循环。添加下述代码:

代码:

screen.waitVblankStart()
screen.flip()
end

  保存运行,测试一下吧。然后赶紧回来!

  啊哦,怎么回事!敌兵的生命值下降太快了,都变成负值了!可不能在游戏中这么搞!这向你显示了循环执行的速度有多快。我们可以修正它,仅在按下X键时减生命值,按住时不减。

  首先在代码顶端的数据表之前添上此行。在色彩变量之前或之后都可以。

代码:

oldpad = Controls.read()

  其次找到代码行 "if pad:cross() then" 更改如下:

代码:

if pad:cross() and oldpad:cross() ~= pad:cross() then

  ...最后,就在 screen.flip() 之后和 "end" 之前添加此行:

代码:

oldpad = pad

  目前我们暂时不纠缠于细节。简单的说,此代码检测你按下的按钮是否上一循环相同,如果是,则“if”语句不会执行。~= 表示“不相等”。我们很快会学到运算符的。

  保存运行,测试一下。

  怎样,运行的不错,除了还会变成负数以外。正好,我们正要学习另一个运算符呢。

  找到代码行 "if pad:cross() and oldpad:cross() ~= pad:cross() then" 更改如下:

代码:

if pad:cross() and oldpad:cross() ~= pad:cross() and Enemy[1].health > 0 then

  我们添加了 Enemy[1].health > 0 这个条件。 > 表示“大于”,可能你已经知道了。所以修改后的整行代码表示如果X键按下,并且没有按住与上一循环相同的按钮,并且敌兵的生命值大于0则执行随后的语句(生命值减5)。注意要执行此代码就必须所有条件都满足。

  保存运行,现在应该一切正常了。敌兵的生命值不会变得小于0。

  本课到此为止。注意本课的重点是数据表。所以其他东西你不是完全理解也没关系。该休息一下了,下节课再见。