Дано:
  1. Существует карта с игровой зоной (А).
  2. Внутри существует красная область спавна юнитов (В), которые периодически (в определенные моменты) массово спавнятся триггерами в рандомной позиции этой области (затем они идут в географический центр карты).
  3. Существует голубая (С) внутри красной области (В).
Задача: организовать по команде спавн юнитов в красной области (В), ИСКЛЮЧАЯ голубую зону (С). Благодарю откликнувшихся и надеюсь на подсказки.

СерафимКречет, ух, ну тогда держи простую, тупую гуишную систему, где втупую рандомим точку. Если находится внутри среднего региона - рандомим еще раз.
Инициализация координат регионов
Рандомизация точки и спавн юнита в этой точке
Результат
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...
32
Епттить проверять координаты чтобы они были больше макс х коррдинаты области C или меньше минимальной координаты x, аналогично для координаты y.
В целом, можно наделать много точек спавна и занести их в массив, и выбирать случайную.
22
Один подход, можно поделить красную зону на 4 или 8 зон (вне синей) и сперва рандомить одну из них.
Второй подход: сперва рандомим координату ширины, если она вне пределов ширины голубой зоны, то просто рандомим высоту. А если внутри, то тогда выбираем выше или ниже (рандомом), затем рандомим высоту выше или ниже голубой зоны, между ее пределом и соответствующим пределом красной.
7
Если площадь области спавна слишком мала, по отношению к забанненым областям, может оборваться поток. Но при штатом пользовании должно работать нормально.
Код

function GetSpawnPoint takes rect spawnRect returns location 
	local real x
	local real y
	local boolean pass
	loop
		set pass = true
		set x = GetRandomReal(GetRectMinX(spawnRect),GetRectMaxX(spawnRect))
		set y = GetRandomReal(GetRectMinY(spawnRect),GetRectMaxY(spawnRect))
		if RectContainsCoords(gg_rct_rectC,x,y) then  		// проверяем лежит ли случайная точка в запрещенной области
			set pass = false					
		endif
		/*
		if RectContainsCoords(gg_rct_rectD,x,y) then  			// можно добавить несколько забаненых областей
			set pass = false							
		endif
		*/
		exitwhen pass
	endloop
	return Location(x,y)				// незабываем удалять локацию после использвания 
endfunction 

..
local location loc = GetSpawnPoint(gg_rct_rectB)
call CreateUnitAtLoc(p,id,loc,GetRandomReal(0.,360))
call RemoveLocation(loc)
set loc = null 
..
Ответы (4)
26
Zeix, зачем так цикл раздувать? сразу пиши в закрывашку
loop
	set x = GetRandomReal(GetRectMinX(spawnRect),GetRectMaxX(spawnRect))
	set y = GetRandomReal(GetRectMinY(spawnRect),GetRectMaxY(spawnRect))
	exitwhen RectContainsCoords(gg_rct_rectC,x,y)
endloop
7
В комментах написано, что бы автор вопроса мог проще добавить другие забаненные зоны. Такой код легче читается и редактируется новичками. Можно еще сократить, и не использовать координаты, а сразу создавать и двигать локацаю, это еще сократит код еще на две строки, но зачем?
26
Zeix, все остальные области я бы просто добавил в exitwhen через and )) ну ладно, я думал про новичков тут уже давно не думают...
30
Zeix, если думаешь про новичков, то лучше откажись от location и пиши координаты в глобалки.
28
ему нужна формула поиска случайной точки в многоугольнике, а не ваши костыли
Ответы (3)
7
rsfghd, в вопросе буквально нет ни слова, ни намека на многоугольники, четко и ясно написано Области(которые являются прямоугольниками). Если в варике понадобилось использовать многоугольники, то что-то в дизайне пошло явно не так.
28
Если в варике понадобилось использовать многоугольники, то что-то в дизайне пошло явно не так.
Это явно было лишним
30
Zeix, не просто прямоугольники, а ориентированные по осям многоугольники.
28
Может я тупой, но единственный вариант к которому я додумался, это разбить многоугольник на треугольники, выбирать среди них случайный и там уже искать рандомную точку, однако таким треугольникам нужно задавать определенный "вес", зависящий от их площади для определенного шанса, то есть чем больше треугольник, тем больше шанс его выбора. Но учитывая, что тебе доступен вариант попроще (разбитие на прямоугольники), лучше пользоваться им
26
rsfghd, можно просто рандомить координаты и при этом, если X выпадает в ненужный промежуток - рандомить Y немного иначе, вот и всё.

