Як я справедливо розподіляю ресурси між фабриками, коли ресурси майже вичерпані?


12

Основний ресурс в моїй грі - це маса , що зберігається як число з плаваючою комою, яке змінюється з часом. Ресурсні вузли збільшують масу, а заводи її виснажують. Наприклад, якщо у мене є ресурсний вузол, що дає 5 мас в секунду, я набиратиму 5 * deltaTмасу кожен крок гри. Маса відображається округлим до найближчого цілого числа, а показники посилення / втрати відображаються на десяті частини.

Як слід обробляти масу, що вражає нуль? Це створює перегонну умову, якщо кілька заводів намагаються будувати відразу: Фабрики, які спочатку стоять у черзі, або які вичерпують менше ресурсів, отримують пріоритет, як тільки приходить якийсь більше ресурс і так будується швидше, ніж інші.

Як я можу впоратися з цим? Чи варто пропустити крок цілком?


Ба, мій коментар не врятував. У мене було краще роз'яснення. В основному у мене є ресурс, до якого кожен крок отримує доступ до кожного об'єкта. Кожен об’єкт додає або віднімає ресурс. Моя проблема полягає в тому, що якщо ресурс потрапляє на 0, я не знаю, що робити. Чи варто робити якусь чергу? Чи слід пропустити крок об’єкта. Що?
Моб

3
Кругової. Проблема вирішена.
Патрік Х'юз

Відповідь Роя нижче в поєднанні з коментарем до нього описує пристойну, просту в обслуговуванні та налаштування систему круглої роботи Поки ваша негайна проблема дизайну вирішується, все добре =)
Патрік Хьюз

Відповіді:


9

Я погоджуюся з Петром: Не існує встановленого способу зробити це. Як ви хочете це зробити - це питання про те, як ви хочете розробити свою гру.

Однак, за цією обставиною, я думаю, що це очевидно, який тип механіки ви намагаєтеся отримати: ви просто хочете, щоб речі вироблялися якомога швидше, в межах наявної вами маси.

Виробництво в межах потужностей

Я збираюся винести листок із книги Верховного Головнокомандувача, оскільки ви працюєте з системою дуже схожою на їхню: Якщо ви виробляєте понад потужність, найменший спосіб впоратися з цим - це сповільнення виробництва на всій основі. Знизити виробничі потужності насправді досить просто.

Механік швидкості виробництва

На кожному кроці оновлення ваші фабрики не просто виробляють задану кількість: вони працюють зі швидкістю виробництва , яка визначає, який прогрес вони досягають на кожному кроці та яку масу вони використовують. Коли ви виробляєте потужність 75%, ваші фабрики роблять 75% максимального прогресу на кожному кроці і використовують 75% масу порівняно зі 100% потужністю.

Для обчислення швидкості виробництва, перш ніж взагалі щось будувати, слід запитати ваші заводи, щоб визначити загальні ресурси, які використовували б цей крок на повну потужність. Тоді ви виконуєте простий розрахунок:

production speed = (total mass capacity / mass required this step)
if (production speed > 1.0) production speed = 1.0

Скажімо, для виготовлення на повній потужності для цього кроку вам потрібно 125 мас, але на цьому кроці є лише 100 мас. Це рівняння забезпечує швидкість виробництва 0,8 (десяткове представлення 80%). Коли ви говорите своїм фабрикам фактично виконувати їх будівництво , ви передаєте їм це значення, щоб сказати їм, на якій швидкості вони будують: і тепер ваше виробництво сповільнюється в усьому світі.

Альтернативи

Ви також можете почати тимчасово вимикати заводи, поки виробничі потужності не звільняться, і це може бути дуже цікаво побачити, що відбувається на заводах, що знаходяться далі від генераторів, коли вони мають надзвичайно низьку потужність.

Кілька ресурсів?

Ви вирішуєте, як ви справляєтесь з цим; варіантів дуже багато. Найпростіший - це, мабуть, обчислити виробничу потужність для кожного ресурсу, а потім вибрати найнижчий , щоб ваш найслабший ресурс став вузьким місцем для всіх інших.


