Пользователь
0,0
рейтинг
25 сентября 2013 в 13:24

Разработка → Генератор случайных котов за 8 шагов из песочницы


Доброго времени, Хабр!
Я всегда очень любил котов, и любил их рисовать, особенно морды кошачьи. Чуть изменишь форму, линию — и совершенно другое выражение, другое настроение. У меня листы А4 были изрисованы под предел. И тут мне недавно стукнуло в голову — а что если сделать генератор морд котов? Чтобы нажал на кнопочку и тебе выкинется случайная морда кота. Как можно более случайная и интересная. Давайте же посмотрим, как же сделать такую штуку.
Прошу под кат, любители котов.

Всё будем делать на JS и Canvas'е, и я не привожу код инициализации, настройки и подобного. Этого в интернетах полно, а нам же интересно как рисовать котов, правда?

Приведу лишь несколько предопределенных функций, просто для дальнейшего удобства, вот они:

function add(func, scale){

	Graphics.ctx.scale(scale.x, scale.y);
	func(Graphics.ctx);	
	Graphics.ctx.scale(1, 1);

}

Меняем размер канваса, что-то рисуем, возвращаем назад.

function drawСircle(ctx, pos, radius, fillColor, strokeColor, lineWidth)
{
    ctx.beginPath();
    ctx.arc(center.x - pos.x, center.y + pos.y, radius, 0, 2*Math.PI, false);
    ctx.fillStyle = fillColor;
    ctx.fill();
    ctx.lineWidth = lineWidth;
    ctx.strokeStyle = strokeColor;
    ctx.stroke();
}


А это рисование окружностей\кругов. Тоже ничего особенного, всё это можно прочитать миллионы раз и на хабре и где угодно, давайте скорее к котам!

Шаг 1 — Голова


Начнем мы с головы. Шо есмь голова? Окружность. Которую можно немного сжать, или расширить.
Ещё можно задать толщину обводки, это тоже сделаем. И есть маленькая деталь, смотрим в коде комментарии.
Код весь прокомментирован, думаю проблем с понимаем не возникнет.

//Генерим случайный радиус
var radius = Math.sRandom(60, 70);
//Изменяем размеры
var scaleCircle = {x:Math.sRandom(1,1.1),y:Math.sRandom(0.9,1.0)};
//Задаем цвета
var whiteColor = "#fff";
var blackColor = "#000";
//Рисуем
add(function(ctx){
        // (Math.sRandom(0, 100) < 95 ? blackColor : whiteColor) - эта строчка, иногда, редко, делает контур белым, т.е. голова оказывается без контура. Уверяю, это получаеться здорово.
	drawСircle(ctx, {x:0,y:0}, radius, whiteColor, (Math.sRandom(0, 100) < 95 ? blackColor : whiteColor), Math.sRandom(2,5));
}, scaleCircle);


Воть и голова появилась.



Идем дальше!

Шаг 2 — Уши


Уши у котов — одно из самых выразительных элементов морды. Поэтому чем более уши будут разные, по разному повернуты, разной ширины, тем больше будет разнообразия выражений.
Делаем.

	//Вектор, который будем поворачивать, в поисках точек ушей
	var dir = {x:0, y:radius};
	//Первый угол
    var angleOne = Math.PI + Math.PI/Math.sRandom(2, 5);
    //Поворачиваем вектор и получаем первую точку
    var pointR1 = VectorRot(dir, angleOne);
    //Делаем вторую точку, через поворт вектора на первый угол минус отклонение
    var pointR2 = VectorRot(dir, angleOne - Math.PI/Math.sRandom(4, 7));
    //Считаем верхнюю точку уха
    var topPointR = {x:((pointR1.x + pointR2.x) / 2)+Math.sRandom(-10, 10), y:pointR2.y - 30 + Math.sRandom(0, 5)};
    //Рисуем
	add(function(ctx){
		//Рисуем правое ухо
	    ctx.beginPath();
        ctx.strokeStyle = strokeColor;
        ctx.fillStyle = fillColor;
        ctx.lineWidth = Math.sRandom(2, 4);
        topPointR = {x:topPointR.x+Math.sRandom(-1,5), y:topPointR.y+Math.sRandom(-5,5)};
		ctx.moveTo(center.x + pointR1.x,center.y + pointR1.y);
		ctx.lineTo(center.x + topPointR.x,center.y + topPointR.y);
		ctx.lineTo(center.x + pointR2.x,center.y +pointR2.y);
		ctx.fill();
		ctx.stroke();
		//Рисуем левое ухо
    	ctx.beginPath();
        ctx.strokeStyle = strokeColor;
        ctx.fillStyle = fillColor;
        ctx.lineWidth = Math.sRandom(2, 4);
        var topPointL = VectorXInvert({x:topPointR.x+Math.sRandom(-5,5), y:topPointR.y+Math.sRandom(-5,5)});
        var pointL1 = VectorXInvert(pointR1);
        var pointL2 = VectorXInvert(pointR2);
		ctx.moveTo(center.x + pointL1.x,center.y + pointL1.y);
		ctx.lineTo(center.x + topPointL.x,center.y + topPointL.y);
		ctx.lineTo(center.x + pointL2.x,center.y +pointL2.y);
		ctx.fill();
		ctx.stroke();


	}, {x:1,y:1});


