20

» Game Dev / Аниматик к нашей игре

Мне очень нравится дизайн и стиль рисовки, какая-то настольгия по флэш играм из детства
20

» XGM Конкурсы / Результаты и видео конкурса 3D-инсталляций 2025!

С результатами конкурса я согласен, но уровень представленных работ оставляет желать лучшего.
Работа N7 Molot заняла 3-е место, хотя выглядит как набор наспех расставленных ассетов. Возможно, там имело значение удачно выбранный ракурсом скриншот. Но речь, же, идёт о 3D-инсталляции. Хотелось бы видеть от жюри более строгий подход и введение минимального порога качества, тоесть если работа не дотягивает, она просто не должна проходить в конкурс.
Понимаю, что для хигамы это, по сути, дебют в конкурсах геймдева (мб я ошибаюсь). И в этом смысле сам факт проведения конкурса уже шаг вперёд. Однако именно поэтому хотелось бы сразу видеть работы, которые могут задать высокую планку. Мне казалось что смысл таких демо-инсталяций - вдохновить зрителяя, пробудить в нём идею - может игры, книги, истории, чего угодно. Однако, я не почувствовал ничего. После просмотра не возникло ни одной идеи, не зацепило.
Отдельно стоит сказать о ИИ медальках, которые выглядят крайне неудачно. Если вы хотите использовать нейросети, то хотя бы выдерживайте единый стиль. А ещё лучше - нарисуйте что-то вручную, пусть даже в пеинте. Мне лично было бы приятнее получить простые карикатуры, чем генеряшку, которая выглядит очень дешево и без души.
20

» WarCraft 3 / [Jass] - Огненный Шар

library Points {

	public Point2D TempPoint;

	public struct Point2D {
		real x, y;
		
		// Constructors
		static method createAt(real x, real y) -> Point2D {
			return Point2D.allocate().setAt(x, y);
		}

		static method createAtWidget(widget which) -> Point2D {
			return Point2D.allocate().setAt(GetWidgetX(which), GetWidgetY(which));
		}
		
		static method create() -> Point2D {
			return Point2D.allocate().setAt(0.0, 0.0);
		}
		
		// Transitional behavior
		static method clone(Point2D another) -> Point2D {
			return Point2D.allocate().setAt(another.x, another.y);
		}
		
		method setAt(real x, real y) -> Point2D {
			this.x = x + GetRandomReal(-0.1, 0.1);
			this.y = y + GetRandomReal(-0.1, 0.1);
			return this;
		}

		method setAtWidget(widget which) -> Point2D {
			this.setAt(GetWidgetX(which), GetWidgetY(which));
			return this;
		}
	
		method clear() -> Point2D {
			return this.setAt(0.0, 0.0);
		}

		method copy(Point2D another) -> Point2D {
			return this.setAt(another.x, another.y);
		}

		// Hash
		method save(handle whichHandle, integer childKey) -> Point2D {
			SaveInteger(HT, GetHandleId(whichHandle), childKey, this);
			return this;
		}

		static method load(handle whichHandle, integer childKey) -> Point2D {
			return LoadInteger(HT, GetHandleId(whichHandle), childKey);
		}

		// Math
		method distTo(Point2D another) -> real {
			return DistanceBetweenCoords(this.x, this.y, another.x, another.y);
		}

		method distToCoords(real x, real y) -> real {
			return DistanceBetweenCoords(this.x, this.y, x, y);
		}

		method distToWidget(widget which) -> real {
			return DistanceBetweenCoords(this.x, this.y, GetWidgetX(which), GetWidgetY(which));
		}

		method angleTo(Point2D another) -> real {
			return AngleNormalize(AngleBetweenCoords(this.x, this.y, another.x, another.y));
		}

		method angleToCoords(real x, real y) -> real {
			return AngleNormalize(AngleBetweenCoords(this.x, this.y, x, y));
		}

		method angleFromCoords(real x, real y) -> real {
			return AngleNormalize(AngleBetweenCoords(x, y, this.x, this.y));
		}

		method movePolar(real distance, real angle) -> Point2D {
			this.x = GetPolarOffsetX(this.x, distance, angle);
			this.y = GetPolarOffsetY(this.y, distance, angle);
			return this;
		}

		method moveTowards(Point2D another, real distance) -> Point2D {
			real angle = this.angleTo(another);
			this.x = GetPolarOffsetX(this.x, distance, angle);
			this.y = GetPolarOffsetY(this.y, distance, angle);
			return this;
		}

		method getTerrainZ() -> real {
			return GetTerrainZ(this.x, this.y);
		}

		method getTerrainCliffZ() -> real {
			return (GetTerrainCliffLevel(this.x, this.y) - 1) * 128.;
		}

		method approachClosestAvailablePoint(Point2D another) {
			real angle = this.angleTo(another);
			real height = another.getTerrainCliffZ();
			while (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) || AbsReal(this.getTerrainCliffZ() - height) > 100.) {
				this.movePolar(50, angle);
			}
		}
	}

}
20