Я думаю, вам навіть не потрібно казати фабриці виробляти з 80% швидкістю, тому що все, що створює ваш завод, використовує фіксовану кількість маси. Наприклад: ви будуєте резервуар, який займає 100 мас для побудови, зазвичай фабрика може використовувати 2 маси на кожен цикл. Це означає, що для заповнення бака потрібно 50 циклів, і кожен цикл ви додаєте 2 до поточної маси резервуарів. Тепер у вас є лише 1 маса, це означає, що цей цикл, витрачена в даний час резервуарна маса збільшується на 1 замість 2. Після кожного циклу просто перевіряйте поточну масу та загальну масу, необхідну для того, щоб побачити, чи є резервуар повністю нарощений чи ні.
Томас

Якщо у вас в наявності 0 мас, просто не додайте жодної маси в бак. Час, необхідний для створення щось таким чином, може змінюватись залежно від ваших масових доходів. якщо у вас є 2 фабрики, які можуть використовувати 2 маси / цикл і лише 3 доходи, бак 1 будується за 50 циклів, танк 2 - у 100. Інший спосіб - розділити загальну кількість маси, наявну на всі заводи, які її використовують (є активно будуючи щось). Загальна кількість маси, яку може використовувати фабрика, може бути покращена шляхом додавання рівнів до фабрики. Наприклад, на рівні 1 вони можуть витратити 2 маси, на рівні 2: 3 маси і т. Д.
Томас

@Thomas Додавання маси в продукт під час виготовлення здається надто складним способом порівняно з просто заповненням відсотка продукту. Тим більше, що ваш завод повинен знати все про вашу ресурсну систему, а не про просту властивість "швидкість виробництва". Якщо результат для гравця однаковий, тримайте реалізацію якомога простіше. Це також полегшує внесення змін у майбутньому, наприклад, коли ви додаєте / видаляєте ресурси.
Хакворт

@Hackworth Я схильний не погоджуватися, фабриці не потрібно знати про систему ресурсів. Фабрика знає лише, що вона будує і наскільки вона далека. Ресурсна система просто повідомляє фабричному додати суму X до збірки. Таким чином, вам не потрібно обчислювати відсоток доходу від ресурсів, який має цей завод, і вам не потрібно переводити ресурсний дохід на додатковий відсоток добудови.
Томас

6

Хоча мені подобається відповідь Джонатана Гоббса, я думаю, що система черг ще простіша:

Queue<Factory> queue = ...;
int numFactories = ...;

Update()
{
    int resources = GetAllResourcesForThisStep();
    for(int i = 0; i < numFactories; i++)
    {
        if(queue.Peak().RequiredResources <= resources)
        {
            Factory f = queue.Pop();
            resources -= f.RequiredResources;
            queue.Push(f);
        }
        else
        {
            break;
        }
    }
}

Це, ймовірно, буде працювати в середньому так само, як і реалізація Джонатана. Однак рішення Джонатана може створити проблеми, якщо робоча швидкість встановлена ​​дуже низькою, і моя реалізація могла б мати завод з дуже високим запитом на ресурси для цього кадру, якби він блокував інші заводи на кілька кадрів.


+1 Я розробляю гру з подвійними ресурсами, як і в питанні, і коли я вирішу вирішити проблему блокування постачання, я планую використовувати щось подібне до цього. Не такий точний код, а ідея, що стоїть за ним. Споживачі, які можуть використовувати ресурси за один галочок, отримають нижчий пріоритет під час наступного галочки. Я також планую додати прапор, щоб вказати, чи є цей споживач пріоритетним, і дати контроль над цим прапором користувачеві.
Джон Макдональд

Остерігайтеся голоду, якщо даєте їм окремі пріоритети. :)
Рой Т.

Хоча голодування з окремими пріоритетами було б метою. Коли-небудь грав Settlers 4 або Knights & Merchants? Якщо ви надбудовуєте будинки, обмежені ресурси спрямовуються на випадкові будівлі, і це потрібно назавжди закінчити. Але вони також дозволяють вибрати, важлива чи ні будівля, і в цьому випадку ресурси спочатку підуть до цих важливих будівель. Ключ - ніколи не будувати надмірно конструювати, або, якщо ви цього робите, надбудувати якомога менше.
Джон Макдональд

5

