2014-02-18 2 views
5

В настоящее время я работаю над игрой с использованием Roblox (который использует Lua). Это в основном состоит из нескольких мини-игр. В начале каждого раунда все игроки в игре помещаются в стол и телепортируются в область. Именно здесь играет игра coroutine. Когда раунд продолжается, я хочу запустить сопрограмму. Каждую секунду, когда coroutine проверяет, находится ли здоровье игрока ниже нуля и удаляет их из таблицы currentPlayer, если это так.Как закончить цикл обработки в Lua?

Извините, если я неправильно описываю проблему, но сопрограмма не выйдет. Раньше я раньше не использовал сопрограммы, поэтому я, вероятно, пытаюсь уступить это неправильному пути. Я знаю, что большинство из вас не будут знакомы с Roblox, но синтаксис Lua одинаковый.

Может кто-нибудь, пожалуйста, дайте мне пример того, как я закончил бы петлю coroutine?

currentPlayers = {} 
roundTime = 60 

local lookForWinners = coroutine.create(function() 
    while coroutine.running do 
    wait(1) 
    for i, v in pairs(currentPlayers) do 
     if v.Character.Humanoid.Health <= 0 then 
     table.remove(currentPlayers, v) 
     end 
    end 
    end 
end) 


while wait() do 
    repeat display("Two or more players need to be in the game.", 1) until #_G.plrs > 1 --Ignore, just checks if two+ players are in game. 
    display("Picking a map...", 3) pickMap() 
    teleport(0, 500, 0) 
    coroutine.resume(lookForWinners) 
    wait(roundTime) 
    print("Round over") 
    coroutine.yield(lookForWinners) 
end 
+0

Благодарим за исправление кода, что плохо для того, чтобы не отправлять его правильно. – user3314993

ответ

4

Lua - это однопоточный язык. Coroutines не приводит к параллельной работе функций.

Coroutines - это просто способ сделать функцию, которая может приостановить собственное выполнение (используя coroutine.yield), который может быть возобновлен снаружи (с использованием coroutine.resume). There is no "coroutine.running": есть только одна строка «работает» в любой момент времени.

Если Roblox были предназначены для того, чтобы использовать wait() выскочить из нити Lua, можно было бы написать это как ряд петель, которые проверяют их состояние, а затем вызвать wait():

local currentPlayers={} 
local roundTime = 60 

while #_G.plrs > 1 do 
    display("Two or more players need to be in the game.", 1) 
    wait() 
end 
display("Picking a map...", 3) pickMap() 
teleport(0, 500, 0) 

for i=0, roundTime do 
    for i, v in pairs(currentPlayers) do 
    if v.Character.Humanoid.Health <= 0 then 
     table.remove(currentPlayers, v) 
    end 
    end 
    wait(1) 
end 
print("Round over") 

Однако это это плохой код. (Всякий раз, когда вы пишете код, пусть циклы с функцией «wait» в них служат для указания того, что что-то выполняется неправильно.) Для обработки логики вашей игры вы должны использовать Events от Roblox.

  • Проверьте, должна ли игра начинаться только при изменении количества игроков.
  • «Ищите победителей» только при изменении здоровья Гуманоида (событие HealthChanged).
  • Запустите таймер на каком-то таймере или интервале (не забывайте, что вы, вероятно, захотите закончить игру раньше, чем кто-либо выиграл).

События имеют много, много преимущества над занятой петлей; наиболее заметным будет то, что ваши проверки происходят , когда вещь, которую они проверяют, происходит, а не позже.

+0

Подробнее о сопрограммах см. По адресу http://www.lua.org/pil/9.1.html. –

3

Я предлагаю вам следовать советам Стюарта, чтобы использовать события; это в основном для предоставления дополнительной информации о том, какие сопрограммы помогут вам правильно их использовать.

Придумайте сопрограммы как функции, которые могут возвращать значения, но с изюминкой: в то время как «нормальная» функция завершается, когда он выполняет return, когда вы yield из сопрограммы, она сохраняет свое состояние, так что resume может затем продолжить с точка, где вы уступили, как будто ничего не произошло. Обратите внимание, что вы только от сопроводителя и только до той точки, где была выполнена resume этой сопрограммы (это ничем не отличается от вызова функции и возврата из нее, управление возвращается к точке, где вы вызывали функцию).

В дополнение к этому, вызовы resume и yield позволяют передавать значения в сопрограммы coroutine и возвращать (промежуточные) значения из сопрограммы. См. Это SO answer для примера того, как это можно использовать.

Из coroutine все еще может быть return, и он ничем не отличается от возврата из функции, которая завершает ее выполнение. Если вы проверяете статус сопрограммы в то время (coroutine.status), он должен быть «мертвым».

Таким образом, чтобы ответить на ваш вопрос, как вы можете закончить циклическую сопрограмму: вы можете return от него, вы можете yield() от него (и никогда не resume его снова), или вы можете вызвать error(), которые вы можете поймать и проверить в результате вызова resume. Сказав это, я согласен с Стюартом в том, что это может быть неправильный способ решить вашу проблему.

Смежные вопросы