教程:使用网格布局 | Corona Labs - Solar2D 游戏引擎
 

教程:使用网格布局

教程:使用网格布局

许多游戏使用网格,其中棋子或物品按行和列排列。经典的例子有国际象棋或跳棋,但即使是像《糖果粉碎传奇》™ 这样的现代游戏也会将棋子放置在网格中。

从机械角度来说,网格只不过是一个二维数组,数组中的每个元素代表网格上的一个位置。在 Lua 中,二维数组基本上是一个表,其中每个子表代表网格的一行,而该行表中的每个条目代表行内的列索引。

让我们看一下演示项目中使用的核心 Lua 代码,你应该下载并配合本教程进行实验。

local GRID_WIDTH = 8
local GRID_HEIGHT = 8
local CELL_WIDTH = 40
local CELL_HEIGHT = 40
--
-- Create a 2D array to hold our objects.
local grid = {}
for i = 1, GRID_HEIGHT do
grid[i] = {}
end
--
-- load the background image:
local checkerBoard = display.newImageRect("table.png", 320, 320)
checkerBoard.x = display.contentCenterX
checkerBoard.y = display.contentCenterY
--
-- Calculate some values
--
local gbOffsetX = checkerBoard.x - ( checkerBoard.width * checkerBoard.anchorX )
local gbOffsetY = checkerBoard.y - ( checkerBoard.height * checkerBoard.anchorY )
--
-- Using positions 1, 8 for X and Y, draw the object at the right place in the grid
--
local function spawnPiece( xPos, yPos, pieceType )
if pieceType ~= "red" and pieceType ~= "white" then
print( "Invalid piece type", pieceType )
return nil
end
if xPos < 1 or xPos > GRID_WIDTH or yPos < 1 or yPos > GRID_HEIGHT then
print( "Position out of range:", xPos, yPos )
return nil
end
local piece = display.newImageRect( "token_" .. pieceType .. ".png", CELL_WIDTH, CELL_HEIGHT )
--
-- record the pieces logical position on the board
--
piece.xPos = xPos
piece.yPos = yPos
--
-- Position the piece
--
piece.x = (xPos - 1) * CELL_WIDTH + (CELL_WIDTH * 0.5) + gbOffsetX
piece.y = (yPos - 1) * CELL_HEIGHT + (CELL_HEIGHT * 0.5) + gbOffsetY
return piece
end
local function movePiece(piece, xPos, yPos )
-- check to see if the position is occupied. You can do either:
-- 1. "Capture the piece". This would involve removeing the piece
-- that is there before moving to the spot or
-- 2. "Reject the move" because the spot is occupied. For the purpose
-- of this tutorial we will reject the move.
--
if xPos < 1 or xPos > GRID_WIDTH or yPos < 1 or yPos > GRID_HEIGHT then
return false
end
if grid[yPos][xPos] == nil then -- got an empty spot
--
-- get the screen x, y for where we are moving to
--
local x = (xPos - 1) * CELL_WIDTH + (CELL_WIDTH * 0.5) + gbOffsetX
local y = (yPos - 1) * CELL_HEIGHT + (CELL_HEIGHT * 0.5) + gbOffsetY
--
-- save the old grid x, y
--
local oldXPos = piece.xPos
local oldYPos = piece.yPos
--
-- Move the object in the table
--
grid[yPos][xPos] = piece
grid[yPos][xPos].xPos = xPos
grid[yPos][xPos].yPos = yPos
grid[oldYPos][oldXPos] = nil
--
-- Now move the physical graphic
--
transition.to(grid[yPos][xPos], { time = 500, x = x, y = y})
return true
end
end
--
-- Generate a few objects
--
--
-- a holding piece for moving the object
--
local lastObject
for i = 1, 10 do
local xPos = math.random( 1, GRID_WIDTH )
local yPos = math.random( 1, GRID_HEIGHT )
local color = "red"
if math.random(2) == 2 then
color = "white"
end
grid[yPos][xPos] = spawnPiece(xPos, yPos, color, checkerBoard)
lastObject = grid[yPos][xPos]
end
timer.performWithDelay(2000, function() movePiece( lastObject, 4, 5); end, 1)
view raw gistfile1.lua hosted with ❤ by GitHub