Я розвиваю подібну систему постачання у власній грі, тому я також думав над тим, як вирішити проблему блокування поставок та фаворитизувати. Для ілюстрації проблеми я створимо простий приклад:

Якщо у вас є список: [виробник1, споживач1, споживач2, споживач3], і ви оновлюєте порядок, починаючи з постачання = 0, ви отримаєте це:

producer1 produces 5 mass. You now have 5 mass
consumer1 wants 3 mass. Success, you now have 2 mass
consumer2 wants 3 mass. Fail
consumer3 wants 3 mass. Fail
[next tick]
producer1 produces 5 mass. You now have 7 mass
consumer1 wants 3 mass. Success, you now have 4 mass
consumer2 wants 3 mass. Success, you now have 1 mass
consumer3 wants 3 mass. Fail
etc...

споживач1 отримує все задоволення, тоді як споживачі 2 і 3 голодують, поки споживач 1 не задовольниться. Залежно від вашої гри, це може бути небажаним. Я знаю в своїй грі, це не так. Коли я обійдусь цим, я збираюся створити чергу, де споживачі, яких годували однією галочкою, перейдуть на задню частину черги за наступним галочкою, і я вважаю, що це потрапляє Рой Т. Приклад вище виглядатиме так:

producer1 produces 5 mass. You now have 5 mass
consumer1 wants 3 mass. Success, you now have 2 mass. <-- Move to end of queue
consumer2 wants 3 mass. Fail
consumer3 wants 3 mass. Fail
[next tick]
producer1 produces 5 mass. You now have 7 mass
consumer2 wants 3 mass. Success, you now have 4 mass  <-- Note the order change
consumer3 wants 3 mass. Success, you now have 1 mass
consumer1 wants 3 mass. Fail
etc...

Таким чином, кожен отримає свою справедливу частку ресурсів.

Я також планую реалізувати додаткову чергу, яка буде використовуватися в якості черги з пріоритетом, щоб користувач міг вибрати певні структури для пріоритету ресурсу. Черга з пріоритетом завжди подаватиметься перед стандартною чергою. Переконайтесь, що спочатку оновлено всіх виробників, потім споживайте всі ресурси по-друге, інакше чергу вийде з ладу, коли ви виробляєте ресурси частково через галочку, а деякі споживачі вже голодують.

Отже, підкажіть: оновіть виробників, потім чергу пріоритетів, переміщуючи годуваних споживачів до кінця черги пріоритету, потім оновіть стандартну чергу, переміщуючи годуваних споживачів до кінця стандартної черги.


Якщо взяти до межі, це може означати, що жоден споживач не закінчує, поки кожен споживач не може закінчити. У реалістичному сценарії виробничого ланцюга це малоймовірно, і це може бути досить катастрофічно, якби хтось захотів створити чергу для масивної армії. Він буде практично без військ протягом усього часу, коли армія створюється.
Карден

Ця відповідь була моєю початковою думкою, коли я читав питання. Крім того, слід зазначити, що споживана маса на галочку не обов'язково є масою для створення повної одиниці, а, скоріше, одиниця витрат протягом необхідного часу, тому я не впевнений, що побоювання @ Cardin є дійсними, якщо тільки ваша одиниця вартість за тик дуже близька до вашої загальної швидкості збору. Я просто мав би чергу пріоритетів, яку явно управляє гравець, щоб він міг вирішити, хто голодує.
брич

@Cardin, ви цілком правильні, але це також може бути використане як ігровий механік. Settlers 4, Knights & Merchants, Total Annihilation, Supreme Commander - це ігри, які я знаю, що зробили це. Хитрість полягає в тому, щоб не дійти до цього блокування живлення, і якщо ви це зробите, переконайтесь, що ви вийдете з блокування живлення якнайшвидше. Додавання черги із пріоритетом дає змогу людям легше вийти.
Джон Макдональд

3

Що ж, я розкрию ідею Джона, оскільки ми це трохи обговорили у чаті .

редагувати: Це рішення насправді бажано лише в тому випадку, якщо витратна кількість відповідає тому, як часто фабрика повинна отримувати партію ресурсів. Якщо все-таки все одно, тоді ви дійсно можете просто використовувати чергу.