Такой вариант, с примером:
Допустим область B имеет размер 6000x6000, а область C в её центре имеет размер 2000x2000. Ищем случайный X для B - это случайное число от 0 до 6000, т.е. мин/макс. координата X для B.
Если случайно полученная координата X выпадает на область C (т.е. между 2000 и 4000), то нужно указать для следующих расчётов что мы будем мнимо сдвигать диапазон в меньшую сторону, поэтому запишем set Y0 = 2000 (иначе оно должно быть равно 0, т.к. проще всегда считать его, но с разным результатом).
Теперь мы ищем координату Y, которая будет равна случайному числу от 0 до 6000 - Y0, т.е. для случаев когда нет наложения - это от 0 до 6000, а когда есть наложение - от 0 до 4000.
Далее, если наше случайно найденное значение для Y удовлетворяет условие Y > 2000 то можно докинуть к нему Y0 (т.е. обратно увеличить на мнимый сдвиг set Y = Y + Y0), который будет равен 0 или 2000 (в случае если диапазон был уменьшен).
На выходе мы получим Y от 0 до 6000 при Y0 = 0 без сдвига.
А со сдвигом - от 0 до 4000 при Y0 = 2000, что даст нам от 0 до 2000 если Y меньше 2000, или от 2000+2000 до 4000+2000 со сдвигом (т.е. от 4000 до 6000).
примерно такой набросочек, может что запамятовал...
	rect B = ... // зона спавна
	rect C = ... // чистая зона
	
	local real xC_min = GetRectMinX(C)
	local real xC_max = GetRectMaxX(C)
	local real xR = GetRandomReal(GetRectMinX(B),GetRectMaxX(B))
	local real yR 
	local real y0 = 0.
	
	if xR > xC_min and xR < xC_max then
		set y0 = xC_max - xC_min
	endif
	
	set yR = GetRandomReal(GetRectMinY(B),GetRectMaxY(B)-y0)
	
	if yR < GetRectMinX then
		set yR = yR + y0
	endif
Ответы (7)
28
Extremator, а если фигура будет посложнее статических прямоугольников? Как зарандомить в этой фигуре точку?
26
rsfghd, для решения своего вопроса можешь создать отдельный топик и указать там все исходные.
25
rsfghd, когда решаешь несуществуюшие задачи :D
(Идеальные универсальные решения мало кому нужны на практике хех)
26
konvan5:
Идеальные универсальные решения мало кому нужны на практике
vJass пытался быть универсальным... и где он теперь?)
23
rsfghd, если будет, то пусть автор создаёт на эту тему вопрос))) но он не задал, значит, ему это не надо)
18
Тут конечного уже ответили, но такого типа вопросы рили у того же ChatGPT задавать можно.
Оно тупо по времени быстрее выйдет.
23
Создаешь и привязываешь к голубой области регион через call Region Add Rect
Затем генерируешь случайные координаты в красной области ( в гуи есть это, только с точкой, потребуется просто переделать bj функцию на координаты)
Если not Is point in region ( регион голубой области, координаты x, y )
То создаешь юнита в координатах и отправляешь в
центр голубой области
Есть варианты и с точками, тогда проверять надо будет через is location in region, ну и удалять новые точки)
Также, если голубая область нужна любой формы, то нужно будет сделать несколько областей и привязать их к региону
Также, если нужно, чтобы и красная область была любой формы, то можно по границам красной области распихать областей и привязать их к этому же региону, у региона не обязательно области должны быть рядом, их можно хоть по концам карты расставить)
Собственно всё)
30
Разбиваешь прямоугольник на несколько, выбираешь из них случайный основываясь на площади и в нём уже авчисляешь случайную точку. Вот код от гпт:
function randomPointExcludingB(A, B) {
    const [xA, yA, wA, hA] = A;
    const [xB, yB, wB, hB] = B;

    // Площади зон
    const leftArea = (xB - xA) * hA;
    const rightArea = (xA + wA - (xB + wB)) * hA;
    const topArea = wB * (yB - yA);
    const bottomArea = wB * (yA + hA - (yB + hB));

    // Зоны и их площади
    const zones = [
        { name: "left", area: leftArea },
        { name: "right", area: rightArea },
        { name: "top", area: topArea },
        { name: "bottom", area: bottomArea }
    ];

    const totalArea = zones.reduce((sum, zone) => sum + zone.area, 0);

    // Выбор зоны пропорционально площади
    let r = Math.random() * totalArea;
    let selectedZone = null;
    for (const zone of zones) {
        if (r <= zone.area) {
            selectedZone = zone.name;
            break;
        }
        r -= zone.area;
    }

    // Генерация случайной точки в выбранной зоне
    let x, y;
    switch (selectedZone) {
        case "left":
            x = Math.random() * (xB - xA) + xA;
            y = Math.random() * hA + yA;
            break;
        case "right":
            x = Math.random() * (xA + wA - (xB + wB)) + (xB + wB);
            y = Math.random() * hA + yA;
            break;
        case "top":
            x = Math.random() * wB + xB;
            y = Math.random() * (yB - yA) + yA;
            break;
        case "bottom":
            x = Math.random() * wB + xB;
            y = Math.random() * (yA + hA - (yB + hB)) + (yB + hB);
            break;
    }

    return [x, y];
}