» WarCraft 3 / [Jass] - Огненный Шар

library Parabolas requires Points {

	public struct Parabola {
		Point2D start;
		Point2D end;
		real apsis;

		static method create(Point2D start, Point2D end, real apsis) -> Parabola {
			return Parabola.allocate().setAt(start, end, apsis);
		}

		method destroy() {
			this.start.destroy();
			this.end.destroy();
			this.deallocate();
		}

		method setAt(Point2D start, Point2D end, real apsis) -> Parabola {
			this.start = start;
			this.end = end;
			this.apsis = apsis;
			return this;
		}

		method setStart(Point2D start) -> Parabola {
			this.start.copy(start);
			return this;
		}

		method setEnd(Point2D end) -> Parabola {
			this.end.copy(end);
			return this;
		}

		method setapsis(real apsis) -> Parabola {
			this.apsis = apsis;
			return this;
		}
	
		method calculateZ(Point2D current, real startOffsetZ, real endOffsetZ) -> real {
			real startHeight = start.getTerrainZ() + startOffsetZ;
			real endHeight = end.getTerrainZ() + endOffsetZ;
			real totalDistance = start.distTo(end);
			real currentDistance = start.distTo(current);
			real apsis = MaxReal(startHeight, endHeight) + apsis;
			return ParabolaZ2(startHeight, endHeight, apsis, totalDistance, currentDistance);
		}

		method calculateZMaxHeight(Point2D current, real startOffsetZ, real endOffsetZ, real maxHeight) -> real {
			real startHeight = start.getTerrainZ() + startOffsetZ;
			real endHeight = MinReal(end.getTerrainZ() + endOffsetZ, start.getTerrainZ() + startOffsetZ + maxHeight);
			real totalDistance = start.distTo(end);
			real currentDistance = start.distTo(current);
			real maxApsis = MaxReal(startHeight, endHeight) + apsis;
			return ParabolaZ2(startHeight, endHeight, maxApsis, totalDistance, currentDistance);
		}
	}

}
20

» WarCraft 3 / [Jass] - Огненный Шар