Моє рішення: всі фабрики, перелічені в черзі пріоритету. Пріоритет збільшується, оскільки фабрика страждає від голоду. Голод, пріоритет, встановлений на нулі, коли фабрика споживає ресурси. Першочерговим завданням завжди буде отримання наступної партії ресурсів.

Визначаючи, яка фабрика отримує які ресурси, у якомусь псевдокоді:

iterator i = factoryqueue.start()
bool starvation = false
while(i.next())
  if(i.ready)
    if (!starvation) 
      if (i.consumeAmount < resource.count) starvation = true
      else 
        i.consume(resource)
        i.priority = 0
    if (starvation)
      i.priority += 1

Таким чином ваші фабрики будуть виготовляти по 1 продукт по черзі, якщо ви хочете скоригуватися, враховуючи споживчу суму, щоб дешевші продукти робили частіше, ви можете збільшити пріоритет, наприклад, на 1 / споживати.


Мені хотілося б підтримати це, але я не впевнений, що це має бути зроблено - він відслідковує голодування, але в іншому випадку (імовірно) просто обертається по черзі рівно як нормально, і голодування, і пріоритет ніколи не закінчуються робити що завгодно.
doppelgreener

різниця стає очевидною, якщо ви збільшуєте пріоритет на + = 1 / кількістьThisFactoryConsumes, тоді ті, яким потрібно більше ресурсів для створення продукту, трохи відстають, дозволяючи менш дорогим витрачати пропорційно більше партій ресурсів. Це навіть виправдало б співвідношення ресурсів на завод. Однак це все ще не є дурним доказом, оскільки число голоду встановлюється на магічне число 0 щоразу, коли ресурси споживаються фабрикою, тому його не буде, щоб чотиризначення було рівномірно розподілено, коли оновлення ресурсів коливається.
Тоні

Насправді я зараз не такий впевнений, чи насправді це не гарантується. Мені потрібно намалювати кілька графіків і перевірити це, щоб бути впевненим.
Тоні

о, і пріоритет - це якість самої черги пріоритетів. Я не збираюся заважати пояснювати, як його побудувати. Сама черговість пріоритетів завжди сортується відповідно до значення пріоритету її членів.
Тоні

+1 Розуміючи, що це черговість з пріоритетом, її робота тепер виглядає просто: просійте по черзі і виберіть найшвидший предмет, який може споживати ресурси. Якщо потужність сильно розділена (у вас є 1000 ресурсів цього галочки, але це 100 сто-ресурсних нарощувань), це не повинно бути проблемою, і все набирається досить добре. Навіть якщо щось значно вище ваших ресурсів цього галочки, це може врешті-решт заощадити достатньо, щоб трохи досягти прогресу - що може вплинути на уповільнення його роботи або виключення великих речей на користь менших речей, що є хорошою справою. Мені це подобається МНОГО. :)
doppelgreener

2

Дивне питання.

Моя проблема полягає в тому, що якщо ресурс потрапляє на 0, я не знаю, що робити. Чи варто робити якусь чергу? Чи слід пропустити крок об’єкта. Що?

Що вам потрібно зробити, залежить від ігрової логіки, яку ви створюєте. Можна зробити чергу, можна пропустити. Залежить від того, як ви вважаєте, як повинна поводитися ваша гра. Виправте мене, якщо я помиляюся у вашому питанні.


1

Ви можете зберегти кількість загального попиту на ресурс на один галочку для всіх конструкцій. Якщо одне сховище ресурсів потрапить менше, ніж потрібно, то все будівництво припиниться повністю, поки сховище не збереться достатньо, щоб підтримати хоча б 1 галочку виробництва. Тоді виробництво може відновитись.

Тож замість того, щоб зберігати темпи виробництва як плавучість, він є двійковим - або ваша фабрика виробляє на повній швидкості, або її немає.

За словами, цей підхід по суті такий же, як і відповідь Джонатана, для спеціальних випадків швидкості виробництва 0,0 та 1,0 - довільний поплавок f з 0,0 <= f <= 1,0, ймовірно, більш елегантний, оскільки ви не отримуєте ривкових переміщень у кількості зберігання , але логіка повинна бути трохи простішою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.