Chain2D.Map
맵 하나에 대한 손잡이. `Chain2D.Maps` 의 함수들이 돌려주는 것이 이것이고, 맵을 말하지 않는 게임에도 맵은 하나 있습니다 — 그것이 `Chain2D.Map` 이고, 사람은 연결되는 순간 여기 놓입니다. 이름을 닫아 쥔 함수들이지 self 를 받는 메서드가 아니므로 점으로 부릅니다. 여기만 콜론이면 `Map.setMap(w, h, ...)` 이 w 를 맵으로 읽는 조용한 오류가 되고, 그것은 맵이 여럿이 되기 전에 쓰인 모든 게임이 쓰는 바로 그 문장입니다. 몸은 `{ slot, generation, map }` 세 숫자로 된 언 표이고, 아래에서 `Body` 라고 씁니다. 위치를 쓰는 짝은 없습니다 — 몸은 의도(`setInput`)로 움직이고, 어디까지 갈 수 있는지는 솔버가 정합니다.
Map.name
Chain2D.Map.name: string이 손잡이가 든 맵의 이름. `Maps.move` 의 목적지나 `Maps.stateOf` 에 그대로 넘기는 값입니다. 손잡이가 쥐고 있는 것은 이름뿐입니다 — 맵 자체를 쥐면 언로드된 맵의 손잡이가 채널이 더는 갖고 있지 않은 메모리를 가리키게 되고, 그 사이에도 참인 채로 남는 것은 이름뿐이기 때문입니다.
local map = Chain2D.Maps.of(player)
if map ~= nil and map.name == "main" then
print("마을에 있습니다")
endMap.Tile
Chain2D.Map.Tile: { empty: number, solid: number, oneWay: number, climbable: number, swimmable: number, slopeUpRight: number, slopeUpLeft: number }타일에 붙는 성질. 손잡이마다 같은 표이므로 `Chain2D.Map.Tile` 과 `map.Tile` 은 같은 것입니다. `Map.setMap` 에 넘기는 판정 플래그가 이 값들이고, 하나하나가 무엇인지는 `Chain2D.Map.Tile` 페이지에 있습니다.
local Tile = Chain2D.Map.Tile
print(Tile.solid, Tile.oneWay)Map.setMap
Chain2D.Map.setMap(width: number, height: number, tileSize: number, tiles: {number})| width | number | 가로 칸 수. 1 이상 4096 이하이고, `width * height` 는 1048576 을 넘을 수 없습니다. 벗어나면 "World map size is out of range" 오류입니다 — 백만 칸을 넘겨 달라는 요청은 들어주기보다 거부할 만한 실수이고, 그 할당은 채널을, 그리고 그 채널에 있는 사람 전부를 함께 내립니다. |
| height | number | 세로 칸 수. 같은 한계를 받습니다. |
| tileSize | number | 한 칸이 몇 픽셀인지. 0 보다 큰 유한한 수여야 하고, 아니면 "World tile size must be a positive number" 오류입니다. |
| tiles | {number} | 칸마다 판정 플래그 하나. 행 우선이고 아래 줄이 먼저입니다 — `tiles[y * width + x + 1]` 이고 y 는 바닥에서 위로 셉니다. 솔버가 쓰는 순서와 같아서 옮겨 담는 계산 없이 그대로 읽힙니다. 수가 아닌 칸은 0(빈 칸)으로 읽습니다. |
맵을 스크립트가 직접 칠합니다. 타일셋이 없는 맵이 되고, 그런 맵에서는 `Map.setTile` 의 세 번째 값이 그림이 아니라 판정 플래그입니다. 문서로 칠하는 `Map.loadTiles` 가 있는 자리입니다. 좌표를 도는 루프를 스크립트에 두면 그 스크립트 말고는 아무것도 맵을 읽을 수 없습니다 — 에디터가 열 것도, diff 가 보여 줄 것도 없습니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local Tile = Chain2D.Map.Tile
local tiles = {}
for index = 1, 16 * 12 do
tiles[index] = if index <= 32 then Tile.solid else Tile.empty
end
Chain2D.Map.setMap(16, 12, 16, tiles)Map.loadTiles
Chain2D.Map.loadTiles(document: string) -> {
width: number, height: number, tileSize: number,
points: {{ name: string, x: number, y: number }},
areas: {{ name: string, x1: number, y1: number, x2: number, y2: number }},
tiles: {[string]: number},
tile: (name: string) -> number,
point: (name: string) -> { name: string, x: number, y: number }?,
area: (name: string) -> { name: string, x1: number, y1: number, x2: number, y2: number }?,
}| document | string | 릴리스가 들고 있는 맵 문서의 이름. `shared/maps/<이름>.json` 이고, 폴더에 넣었으면 폴더까지가 이름입니다 — `shared/maps/levels/town.json` 은 "levels/town" 입니다. 문자열이 아니면 오류가 납니다. |
table문서가 말한 크기와, 문서가 이름 붙인 자리와 구역, 그리고 타일셋이 이름 붙인 타일들. `tiles` 는 이름에서 타일 번호로 가는 표이고, `tile` `point` `area` 는 그 안에서 이름으로 찾는 함수입니다 — 이 값들을 쓰는 거의 모든 경우가 이름으로 찾는 것입니다.
릴리스가 들고 있는 맵 문서를 읽어 칠합니다. 문서의 움직이는 발판도 이때 함께 올라갑니다. 판정은 모든 레이어의 합집합이고 그림은 가장 위에 무언가를 놓은 레이어의 것입니다 — 앞에 장식을 깐다고 뒤의 벽이 사라지지 않습니다. 없는 문서를 부르면 그 자리에서 오류가 납니다. 조용히 비어 있으면 바닥 없는 게임이 되고, 그것은 파일이 빠졌다는 사실이 아니라 물리 버그처럼 읽힙니다. 문서가 말하는 타일셋을 이 릴리스가 들고 있지 않을 때도 같은 이유로 거부합니다 — 타일셋을 잃은 맵은 아무것도 단단하지 않은 채로 올라옵니다. 거부하는 말은 이렇습니다: "this Runtime carries no map documents", "no map document is called ...", "map document ...: <읽지 못한 이유>", "map document ... is larger than a map may be", "map document ... is drawn with tileset ..., which this Release does not carry", "tileset ...: <읽지 못한 이유>". 돌아오는 것은 이름과 좌표뿐입니다. 그것이 스폰인지 문인지는 엔진이 모르고, 이름을 읽는 이 게임만 압니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local town = Chain2D.Map.loadTiles("town")
print(town.width, town.height, town.tileSize)
local spawn = town.point("spawn")
local body = Chain2D.Map.spawn({ sprite = "hero" }, spawn.x, spawn.y)loadTiles.tile
loaded.tile(name: string) -> number| name | string | 타일셋이 그 타일에 붙인 이름. 그런 이름이 없으면 오류가 납니다. |
number그 타일의 번호. `Map.setTile` 에 그대로 넘기는 값입니다.
타일셋이 이름 붙인 타일의 번호를 찾습니다. `loaded` 는 `Map.loadTiles` 가 돌려준 표입니다. 이름으로 부르는 이유는 번호가 그림이 시트의 어디에 있는지일 뿐이기 때문입니다. 창작자가 앞에 타일 하나를 끼워 넣으면, 8 이라고 쓴 모든 스크립트를 찾아 그 8 하나하나가 다리를 뜻했는지 정해야 합니다.
local town = Chain2D.Map.loadTiles("town")
Chain2D.Map.setTile(12, 3, town.tile("bridge"))loadTiles.point
loaded.point(name: string) -> { name: string, x: number, y: number }?| name | string | 문서가 그 자리에 붙인 이름. |
{ name: string, x: number, y: number }?그 이름의 자리, 없으면 `nil`.
문서가 이름 붙인 자리를 찾습니다. 사람이 나타나는 곳, 적이 서는 곳, 상자가 있는 곳 — 어느 것인지 엔진은 모르고, 이름과 좌표를 건넬 뿐입니다. 이름은 하나뿐이 아닐 수 있습니다. 적 여섯을 세우는 맵은 "enemy" 를 여섯 번 쓰고, 이 함수는 그중 처음 것을 돌려줍니다. 전부가 필요하면 `loaded.points` 를 직접 돕니다.
local town = Chain2D.Map.loadTiles("town")
for _, post in ipairs(town.points) do
if post.name == "enemy" then Chain2D.Map.spawn(nil, post.x, post.y) end
endloadTiles.area
loaded.area(name: string) -> { name: string, x1: number, y1: number, x2: number, y2: number }?| name | string | 문서가 그 사각형에 붙인 이름. |
{ name: string, x1: number, y1: number, x2: number, y2: number }?그 이름의 구역, 없으면 `nil`. `x1` `y1` 이 낮은 쪽 모서리, `x2` `y2` 가 높은 쪽입니다.
문서가 이름 붙인 사각형을 찾습니다. 문이 이것이 있는 이유입니다 — 문은 타일이 아니라 몸이 설 수 있는 자리이고, 밟을 수 있어야 합니다. 엔진에는 문이 없습니다: 맵은 "여기 사각형이 있고 이름은 to-dungeon 이다" 라고만 말하고, 그 이름을 읽는 스크립트만 그것이 무엇인지 압니다.
local town = Chain2D.Map.loadTiles("town")
local door = town.area("to-dungeon")
assert(door ~= nil, "town 에 to-dungeon 이 없습니다")
print(door.x1, door.y1, door.x2, door.y2)Map.setTile
Chain2D.Map.setTile(x: number, y: number, tile: number)| x | number | 칸 좌표. 맵 밖이면 아무 일도 일어나지 않습니다. |
| y | number | 칸 좌표. 바닥에서 위로 셉니다. |
| tile | number | 0 이상 65535 이하. 벗어나면 "<값> is not a tile" 오류입니다. 타일셋으로 그린 맵이면 타일 번호이고, 그 타일이 무엇을 하는지는 타일셋이 정합니다 — 무엇으로 보일지와 무엇일지를 따로 말하면 둘이 다른 말을 할 수 있고, 플레이어가 어디에 설 수 있는지에 대해 가진 증거는 그림뿐입니다. 스크립트가 칠한 맵이면 예전처럼 판정 플래그이고, 그때 쓰이는 것은 낮은 한 바이트뿐입니다. |
타일 하나를 바꿉니다. 무엇이 되어야 하는지를 말하고, 언제인지는 엔진이 정합니다 — 지금부터 12틱, 0.2초 뒤에 놓이며 그 사이에 모든 클라이언트가 소식을 받습니다. 놀란 적 없는 클라이언트는 보정받을 일도 없습니다. 지금 당장 바꾸면 클라이언트는 이미 그 자리를 지나 예측한 뒤이고, 그것을 고치는 유일한 방법은 세계를 되감는 것입니다. 0.2초를 위해서는 지나친 기계입니다. 스크립트는 그 지연을 보지 않습니다. 지금 바꾸는 것처럼 쓰여 있고, 언젠가 이 엔진이 즉시 할 수 있게 되어도 누구의 게임도 한 줄 바뀌지 않습니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local town = Chain2D.Map.loadTiles("town")
for x = 12, 18 do
Chain2D.Map.setTile(x, 3, town.tile("bridge"))
endMap.setMoverRate
Chain2D.Map.setMoverRate(mover: number, rate: number)| mover | number | 맵 문서의 movers 배열에서 몇 번째인지. 0 부터 셉니다. 범위 밖이면 아무 일도 일어나지 않습니다. |
| rate | number | 유한한 수. 1 은 돌고, 0 은 멈추고, -1 은 거꾸로 갑니다. 무한이나 NaN 이면 "a mover rate must be a finite number" 오류입니다. |
무버의 시계가 얼마나 빨리 도는지 바꿉니다. 멈추는 순간 발판이 옮겨지지 않도록 위상은 엔진이 맞춥니다 — 리프트를 세우면서 동시에 다른 자리로 옮기는 스위치는 아무도 겨눌 수 없는 스위치입니다. 타일 바꾸기와 같이 0.2초 뒤에 놓이고, 이유도 같습니다. 모든 클라이언트가 그 틱을 굴리기 전에 듣기 때문에 되돌릴 것이 생기지 않습니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
Chain2D.Map.setMoverRate(0, 0) -- 0번 발판을 멈춥니다
Chain2D.Map.setMoverRate(0, -1) -- 거꾸로 돌립니다Map.setViewDistance
Chain2D.Map.setViewDistance(distance: number)| distance | number | 0 이거나 양수인 유한한 수. 음수이거나 무한이면 "a view distance must be zero or a positive number" 오류입니다. 0 이 기본이고, 전부를 뜻합니다. |
한 사람에게 얼마나 먼 곳까지 알려줄지 정합니다. 맵 안의 모든 몸을 모든 사람에게 보내면 그 값은 사람 수의 제곱으로 자랍니다 — 게임이 잘될수록 비싸지는 방향입니다. 화면에 다 들어오는 맵에는 0 이 맞고, 모든 맵이 그렇습니다, 그렇지 않게 되기 전까지는.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
Chain2D.Map.setViewDistance(900)Map.spawn
Chain2D.Map.spawn(params: table?, x: number, y: number) -> Body| params | table? | 몸에 붙는 값들. 표에 없는 이름은 기본값 그대로이고, 여기 없는 이름은 읽지 않습니다. sprite: 무엇으로 그려지는지 (client/sprites/<이름>.json). 이름으로 주는 이유는 숫자가 와이어에만 있기 때문입니다 — 숫자를 쓰는 창작자는 자기가 스폰한 순서를 적게 됩니다. mode: "grid" 이면 칸 단위로, 그 밖에는 자유롭게 움직입니다. halfWidth (7) halfHeight (15): 몸 상자의 반. gravity (-980): 0 이면 탑다운이고, 따로 만든 솔버가 아니라 이 값 하나입니다. maxSpeed (200) acceleration (1600) deceleration (2000). jumpHeight (64): 초기 속도가 아니라 도달하는 높이(픽셀)입니다 — 창작자는 "세 칸 높이" 로 생각하지 "초당 620픽셀" 로 생각하지 않습니다. maxJumps (1). coyoteTime (0.1): 발판에서 걸어 나간 뒤에도 이만큼은 점프할 수 있습니다. inputBuffer (0.12): 착지 직전에 누른 점프는 착지하면서 나갑니다. maxSlopeAngle (45): 이보다 가파른 경사는 바닥이 아니라 벽입니다. 타일 경사는 45도이므로 45 미만이면 모든 경사가 벽이 되는데, 각진 지형을 원하는 게임에게는 정당한 선택입니다. snapLength (6): 내려가는 경사에 붙어 있으려고 아래로 뻗는 거리. 없으면 내리막이 잔걸음의 연속처럼 보입니다. wallSlide (false) wallJump (false) dash (false) dashSpeed (420) dashDuration (0.14) dashCooldown (0.4) airDashes (1). gridSize (16): 칸 단위로 움직일 때 한 걸음. moduleStateSlots moduleInputSlots (0): 이 몸이 움직임 모듈에서 쓰는 슬롯 수로, 각각 16 개와 4 개까지 잘립니다 — 있지도 않은 슬롯을 주장하는 몸은 자기 상태 밖을 읽게 됩니다. 0 이면 이 몸에게는 모듈이 아예 불리지 않습니다. 수여야 하는 자리에 무한이나 NaN 을 넣으면 "World field ... must be a finite number" 오류가 납니다. |
| x | number | 설 자리. 유한한 수여야 합니다. |
| y | number | 설 자리. 유한한 수여야 합니다. |
Body`{ slot, generation, map }` 세 숫자로 된 언 표. map 이 함께 들어 있으므로 다른 맵의 손잡이에 넘기면 남의 몸이 아니라 없는 몸으로 답합니다 — 읽는 쪽(`Map.stateOf` `Map.moduleStateOf`)은 `nil`, 쓰는 쪽(`Map.despawn` `Map.setOwner` `Map.setInput`)은 `false` 입니다. 맵 번호가 없으면 마을의 첫 몸과 지하의 첫 몸이 둘 다 slot 0 generation 1 이고, 잘못 넘긴 손잡이에 대한 읽기와 쓰기가 조용히 남의 캐릭터에 닿습니다.
몸 하나를 세웁니다. 주인이 없는 몸은 서버가 몹니다 — 주인을 붙이려면 `Map.setOwner` 입니다. 한 맵은 몸을 4096 개까지 쥡니다. 솔버는 몸 하나당 싸지만 한없이 스폰하는 스크립트는 결국 틱 예산을 찾아내고, 정해진 숫자에서 거부하면 그 실패가 만든 사람이 볼 수 있는 자리에서 일어납니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local body = Chain2D.Map.spawn({
sprite = "hero",
halfWidth = 7, halfHeight = 15,
maxSpeed = 200, jumpHeight = 64, dash = true,
}, 100, 150)Map.despawn
Chain2D.Map.despawn(body: Body) -> boolean| body | Body | `Map.spawn` 이나 `Map.bodyOf` 가 준 값. 표가 아니면 "World body id must be a table" 오류입니다. |
boolean내렸으면 `true`. 이 맵에 그런 몸이 없으면 `false`.
몸을 내립니다. 슬롯은 다시 쓰이지만 세대가 함께 올라가므로, 내려간 몸의 손잡이는 그 자리에 들어선 다음 몸을 조용히 가리키지 않고 없다고 답합니다. 사라졌다는 답은 부른 쪽이 실제로 다룰 수 있는 답입니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local body = map.bodyOf(player)
if body ~= nil then
map.despawn(body)
endMap.setOwner
Chain2D.Map.setOwner(body: Body, player: Player) -> boolean| body | Body | `Map.spawn` 이 준 값. |
| player | Player | 접속해 있는 Player. 표가 아니거나 `id` 가 문자열이 아니면 오류가 납니다. |
boolean붙었으면 `true`. 이 맵에 그런 몸이 없으면 `false`.
몸을 플레이어에게 넘깁니다. 그 뒤로 그 플레이어의 입력 패킷은 엔진이 직접 이 몸에 적용합니다 — 스크립트가 패킷을 만지지 않습니다. 한 사람에 몸 하나입니다. 두 번째 호출은 주인을 옮기지 더하지 않습니다: 남은 옛 연결이 한 사람에게 두 캐릭터를 몰게 해서는 안 되기 때문입니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
Chain2D.Players.playerAdded(function(player)
local body = Chain2D.Map.spawn(params, 100, 150)
Chain2D.Map.setOwner(body, player)
end)Map.setInput
Chain2D.Map.setInput(body: Body, input: table?) -> boolean| body | Body | `Map.spawn` 이 준 값. |
| input | table? | 이번 명령. moveX moveY 는 -1 에서 1 사이로 잘립니다. jumpPressed 는 버튼이 내려간 그 틱에만, jumpHeld 는 눌려 있는 동안 참입니다. dropThrough 는 one-way 발판에서 일부러 내려가는 것, dashPressed 는 대시 버튼이 내려간 그 틱입니다. module 은 움직임 모듈이 선언한 이름마다 수 하나이고, 같은 범위로 잘립니다. `nil` 이면 빈 입력입니다. |
boolean들어갔으면 `true`. 이 맵에 그런 몸이 없으면 `false`.
서버가 직접 모는 몸(적, 이동하는 것들)에 씁니다. 플레이어가 모는 몸은 순서가 붙은 입력 패킷으로 들어오므로 이것을 쓰지 않습니다. 축이 -1 에서 1 로 잘리는 이유는 이것이 클라이언트가 영향을 줄 수 있는 유일한 구조이기 때문입니다. moveX 가 1000 인 명령은 스피드핵입니다. 모듈 입력도 같은 이유로 같은 범위입니다 — 모듈의 입력도 입력입니다. 주는 것은 의도이지 위치가 아닙니다. 어디까지 갈 수 있는지는 서버의 솔버가 정합니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local state = Chain2D.Map.stateOf(patrol)
if state ~= nil then
local direction = if state.x > 600 then -1 else 1
Chain2D.Map.setInput(patrol, { moveX = direction })
endMap.stateOf
Chain2D.Map.stateOf(body: Body) -> {
x: number, y: number,
velocityX: number, velocityY: number,
grounded: boolean, climbing: boolean, swimming: boolean,
motionState: string,
}?| body | Body | `Map.spawn` 이나 `Map.bodyOf` 가 준 값. |
table?위치와 속도, 땅에 붙었는지 사다리를 잡았는지 물에 있는지, 그리고 motionState 는 "idle" "run" "jump" "fall" "climb" "dash" "wallSlide" "swim" 중 하나입니다. 언 표입니다. 이 맵에 그런 몸이 없으면 `nil`.
몸이 지금 어디에 어떻게 있는지 묻습니다. 내려간 몸도, 다른 맵의 몸도 `nil` 입니다 — 손잡이에 맵 번호가 박혀 있어서, 마을의 몸을 지하에 물어도 지하의 첫 몸이 나오지 않습니다. motionState 는 애니메이션을 위해 복제되기도 하는 값입니다. 보간된 위치에서 짐작하는 대신 실제 상태를 따라가야 착지가 미끄러짐처럼 보이지 않습니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local state = Chain2D.Map.stateOf(body)
if state ~= nil and state.grounded then
print(state.x, state.y, state.motionState)
endMap.moduleStateOf
Chain2D.Map.moduleStateOf(body: Body) -> {[string]: number}?| body | Body | `Map.spawn` 이나 `Map.bodyOf` 가 준 값. |
{[string]: number}?모듈이 선언한 이름마다 수 하나. 이 맵에 그 몸이 없거나 이 게임에 움직임 모듈이 없으면 `nil`.
움직임 모듈이 이 몸에 대해 들고 있는 값을 이름으로 읽습니다. `shared/motion.luau` 를 두면 서버와 모든 클라이언트가 같은 파일을 돌고, 슬롯의 이름은 그 파일이 선언한 것입니다. 이 몸이 params 에서 선언한 슬롯 수까지만 옵니다. 선언하지 않은 몸에게는 모듈이 아예 불리지 않으므로 여기에도 아무것도 없습니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local module = Chain2D.Map.moduleStateOf(body)
if module ~= nil then
-- 이름은 shared/motion.luau 가 선언한 것입니다.
print(module.ropeLength)
endMap.bodyOf
Chain2D.Map.bodyOf(player: Player) -> Body?| player | Player | 접속해 있는 Player. 표가 아니거나 `id` 가 문자열이 아니면 오류가 납니다. |
Body?이 맵이 이 사람을 위해 쥐고 있는 몸. 없으면 `nil`.
이 맵이 이 사람을 위해 쥐고 있는 몸을 묻습니다. 스크립트가 표를 따로 들고 있으면 스폰과 디스폰과 맵 이동을 전부 따라다녀야 하고, 이동 뒤에 그 표가 가리키는 것은 이 사람이 떠난 맵의 몸입니다. 맵이 이미 알고 있으므로 맵에게 묻습니다. 다른 맵에 있는 사람은 이 맵에서 `nil` 입니다. 어느 맵인지부터 물으려면 `Maps.of` 입니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
local map = Chain2D.Maps.of(player)
local body = if map ~= nil then map.bodyOf(player) else nil
if body ~= nil then
print(map.stateOf(body).x)
endMap.bodyCount
Chain2D.Map.bodyCount() -> numbernumber이 맵에 살아 있는 몸의 수.
이 맵의 몸을 셉니다. 주인이 있는 것과 서버가 모는 것을 함께 셉니다. 최대는 4096 이고, 그 위에서 `Map.spawn` 은 거부합니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
print("이 맵의 몸: " .. Chain2D.Map.bodyCount())Map.playerCount
Chain2D.Map.playerCount() -> numbernumber이 맵에 있는 사람의 수.
이 맵의 사람을 셉니다. 정원이 보는 값이고, 맵을 재우고 내리는 일이 보는 값도 이것입니다. 사람이 어느 맵에 있는지도, 그 맵의 정원도 맵이 아니라 채널이 들고 있습니다. 맵을 내려도 그 둘은 남으므로, 이것과 `Map.setCapacity` 만은 내려간 맵의 손잡이로도 부를 수 있습니다.
for _, map in ipairs(Chain2D.Maps.list()) do
print(map.name, map.playerCount())
endMap.setCapacity
Chain2D.Map.setCapacity(capacity: number)| capacity | number | 받을 수 있는 사람 수. 0 이면 제한 없음이고 그것이 기본값입니다. 음수는 "a map capacity cannot be negative" 오류입니다. |
이 맵이 받을 수 있는 사람 수를 정합니다. 넘으면 이동이 줄 세워지는 대신 거부됩니다 — 열릴지 모르는 문 앞에서 기다리는 것보다 지금 안 된다고 듣는 편이 낫습니다. 같은 맵 안에서 자리만 옮기는 이동은 정원을 보지 않습니다. 이 이름의 맵을 아직 한 번도 만든 적이 없으면 아무 일도 일어나지 않습니다.
local dungeon = Chain2D.Maps.load("dungeon")
dungeon.setCapacity(8)Map.tick
Chain2D.Map.tick() -> numbernumber이 맵이 지금까지 돈 고정 틱의 수.
이 맵이 몇 번 판정했는지 묻습니다. 맵마다 따로 셉니다 — 한 채널의 맵들은 같은 시계를 나눠 쓰지만 잠든 맵은 돌지 않으므로, 이 숫자는 이 맵이 실제로 굴린 횟수입니다. 스텝은 절대 변하지 않습니다. 델타가 변하면 같은 입력이 다른 결과를 내고, 그러면 보정 뒤에 자기 입력을 다시 굴리는 클라이언트는 서버가 얻은 답에 영영 도착하지 못합니다.
언제내려간 맵의 손잡이로는 부를 수 없습니다 — `Maps.stateOf` 가 "unloaded" 인 동안 "no map named ... is loaded" 오류가 납니다.
print("simulation tick " .. Chain2D.Map.tick())