Похожая либа для проджектайлов на Zinc
library StaticProjectiles requires TechUtils, Parabolas {

	// Constants
	constant real FOCUS_LOST_DISTANCE = 200.;
	constant real HIT_DISTANCE = 25.;

	struct StaticProjectile {
		integer object;
		unit owner;
		unit target;
		unit projectile;
		integer actionsId;
		real speed;
		real offsetZ;
		real startOffsetZ;
		boolean canFocusLost;
		string func;
		Point2D current;
		Point2D end;
		Parabola parabola;
		boolean isFocused;

		timer tm;
		static integer CK_HID = 0;
		static real INTERVAL = 1./40.;

		static method create(
			integer object,
			unit owner,
			unit target,
			unit projectile,
			integer actionsId,
			string func,
			real speed,
			real maxHeight,
			real offsetZ,
			boolean canFocusLost
		) -> StaticProjectile {
			StaticProjectile this = StaticProjectile.allocate();
			this.current = Point2D.createAtWidget(owner);
			this.end = Point2D.createAtWidget(target);
			this.parabola = Parabola.create(Point2D.clone(current), Point2D.clone(end), maxHeight/(1200/current.distTo(end)));

			this.object = object;
			this.owner = owner;
			this.target = target;
			this.projectile = projectile;
			this.speed = speed;
			this.offsetZ = offsetZ;
			this.actionsId = actionsId;
			this.func = func;
			this.canFocusLost = canFocusLost;

			this.startOffsetZ = GetUnitZ(owner) - current.getTerrainZ();
			this.isFocused = true;
			MakeUnitFly(projectile);
			SetUnitPathing(projectile, false);

			this.tm = CreateTimer();
			SaveInteger(HT, GetHandleId(this.tm), CK_HID, this);
			TimerStart(this.tm, 0, false, function StaticProjectile.callback);

			return this;
		}

		static method createAt(
			integer object,
			unit owner,
			real x,
			real y,
			unit projectile,
			integer actionsId,
			string func,
			real speed,
			real maxHeight,
			real offsetZ
		) -> StaticProjectile {
			StaticProjectile this = StaticProjectile.allocate();
			this.current = Point2D.createAtWidget(owner);
			this.end = Point2D.createAt(x, y);
			if (maxHeight > 0) {
				this.parabola = Parabola.create(Point2D.clone(current), Point2D.clone(end), maxHeight/(1200/current.distTo(end)));
			} else {
				this.parabola = 0;
			}
			

			this.object = object;
			this.owner = owner;
			this.target = null;
			this.projectile = projectile;
			this.speed = speed;
			this.offsetZ = offsetZ;
			this.actionsId = actionsId;
			this.func = func;

			this.startOffsetZ = GetUnitZ(owner) - current.getTerrainZ();
			this.isFocused = false;
			MakeUnitFly(projectile);
			SetUnitPathing(projectile, false);

			this.tm = CreateTimer();
			SaveInteger(HT, GetHandleId(this.tm), CK_HID, this);
			TimerStart(this.tm, 0, false, function StaticProjectile.callback);

			return this;
		}

		method destroy() {
			KillUnit(projectile);
			owner = null;
			target = null;
			projectile = null;

			current.destroy();
			end.destroy();
			if (IsSet(parabola)) parabola.destroy();

			FlushChildHashtable(HT, GetHandleId(tm));
			PauseTimer(tm);
			DestroyTimer(tm);
			tm = null;

			this.deallocate();
		}

		static method callback() {
			StaticProjectile this = LoadInteger(HT, GetHandleId(GetExpiredTimer()), CK_HID);
			real angle;
			real endOffsetZ = 0;
			
			TimerStart(tm, INTERVAL, false, function StaticProjectile.callback);

			if (isFocused && canFocusLost && end.distToWidget(target) >= FOCUS_LOST_DISTANCE)
				isFocused = false;
			
			if (isFocused) {
				end.setAtWidget(target);
				endOffsetZ = GetUnitZ(target) - end.getTerrainZ();
				if (IsSet(parabola)) parabola.setEnd(end);
			}

			angle = current.angleTo(end);
			current.movePolar(speed * INTERVAL, angle);
		
			SetUnitFacing(projectile, angle);
			SetUnitX(projectile, current.x);
			SetUnitY(projectile, current.y);
			if (IsSet(parabola)) SetUnitZ(projectile, parabola.calculateZ(current, offsetZ + startOffsetZ, offsetZ + endOffsetZ));

			if (current.distTo(end) <= HIT_DISTANCE) {
				SPELL_OWNER_UNIT_GET = owner;
				SPELL_TARGET_UNIT_GET = target;
				SPELL_IS_FOCUSED_GET = isFocused;
				SPELL_ACTIONS_ID_GET = actionsId;
				SPELL_OBJECT_GET = object;
				SPELL_X_GET = end.x;
				SPELL_Y_GET = end.y;
				if (actionsId != 0) {
					ExecuteFunc("Trig_" + TRIG_EVENT_SPELLS + "_Actions");
				} else {
					ExecuteFunc(func);
				}
				SPELL_OWNER_UNIT_GET = null;
				SPELL_TARGET_UNIT_GET = null;
				SPELL_IS_FOCUSED_GET = false;
				SPELL_ACTIONS_ID_GET = 0;
				SPELL_OBJECT_GET = 0;
				SPELL_X_GET = 0;
				SPELL_Y_GET = 0;
		
				this.destroy();
			}
			
		}
	}
		
	public function CreateStaticProjectile(
		unit owner,
		unit target,
		unit projectile,
		integer actionsId,
		real speed,
		real maxHeight,
		real offsetZ,
		boolean canFocusLost
	) -> StaticProjectile {
		return StaticProjectile.create(
			0,
			owner,
			target,
			projectile,
			actionsId,
			"",
			speed,
			maxHeight,
			offsetZ,
			canFocusLost
		);
	}

	public function CreateStaticProjectileFunc(
		integer object,
		unit owner,
		unit target,
		unit projectile,
		string func,
		real speed,
		real maxHeight,
		real offsetZ,
		boolean canFocusLost
	) -> StaticProjectile {
		return StaticProjectile.create(
			object,
			owner,
			target,
			projectile,
			0,
			func,
			speed,
			maxHeight,
			offsetZ,
			canFocusLost
		);
	}

	
	public function CreateStaticProjectileAtFunc(
		integer object,
		unit owner,
		real x,
		real y,
		unit projectile,
		string func,
		real speed,
		real maxHeight,
		real offsetZ
	) -> StaticProjectile {
		return StaticProjectile.createAt(
			object,
			owner,
			x,
			y,
			projectile,
			0,
			func,
			speed,
			maxHeight,
			offsetZ
		);
	}

}