// Пример использования
const A = [0, 0, 10, 10]; // Прямоугольник A
const B = [3, 3, 4, 4];   // Прямоугольник B
console.log(randomPointExcludingB(A, B));
3
Пацаны, вы чего?! Я, наверное сам виноват, но я искал решение на ГУЕ...
Ответы (22)
25
СерафимКречет, ух, ну тогда держи простую, тупую гуишную систему, где втупую рандомим точку. Если находится внутри среднего региона - рандомим еще раз.
Инициализация координат регионов
Рандомизация точки и спавн юнита в этой точке
Результат
Загруженные файлы
Принятый ответ
25
(Это не оптимальное решение, но оптимально для понимания и решит твою задачу на 100%)
23
СерафимКречет, на гуе в jngp есть функционал для работы с регионами...
23
nazarpunk, но там же без южапи куча нативок южапишных не будет работать.
30
EugeAl, ужопные нативки все помечены. Если их не юзать, то всё прекрасно будет работать.
23
nazarpunk, ок. А перевод есть? Или они просто добавлены?
3
СерафимКречет, ух, ну тогда держи простую, тупую гуишную систему, где втупую рандомим точку. Если находится внутри среднего региона - рандомим еще раз.
Инициализация координат регионов
Рандомизация точки и спавн юнита в этой точке
Результат
чувак, выглядит как то, что нужно. Приеду из отъезда попробую. Спасибо огромное!
30
EugeAl, если у тебя проблемы с простым английским, то лучше его получи. Он всяко больше варкрафта в жизни пригодится.
23
nazarpunk, может и больше, но если ты делал это гуи для более-менее большой аудитории, а не 3,5 гиков, стоило бы учесть, что 80% минимум этой аудитории английского не знают и учить не хотят. Тем более ради гуи
Да и мне лично он не упал, особенно в нынешних реалиях
Да и вообще, сейчас количество знающих англ 1,3 млрд, китйский 1,2 млрд, и испанский 0,5 млрд, притом что англ не учат ни в Лат Америке, ни в половине Европы, ни в Азии, а Африка нафиг не упала - что ж мне теперь - 3 языка учить?
30
что 80% минимум этой аудитории английского не знают и учить не хотят.
А почему меня должно волновать что они там хотят? Нравится грызть кактус - пускай грызут.
23
nazarpunk, тогда резонный вопрос - для кого продукт? Для кого сделано?
а то получается как со "Смутой" - игросодержащий продукт - игра, но не играбельная и не для игроков, а для распила. Технически играть же можно, подумаешь - не нравится, их проблемы, правильно?
30
Для кого сделано?
Для тех кто хочет соскочить с иглы гуймуй, но у него куча гуймуй кода.
30
а то получается как со "Смутой" - игросодержащий продукт - игра, но не играбельная и не для игроков, а для распила. Технически играть же можно, подумаешь - не нравится, их проблемы, правильно?
Вот ниразу не получается. Что я распилил пока сделал гуймуй?
23
nazarpunk, эммм... и как он соскочит с гуя, перейдя на... другой гуй?
Преобразование гуя в код для разбора кода и так существует по дефолту.
Мб тут есть ещё какая то авторская задумка?
Распил тут не основная мысль, просто как уточнение. Суть в том, что сделано было вообще толком без оглядки на аудиторию, вот к чему сравнение было. Что игру делали по принципу "жри чё дали".
30
эммм... и как он соскочит с гуя, перейдя на... другой гуй?
Если ты бы перед критикой пощупал, то увидел бы, что новые нативки очень похожи на синтаксисжас. Но я спотрю ты адепт "не читал, но осуждаю".
Мб тут есть ещё какая то авторская задумка?
Гуй уже сделан. Кому надо, тот заюзает. Тебе он мешает? Нативки понемногу описываются в документации. А завозить переключающихся юнитов я не обираюсь.
23
nazarpunk, я пощупал. Похоже. Хотя в обычном гуи то же самое.
переключающий юнит - это бред, я согласен тут, юнит триггера куда лучше )
30
Хотя в обычном гуи то же самое.
Вообще не то же самое. Как в обычном гуймуе имя нативки узнать?
23
nazarpunk, ну допустим половина там, которые trigger calls - это нативки. Которые trigger actions - это ИмяНативкиBJ, ИмяНативкиSwap, за редким исключением. Ну и конечно же придётся их раскрывать в листе функций, а какой же кодер - кодер, без пользования листом функций?
В принципе, запомнить 3 этих правила - не надо быть мегамозгом )
30
EugeAl, как глядя на гуй, без конвертации имя нативки узнать? В моём гуе сигнатура совпадает.
23
nazarpunk, а зачем узнавать без конвертации в код, если ты собираешься изучать код?
Тем более названия одного мало, нужно ещё смотреть, где и как и куда она ставится, а для этого нужен код.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.