Иииии вот что у нас получилось:



Уже напоминает кота, правда?

Шаг 3 — Усы


Второй во выразительности, после ушей, элемент морды кота. Сделать его не сложно, но сделать так чтобы они выглядели более правдоподобно сложнее. Одним рандомом тут не обойдёшься, приходится крутить цикл, и по счетчику высчитывать точки, для более линейных результатов.

	//Расчитываем точки начала усов
	//путем выбора вектора, и поворота вектора на почти случайное значение
	//Результат - точка начала уса
	var pointsR = [];
	//Выбираем число усов
	var count = Math.floor(Math.sRandom(3, 5));
	for (var i = 0; i < count; i++) {
		//Делаем вектор, с длиной из радиуса круга / на случайное значение
		var dir = {x:0, y:radius/Math.sRandom(1.6,1.9)};
		//Выбираем угол, плюс некоторые действия, для красоты
		var angleOne = Math.PI/(2 + ((i+1)/4));
		//Пвоворачиваем вектор
		var pointR1 = VectorRot(dir, angleOne);
		//Выбираем y конечной точки, так чтобы первую половину count усы отлонялись в одну сторону
		//а во второй половине в другую
		var y = pointR1.y+(i < count / 2 ? -Math.sRandom(8, 25) : Math.sRandom(7, 15) );
		//Записываем точки начала и конца в массив
		pointsR.push({begin:pointR1, end:{x:pointR1.x - Math.sRandom(60, 100),y:y}});
	}
	//Случайное значение ширины линии
	var lineWidth = Math.sRandom(0.5, 2);
	//Рисуем
	add(function(ctx){
		//Правая сторона
		for (var i = 0; i < pointsR.length; i++) {
			ctx.beginPath();
	        ctx.strokeStyle = strokeColor;
	        ctx.fillStyle = fillColor;
	        ctx.lineWidth = lineWidth;
			ctx.moveTo(center.x - pointsR[i].begin.x,center.y + pointsR[i].begin.y);
			ctx.lineTo(center.x - pointsR[i].end.x,center.y + pointsR[i].end.y);
			ctx.stroke();
		}
		//Левая сторона
	    for (var i = 0; i < pointsR.length; i++) {
			
			ctx.beginPath();
	        ctx.strokeStyle = strokeColor;
	        ctx.fillStyle = fillColor;
	        ctx.lineWidth = lineWidth;
	        var pointLBegin = VectorXInvert(pointsR[i].begin);
	        var pointLEnd = VectorXInvert(pointsR[i].end);
			ctx.moveTo(center.x - pointLBegin.x,center.y + pointLBegin.y);
			ctx.lineTo(center.x - pointLEnd.x,center.y + pointLEnd.y);
			ctx.stroke();
		}

	}, {x:1,y:1});


Функция VectorXInvert пусть вас не смущает, просто приходилось часто отражать по x различные элементы, поэтому сделана простая функция, которая делает x = -x;

Смотрим как прорисовывается наш кот:



