第四章 练习

原文:https://github.com/a327ex/blog/issues/18

在前面三个教程中,我们介绍了许多与本游戏没有直接关系的代码。这些代码都可以独立于该游戏使用,这也是为什么我将其称为engine代码,即使这些代码并不能真正意义上构成一个游戏引擎。随着我们游戏开发进度的推进,我将持续不断地添加属于该类别的代码,这些代码可以在多个游戏中复用。如果要说你从这一些系列教程中可以抽离出什么可重用的内容,那么这些代码绝对符合,随着时间的推移,这些代码对我而言也越来越实用。

马上我们就将进入游戏本身的开发,在继续进行下一部分教程之前,你需要熟悉之前教程里介绍的一些概念,因此让我们进行更多的练习。

目录

练习

  1. Area类中创建一个getGameObjects函数,其功能如下:

    1. -- Get all game objects of the Enemy class
    2. all_enemies = area:getGameObjects(function(e)
    3. if e:is(Enemy) then
    4. return true
    5. end
    6. end)
    7. -- Get all game objects with over 50 HP
    8. healthy_objects = area:getGameObjects(function(e)
    9. if e.hp and e.hp >= 50 then
    10. return true
    11. end
    12. end)

    它接受一个函数作为参数,该函数接受一个游戏对象作为参数,执行某些测试逻辑,最终返回测试结果(truefalse)。如果测试结果为真,则将该游戏对象添加到结果列表中,最终将结果列表返回。

  2. 思考:abcdefg值分别是多少?

    1. a = 1 and 2
    2. b = nil and 2
    3. c = 3 or 4
    4. d = 4 or false
    5. e = nil or 4
    6. f = (4 > 3) and 1 or 2
    7. g = (3 > 4) and 1 or 2
  3. 创建一个名为printAll的函数,该函数接收位置数量的参数,并将它们全部打印到控制台。例如:printAll(1, 2, 3)将打印 1,2 和 3 到控制台,printAll(1, 2, 3, 4, 5, 6, 7, 8, 9)将打印 1 ~ 9 到控制台。

  4. 与上一个练习类似,创建一个名为printText的函数,该函数接收未知数量的字符串,将它们全部连接成一个字符串,并打印到控制台。

  5. 思考:如何触发垃圾回收?

  6. 思考:如何显示 Lua 程序当前使用了多少内存?

  7. 思考:如何主动触发一个错误来终止程序执行,并打印一个自定义错误信息?

  8. 创建一个名为Rectangle的类,该类在其创建的位置绘制一个给定长宽的矩形。在屏幕上的随机位置创建 10 个随机宽高的Rectangle实例。当按下d键时,应随机删除一个矩形实例。当剩余的实例数为 0 时,应重新在屏幕的随机位置创建 10 个随机宽高的实例。

  9. 创建一个名为Circle的类,该类在其创建的位置绘制一个给定半径的圆。在屏幕上的随机位置间隔 0.25 秒创建 10 个随机半径的Circle实例,创建完所有实例后(即 2.5 秒后),每 [0.5, 1] 秒(即 0.5 ~ 1 之间的随机数,包含 0.5 和 1)删除一个随机实例。当删除所有实例后,重复创建 10 个实例的过程,并重复删除它们,这个过程将永远重复下去。

  10. Area类中创建一个queryCircleArea函数,其功能如下:

    1. -- Get all objects of class 'Enemy' and 'Projectile' in a circle of 50 radius around point 100, 100
    2. objects = area:queryCircleArea(100, 100, 50, {'Enemy', 'Projectile'})

    它接收一个位置xy和一个半径radius,以及一个包含目标类名称的字符串列表。然后它将返回以xy为中心的半径为radius的圆内所有属于这些类的对象实例。

  11. Area类中创建一个getClosestGameObject函数,其功能如下:

    1. -- Get the closest object of class 'Enemy' in a circle of 50 radius around point 100, 100
    2. closest_object = area:getClosestObject(100, 100, 50, {'Enemy'})

    它接收和queryCircleArea相同的参数,不过它只返回离圆心最近的那个实例。

  12. 思考:在调用对象方法之前,如何检查该对象上是否存在对应方法?以及在使用对象字段之前,如何判断该对线包含对应字段?

  13. 思考:仅使用一个for循环,如何将一个表的内容写入另一个表?


上一章 房间和区域概念

下一章 游戏基础