首先,我们定义一些常量:行数和列数分别作为 GRID_WIDTHGRID_HEIGHT。我们还定义网格上每个单元格的宽度和高度,分别定义为 CELL_WIDTHCELL_HEIGHT。在此之后,我们为整个网格创建一个空表,然后我们为网格中的总行数 (GRID_HEIGHT) 执行一个循环,并在该索引位置创建一个将代表整个行的另一个空表。

接下来,我们将网格的图像放置在屏幕上,并将其定位在内容区域的中心。然后,我们创建两个常量,用于相对于图像偏移棋子。在这里,我们基于网格图像的位置和大小计算 gbOffsetXgbOffsetY

引用单元格

由于我们已经有效地创建了一个“行堆栈”,因此必须以 [row][column] 的方式引用特定的单元格,如下所示

local somePiece = grid[4][5]

此代码将引用从左侧开始的第 5 个位置(第 5 列)和从顶部开始的第 4 个位置(第 4 行)的单元格。因此,行值在先,列值在后。

现在从概念上讲,将单元格位置引用为 x,y 坐标位置,或者换句话说,以“列,行”格式引用可能更合乎逻辑。例如,跳棋棋盘左上角的空格将是 1,1,右上角的空格将是 8,1(请记住,跳棋使用 8×8 的棋盘)。因此,在调用 spawnPiece() 函数时,预计将使用 xPosyPos 两个参数来表示网格中的位置。

生成棋子

在实际的 spawnPiece() 函数中,我们首先验证传入的参数。这包括检查棋子类型并确保单元格位置不在网格范围(大小)之外。如果验证成功,我们将生成棋子的显示对象,并将棋子在棋盘上的位置存储为该对象的属性。最后,我们根据之前定义的常量将棋子放置在实际屏幕位置(像素坐标)中。

移动棋子

下一个函数用于移动棋子。在此示例中,我们通过在 2 秒的计时器后调用该函数来测试它,但这很可能是通过触摸、滑动、选择棋子并点击其目的地或任何其他方法来完成的。

无论如何,在 movePiece() 函数中,我们首先验证请求的位置是否在网格范围内,并确认该位置未被另一个棋子占用。如果验证通过,我们将移动 grid 表内棋子的位置,然后在视觉上将棋子滑动(转换)到新位置。

结论

如本教程所示,使用二维数组创建网格、存储数组中棋子的位置以及使用基本数学基于逻辑坐标定位和移动可视化棋子非常简单。请记住下载 演示项目,以便进行实验和编辑,以便在自己的基于网格的应用项目中使用。


标签
,
Rob Miracle
[email protected]

Rob 是 Corona Labs 的开发者关系经理。除了热衷于帮助其他开发人员使用 Corona 制作出色的游戏之外,他还喜欢在业余时间制作游戏。自 1979 年以来,Rob 一直在为从个人计算机到大型机编码游戏。他在游戏行业拥有超过 16 年的专业经验。

1 条评论
  • J. A. Whye
    发布于 4 月 9 日 02:53

    前段时间,我创建了一个实用程序,帮助我解决了一个基于网格的问题。给定任何大小的网格中的任何位置,我想知道它周围有哪些网格方块(左、右、上、下和对角线)。

    我最终得到了你在这里看到的代码
    http://masteringcoronasdk.com/free-corona-sdk-tutorial/wont-you-be-my-grid-neighbor/

    可能有一些基于数学的巧妙方法可以使解决方案成为一行代码,但在有人发布之前,如果它有助于解决你的问题,请随意使用该代码。

    Jay

该网站不再更新,仅供存档之用。

 

Corona SDK 现在是 Solar2D

https://Solar2D.com/

×