Шаг 4 — Рот


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

	//---Рот
	//Рот строем с помощью кривых Безье. Задаем четыре точки + 2 точки для отражения
	//      P0
	//  P3  |   iP3
	//  |   |    |
	//  P2--P1--iP2
	var P0 = {x:center.x, y:center.y};
	var P1 = {x:center.x, y:center.y + Math.sRandom(40, 65)};
	var P2 = {x:center.x - Math.sRandom(29, 36),y: center.y + 40};
	var P3 = {x:center.x - Math.sRandom(20, 40), y:center.y + Math.sRandom(23, 28)};
	var iP2 = {x:center.x + Math.sRandom(29, 36),y: center.y + 40};
	var iP3 = {x:center.x + Math.sRandom(20, 40), y:center.y + Math.sRandom(23, 28)};
	//Рисуем
	add(function(ctx){
	    ctx.beginPath();
        ctx.strokeStyle = strokeColor;
        ctx.fillStyle = fillColor ;
        ctx.lineWidth = Math.sRandom(1,3);
		ctx.moveTo(P0.x,P0.y );
		ctx.bezierCurveTo(P1.x, P1.y, P2.x, P2.y, P3.x, P3.y);
		ctx.stroke();

	    ctx.beginPath();
        ctx.strokeStyle = strokeColor;
        ctx.fillStyle = fillColor ;
        ctx.lineWidth = Math.sRandom(1,3);
		ctx.moveTo(P0.x,P0.y );
		
		ctx.bezierCurveTo(P1.x, P1.y, iP2.x, iP2.y, iP3.x, iP3.y);
		ctx.stroke();


	}, {x:1,y:1});


Глядим на то, что получилось. Терпение, ещё чуть-чуть осталось!


Шаг 5 — Нос


Нос есть нос. Сделаем его двух вариантов — маленький круг, и треугольничек. Круг будет появляться намного реже. Ну так, для интереса.
Разуметься примешиваем рандом, в том числе в цвета, чтобы получались разные носы — закрашенные, и просто контур. Нам ведь нужно много котов?

	//Два типа носа - либо треугольник, либо круг
	var chance = Math.sRandom(0, 100);
	if(chance < 98)
	{
		//Коефициент размера
		var scale = {x:Math.sRandom(0.9,1.3), y:Math.sRandom(0.9,1.3)};
		//Правая точка
		var pointR ={x:Math.sRandom(4,5)*scale.x,y:Math.sRandom(-5,-4)*scale.y};
		//Левая точка
		var pointL ={x:Math.sRandom(-4,-5)*scale.x,y:Math.sRandom(-5,-4)*scale.y};
		//Нижняя точка
		var bottomPoint ={x:0,y:Math.sRandom(5,6)*scale.y};
		//Рисуем
		add(function(ctx){
		    ctx.beginPath();
	        ctx.strokeStyle = strokeColor;
	        ctx.fillStyle = (Math.sRandom(0, 100) > 50 ? fillColor : strokeColor);
	        ctx.lineWidth = Math.sRandom(1,3);
			ctx.moveTo(center.x + pointR.x,center.y + 5 + pointR.y);
			ctx.lineTo(center.x + bottomPoint.x,center.y + 5 + bottomPoint.y);
			ctx.lineTo(center.x + pointL.x,center.y + 5 + pointL.y);
			ctx.closePath();
			ctx.fill();
			ctx.stroke();

		}, {x:1,y:1});
	}
	else
	{
		//Рисуем кот
		add(function(ctx){
			drawСircle(ctx, {x:0,y:0}, Math.sRandom(7, 10), strokeColor, strokeColor, 1);
		}, {x:1,y:1});
	}


Наш кот постепенно превращается в кота. Это не может не радовать.



Шаг 6 — Глаза


Глаза штука сложная. Нет, нарисовать не сложно — просто две кривых Безье. Но надо ещё добавить закрывающееся глаза, котик же может спать, а может и один глаз приоткрыть. И это надо сделать. В этот раз просто кот, без кода. Ибо большой объем, не хочется утомлять читателя кучей текста. В конце будут приведены исходники, кто захочет поглядит. А мы просто посмотрим на то что получилось.



Кот уже есть, но добавим ещё некоторый декор.

Шаг 7 — Точки усов на щеках


Знаете, бывают такие. Вероятность появления естественно, не 100%. Вот код, потом результат.
Код простой — просто раскидываем точки на некотором расстояниие от носа.

	if(Math.sRandom(0, 100) > 60)
	{
		add(function(ctx){

			for (var i = 0; i < Math.sRandom(5, 7); i++) {
				var P = {x:Math.sRandom(20, 40),y:Math.sRandom(0, 30)};
				drawСircle(ctx, P, 1, strokeColor, strokeColor, 1);
			}
		    for (var i = 0; i < Math.sRandom(5, 7); i++) {
				var P = {x:-Math.sRandom(20, 40),y:Math.sRandom(0, 30)};
				drawСircle(ctx, P, 1, strokeColor, strokeColor, 1);
			}

		}, {x:1,y:1});
	}