// 2022
20

» Game Dev / Вот почему маркетинг не спасёт вашу инди игру

Феникс, ну тут зря быканул, просто в начале, кажется, что воды много. Ну вывод (Так что же автор этого поста хочет донести до вас?) улучшает ситуацию.
20

» Game Dev / Как спроектировать игровую математическую модель, забалансить её и не сдуреть. Разбор на практических кейсах

PROSHELDOTU,
держи в курсе, очень важно знать ! расскажи ещё побольше что смог/не смог... рофл
И что мне теперь комментарии писать запретишь?
рецензия в 3 строчки совершенно бесполезная и не несет никакой ценности, это бесспорно
Как собственно и статья
так всё же: из бреда или из очевидной информации ?? или просто из тебя шиза лезет...
в дополнение к последнему — вопрос: а ты точно в обед был на работе ? а не в школе :)))
Да, я школьник. Или из ложных выводов или из бесполезной информации, которую люди осознают на подсознательном уровне. Не было бы такого заголовка - не было бы претензий.
Как спроектировать игровую математическую модель, забалансить её и не сдуреть. Разбор на практических кейсах
Разбор пары механик в вакууме есть. Игровой математической модели нет как и ее проектирования.
20

» Game Dev / Вот почему маркетинг не спасёт вашу инди игру

Тезис 3 - хороший, мне понравился, можно было оставить только его и выпустить как "тему". В остальном какой-то вайб Cancel'а с его лесенкой урона.
20

» Game Dev / Вот почему маркетинг не спасёт вашу инди игру

Ну последнее время на хгм какой-то вайб бесполезных статей. Ну кидайте камни, но ничего нового я не прочитал. Говно не продашь как ты блестками его не посыпай. Это своего рода информация, существующая на подсознательном уровне, и не вполне ясно, зачем её выносить на поверхность.
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, просто иногда тебе важно чтобы это исполнилось в одном "потоке"
20

» WarCraft 3 / [Jass] - Буран

KaneThaumaturge,
форгруп запустишь и удалишь группу, то он все равно отработает
Я вроде тестил такое, хотя уже не уверен.
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, да, я раньше брезговал задержку в 0 ставить. Но мне кажется это прям классная штука сейчас. Мб везде так сделаю.
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, а чё сломается, если ты форгруп запустишь и удалишь группу, то он все равно отработает
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, в целом лучше просто фор груп прям в конец переместить. Мб так лучше будет
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, достаточно задержку в 0 на таймере, проверено. Я так и делаю. Только у меня модификаторы урона моментально срабатывают, а ивент на сам урон с задержкой.
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, именно в этом не может быть, да. Я же говорю, это так для информации. Если этот код модифицировать и использовать с ивентом урона, то может быть.
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, не я про то, что в этом коде коллизия может быть с глобалками потому что он исполняется после нанесения урона
20

» WarCraft 3 / [Jass] - Буран

nazarpunk, не понял сарказм, а этот код шутка? Или это я что-то не понял?
call GroupClear(Group)
    
	if GetUnitCurrentOrder(Caster) != 0xd0079 then // blizzard
		call PauseTimer(Timer)
		call DestroyTimer(Timer)
		call FlushChildHashtable(HT, TimerId)
	endif