Результат:


Шаг 8 — «Челка»


Просто иногда рисуем парочку линий сверху. На словах тяжело описать, смотрим код, смотрим что получается.


	if(Math.sRandom(0, 100) > 75)
	{
		add(function(ctx){

			
			for (var i = 0; i < Math.sRandom(3, 5); i++) {
				//Берем вектор равный по длине радиусу
				var radiusVector = {x:0,y:-radius};
				//Поворачиваем вектор на некоторое отлонение
				//Нужно чтобы волосы выходили ровно из окружности
				radiusVector = VectorRot(radiusVector, Math.sRandom(-0.01, 0.01))
				//Строим нижнии точки
				var P0 = {x:Math.sRandom(-25, 25), y: radiusVector.y};
				var P1 = {x:Math.sRandom(-25, 25), y: Math.sRandom(-50, -40)};
				//Ширина волоса
				var lineWidth = Math.sRandom(0.5, 1.5);
				//Рисуем
				drawLine(ctx, P0, P1, strokeColor, strokeColor, lineWidth);
			}

		}, {x:1,y:1});
	}


Здорово, правда?



Шаг 8 — Колокольчик или бантик


Ну а это уже просто для интереса, я думал чтобы ещё добавить, и решил добавить бантик и колокольчик. Не судите строго, я развлекаюсь :)
Как всегда код, потом красивые картинки с котиками.

	//Декорации
	//Либо бабочка либо колокольчик
	var chanceBottom = Math.sRandom(0, 100);
	if(chanceBottom > 50)
	{

		var chance = Math.sRandom(0, 100);
		if(chance > 90)
		{
			//Бабочка - два треугольника + круг, с точками в случайном дипазаоне
			var P = {x:0,y:radius};
			var P0 = {x:Math.sRandom(20, 45), y:radius- Math.sRandom(13, 22)};
			var P1 = {x:Math.sRandom(20, 45), y:radius+ Math.sRandom(13, 22)};
			add(function(ctx){
					
				var color = (Math.sRandom(0, 100) > 50 ? fillColor : strokeColor);
			    ctx.beginPath();
		    	ctx.strokeStyle = strokeColor;
		    	ctx.fillStyle = color;
		    	ctx.lineWidth = Math.sRandom(2, 5);
				ctx.moveTo(center.x + P.x,center.y + P.y);
				ctx.lineTo(center.x + P0.x,center.y + P0.y);
				ctx.lineTo(center.x + P1.x,center.y + P1.y);
				ctx.closePath();
				ctx.stroke();
				ctx.fill();

				ctx.beginPath();
		    	ctx.strokeStyle = strokeColor;
		    	ctx.fillStyle = color;
		    	ctx.lineWidth = Math.sRandom(2, 5);
				ctx.moveTo(center.x - P.x,center.y + P.y);
				ctx.lineTo(center.x - P0.x,center.y + P0.y);
				ctx.lineTo(center.x - P1.x,center.y + P1.y);
				ctx.closePath();
				ctx.stroke();
				ctx.fill();

				drawСircle(ctx, P, Math.sRandom(6, 12), (Math.sRandom(0, 100) > 50 ? fillColor : strokeColor), strokeColor, Math.sRandom(1, 3));

			}, {x:1,y:1});
		}
	}
	else
	{
		//Колокольчик
		var chance = Math.sRandom(0, 100);
		if(chance > 90)
		{
			//Колокольчик - треугольник, внизу с кругом. Строится по трём точкам, всё аналогично, как и выше
			var P = {x:0,y:radius};
			var P0 = {x:Math.sRandom(8, 15), y:radius+ Math.sRandom(23, 29)};
			var P1 = {x:-P0.x, y:P0.y};
			var P3 = {x:0,y:P0.y + Math.sRandom(0, 7)};
			add(function(ctx){

				drawСircle(ctx, P3, Math.sRandom(2, 6), (Math.sRandom(0, 100) > 50 ? fillColor : strokeColor), strokeColor, Math.sRandom(1, 3));

				var color = (Math.sRandom(0, 100) > 50 ? fillColor : strokeColor);
			    ctx.beginPath();
		    	ctx.strokeStyle = strokeColor;
		    	ctx.fillStyle = color;
		    	ctx.lineWidth = Math.sRandom(2, 5);
				ctx.moveTo(center.x + P.x,center.y + P.y);
				ctx.lineTo(center.x + P0.x,center.y + P0.y);
				ctx.lineTo(center.x + P1.x,center.y + P1.y);
				ctx.closePath();
				ctx.stroke();
				ctx.fill();

			}, {x:1,y:1});
		}
	}


Как видите ничего сложного, просто геометрические фигуры.
Код был бы скучен, если бы не было котов, да будет кот с бантиком!



Заключение


Ну вот и закончил я свое повествование о котах.
Привожу код на гитхабе: github.com/MagistrAVSH/random-cat
А вот результат всех трудов, можете пощелкать: magistravsh.github.io/random-cat
А теперь брысь от монитора, и погладь кота! :)
MagistrAVSH Cats'A @Magistr_AVSH
карма
35,2
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (69)

  • +17
    Коты хороши, в меру упитанные. Еще бы ширина мордахи менялась :)
    • +1
      И ещё: сколько ни щёлкал, так и не удалось нащёлкать скоттиш фолда :-)
      • 0
        Точно! Найден фатальный недостаток :)
  • 0
    Некоторые коты без овала морды, так задумано?
    • +3
      В статье же написано про это)
      • +2
        Ах да. Не вчитывался в код, прошу прощения
  • НЛО прилетело и опубликовало эту надпись здесь
    • +4
      Я думаю у них рандом нечестный.
      • +7
        Честный на 146%.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Ну если снова посетит вдохновение, обязательно сделаю :) Хотелось бы ещё выгрузку в файл сделать. Но увы, подустал от котов немного.
      • 0
        Не туда ответил.
        Снизу вроде есть такое реквест уже? Если так, то извините за дубляж.
      • +1
        Сделайте-сделайте! Можно будет и историю с отменой сделать.
        Только хотел предложить сделать кнопку «предыдущий кот», чтобы можно было вернуть результат предыдущей генерации. А то столько чудесных котиков пролистывается, пока жмякаешь на кнопку «Generate!»…
        А ещё слайдеры для кастомной настройки кота. Ведь в коде много рандомных параметров — вот все рандомы в слайдеры переделать хорошо бы.
    • +14
      Лучше прикрутить генетические алгоритмы с количеством лайков от пользователей вместо фитнеса. Тогда скоро будет выведена самая няшная порода котэ.
      • 0
        Няшность котейки каждый определяет по-своему, и потому остановиться на какой-то одной породе вряд ли получится. Так что потребуется алгоритм с поддержкой нескольких локальных максимумов (ну или минимумов, смотря что мерять).
        • 0
          Статистика такая гадкая наука, которая навязывает индивидуумам мнение большинства ;)
  • +8
    Производительность скрипта следует изменять в котах в секунду)
    • 0
      Если честно, то не особо думал о производительности, так как анимации нет, просто генерация статичного изображения.
      • +1
        Ну так вдруг человек захочет сгенерировать столько котов, сколько влезет на его жесткий диск?
        Надо же ему будет знать, как долго будут генериться коты)
  • +1
    del
  • +3
    Никогда не понимал, почему нельзя таким же образом генерировать скины для монстров/зомби/прочих врагов в играх? Насколько интереснее был бы, например, мой любимый Day Z, если бы каждый зомби там был чуть-чуть другим, отличался от остальных одеждой, лицом, ростом и фигурой. А то сейчас там пяток стандартных скинов и всё. Эххх…
    • +4
      Возможно потому, что врагов по цвету/виду как раз и можно отличить? Тот же серьезный сем первый — там были противники, которые головы в руках носили. И были разных типов. Отличить можно было только по цвету. В простых играх — то же самое.

      без цветовой дифференциации штанов общество лишено цели
      • +2
        Зато во-первых реалистичнее (к этому же вроде стремиться большинство современный игровых движков?), во вторых представте как здорово было бы похвастаться: «Играл вчера в STALKER, такого худющего кровососа видел возле „Юпитера“ — кожа да кости, хромает, рожа облезлая… болеет он что-ли? Так чего-то жалко его стало, что даже убивать не стал. А собаки в последнее время наоборот здоровые пошли, и жирные — просто кабаны, а не собаки. Недавно за мной такая по всей локации гонялось — еле смылся. Радиация на них так действует что ли?...»

        Круто ведь было бы, разве нет?
        • 0
          ИМХО это немного другое. Например, в GTA (по моему начиная с San Andreas) автомобили могли генерироваться с повреждениями, или тюнингованные. Да, это было круто, это было разнообразие. А теперь возьмем какую нибудь сложную миссию. Вы ее пытаетесь пройти раз 20, уже приноровились что и как делать и тут БАЦ — модель чего то в миссии другая. Подсознательно вы будете вопринимать уже эту модель как нечто другое, и опыт прошлых попыток не будет задействован мозгом полностью. Возьмем что то попроще — любой метч3. Допустим надо совмещать предметы по цветам. Когда у всех предметов одинаковая форма — все легко воспрнимается. А теперь представьте, что формы — разные. Мозг будет думать что желтый квадрат и желтый кружок — это нечто разное.
          • 0
            Возможно вы и правы. В single player играх, где можно сохраниться, а потом ковырять одного и того же монстра пока не пройдеш — да, наверное игроку будет удобнее когда этот монстр всегда один и тот же на вид и ведет себя одинаково.

            А в ролевых open world играх в онлайне? Где нет кнопки «сохранить» и одна и та же ситуация не повторяется? Неужели кто-то откажется от фантастического мира, заполненного разными зомби, разными на вид и с разными боевыми качествами? С разным поведением? Не разделённые на пару классов как в том же HL — «обычный зомби», «быстрый зомби» и т.п. — а различными? Идеш — смотриш идет тощий чахлый зомби. Думаеш что он немощный и неопасный, а он вдруг становится на четвереньки и прыгает на тебя… Или отрывает себе руку и кидает в тебя этой рукой. Демонстрирует уникальный внешний вид и поведение (которое тем не менее вписывается в какие-то рамки под названием «вид и поведение зомби»:)). Я бы в такую игруху с удовольствием поиграл.
            • 0
              Боюсь что данный спор выходит за рамки топика о котиках :-) Вкратце — боевые качества должны так или иначе визуально определяться игроком.
              • 0
                Да, похоже мы немного отошли от темы. Спасибо за дискуссию :)
            • 0
              Когда у нас есть зомби типа 3 в левом углу комнаты (x: 132.381, y:472.785, z:23.542), то сервер передаст игроку пакет содержащий три double и один int. Теперь представим что каждый тип может наследовать множество особенностей, к примеру то-же отрывание руки, значит эту информацию нужно передать клиенту, предварительно прочитав ее из памяти сервера (в которой для каждой модели будет уже не четыре переменных, а на порядок больше, даже если модель наследует базовые свойства). Это создаст дополнительную нагрузку на сервер, на канал и на клиента, так как все это надо еще отрендерить. В ближайшем будущем (5 лет), думаю что популярностью пользоваться не будет, но вот когда в виртуальные миры можно будет полностью погрузиться (не обязательно всем сознанием), то уникальные модели будут необходимы для поддержания ощущения «реальности».
    • +1
      Это бы сильно увеличило требования к видеопамяти. Одна текстурка хорошего качества занимает порядка четырёх мегабайт, а пямять нужна не только для текстур монстров. Кроме того, генерация подобных процедурных текстур — довольно требовательный к ресурсам процесс (например, потому что обычно выполняется силами CPU), который сильно увеличил бы время загрузки.

      Ну и нельзя забывать, что сделать процедурную карту, генерирующую правдоподобные и одновременно с этим разнообразные рожицы, куда сложнее, чем нарисовать несколько текстурок для зомби.


      Хотя с другой стороны, в таких играх, как Skyrim или Sims, скины, как я понимаю, генерируются динамически… Хм… Тогда, наверное, выше я в чём-то ошибся.
      • 0
        Шейдеры рулят…
    • 0
      Возможно, потому, что в трехмерных играх это не просто скин (текстура). Я не спец в computer graphics, но насколько я понимаю, большинство движков используют разные ухищрения, чтобы модельки выглядели красиво и не тормозили. Всякие там карты освещения, карты нормалей. Если «переодеть» персонажа в случайную одежду, придется для него рисовать дополнительный контент, и делать это скорее всего вручную. Можно, конечно, сделать кучу вариаций и их смешивать. Так сделано в GTA, начиная с San Andreas, если не ошибаюсь.
      А для изменения роста/фигуры надо писать движок соответствующий, это в игре вроде ArmA2 (и, как следствие, DayZ) вроде не сильно нужно…
  • +4
    К этой популяции надо прикрутить рейтинг как критерий выживаемости и добавить генетические алгоритмы.
    • 0
      Идея для монетизации — добавить голосование посредством СМС за лучших, а затем за спасение кандидатов на «вылет».
  • +5
    Ня! ^.^
    • +3
      А можно еще так
      =^..^=

      Кот, выглядывающий из-под стола) Если взять точки за глазки)
  • +4
    Есть еще правильные программисты! Может и правда стоит завести на Хабре хаб Коты?
  • +18
    Тут серьезная математика, между прочим.
  • +1
    Сразу напомнило котов из Mew-Genics
    скриншотик

    • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Даешь котов! :)
    И таким же образом еще туловище можно пририсовать, верно?)
    • 0
      Ну это, на мой взгляд, немного сложнее, ибо туловище имеет куда больше форм, тем самым сложнее сделать это красиво, сложнее чем с мордой. Но есть куда развиваться)
      • 0
        Будем пробовать! :)
    • +8
      И вид сзади (простите).
      • +4
        Здесь не место политике)
      • 0
        Тогда уж сразу грант выспрашивать на генератор Алин.
  • –2
    Иногда получаются очень страшные котики. А иногда и не котики вовсе.
    А иногда голова котика без обводки
    Скрытый текст

  • +4
    Странно, что никто не вспомнил про лица Чернова. Автор, если вы сделаете лица котов вертикально асимметричными, и замените рандомы на внешние параметры, получится отличное средство визуализации — количество степеней свободы у кошачьих лиц будет поболее, чем у человечьих :)
  • 0
    Сразу придумалось миллион применений, начиная от аватарки пользователя и заканчивая персонажами в 2D игре )
    • 0
      Я делаю небольшую браузерную 2D игру для одного ресурса. Вполне возможно что для смеха вставлю туда эту штуку :) Применений действительно масса.
      Как-то был пост на Хабре, где делали процедурные пиксельные аватарки, что-то похожее и тут.
  • 0
    А чего они такие страшные? Кот хорош, когда они мимимишный. Сейчас, к сожалению, это не так)
    • 0
      Просто погладь кота
      мимими
  • 0
    Бывает...
    image
    • +1
      habrahabr.ru/post/195142/#comment_6771436
      В самом верху же написано :) Да, это так задумано.
      Изначально это был баг, перешедший из категории багов в категорию фич, потому что мне этот эффект понравился.
  • +1
    которобот
  • +1
    img7.imageshack.us/img7/227/j3aa.png
    Получился слишком толстый кот с маленькой моськой)
  • 0
    Имхо, один глаз закрывается слишком часто. Одноглазых должно быть мало, а тут их большая часть.
    А вообще, спасибо за котов!
  • +5
    а когда рандомный вид сзади сделаете?
    например:
    image
  • 0
    Очень круто! Когда-то хотел тоже сделать генератор портретов для игры, но дальше идеи дело не пошло. А тут действительно большой объем работы сделан до конца и результат вполне прикольный!
  • +2
    Реквестирую Котиков Чернова!
  • 0
    Сколько тысяч лет мне придется жать на кнопку Generate, чтобы получить котейку без контура, с круглым носом и бантиком?
    • 0
      Не проще код поправить?
  • +1
    QR-кот
  • 0
    Генератор аватарок для анимешных ресурсов :)
  • +1
    Классно, но не живые. Исправил тут: Добавил анимации тут.Жать на кнопку Live.

    Я когда-то на синклере подобное (мультяшное лицо) делал. Всё мечтал динамики добавить, но перфоманса не хватало.

    • 0
      Анимация неплохая, но… какая-то неестественная для кота. Исчезающая обводка, точки на щеках, странным образом двигающиеся усы. Как-то странно выглядит.
      • +1
        Ну так и кот не совсем канонический.
        В коде дергается случайный параметр от минимального до максимального значения с произвольным периодом. Можно подобрать периоды для нескольких «случайных» бросков — тогда получим более естественную анимацию.
        А вообще это просто прикол. Да и обожаю я генераторы псевдослучайных чисел, особенно для подобных задач.
        • 0
          Я вообще люблю всякие процедурные алгоритмы :) А насчет прикола, ну если прикол, тогда вполне годно.
  • 0
    Вот еще один генератор рандомных котиков
    thecatapi.com
    Рандомный котик

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.