
Кукловод - маленький гайд по созданию Ragdoll'ов
Создание Куколок.
В этом Уроке я покажу, как я создаю ragdoll'ы
для своих игр С множественным числом я погорячился — для своей игры
Необходимо:
Adobe Flash Studio (у меня CS4) — Для рисования.
Flash Develop + haxe — Для программирования.
Nape — физический двиг.
Как настраивать проект и где брать — не скажу.
Ибо я показываю метод, а не детальное руководство.
Хочется верить, что я программист (
Хотя иногда приходиться открывать штуки для рисования.
ИДЕ у меня появилось не давно — осваивать его решил.
Идея такая не задавать кодом структуру
человечка, а определить функцию, которая считывает
клип с его частями.
Этап 1: Рисование куколок
К сожалению, что во мне спит художник — я точно не верю)
Разбудить мне его не удалось, поэтому не буду
показывать как я рисовал, только результат.
Рисуем части тела по отдельности.
Вот что у меня вышло — ужас):

Теперь конвертируем части тела в клипы:
Я сделал так:

Также, как видно, я добавил еще один символ
— маленький круг — joint
это крепления для частей.
Создаем новый символ ragdoll
и распологаем по местам все наши части,
там где должны быть соединения ставим joint:

И важно, не забыть, прописать всем символам
имена(instance Name).Я написал такие же, как и названия символов.
А Соединениям нужно писать, если голова- join_head, рука — joint_hand_left и тп.
Теперь в свойствах Символа разрешаем ему Экспортироваться
С именем CRagdoll (С большой буквы, ибо Хакс не понимает классы с маленькой)

Все теперь можно нажать Shift+F12 или Publish
Рисование кончалось)
Начинаем прогать.
Этап 2: Куколка живи
Создаем новый хакс проект во ФлещДевелоп

В проекте создаем папку lib
в нее добавим наш ragdoll.swf
Надеюсь нап вы сами скачаете.
У Луки какие-то проблемы с версией под хакс, так что качать лучше код.
Теперь к проекту подключаем библиотеку
Нажать на проект — добавить (Add) — Libraly Asset выбираем наш файл ragdoll.swf
Утомился я писать)
Исходники прикреплю.
Описывать весь процесс не стану — слишком долго, кода вышло много)
опишу методы:
createBoxBySprite — Создает Тело с прикрепленным к нему спрайтом.
createBoxByChild — создает тело по имени ребенка у спрайта
createPivotJoint — создает точечное соединение
createPivotJointByChild — по имени чайлда
createRotaryLimitJoint — создает соединение, ограничивающее углы
createRagdollBySprite — главная наша функция создает регдольчик
Да, много функций для урока) но они потом пригодятся, к примеру для
объектов уровня и тп
Плюс этого метода.
Что теперь художник может нарисовать персонажа
— любого роста и телосложения, а нам — программерам — пофиг)
Что вышло — смотреть ниже (флешку сюда вставить нельзя?, сейчас залью куда-нибудь)
кликаем на экран появляется куколка)
мой нет-бук держит порядка 20 тел, но злоупотреблять не стоит…
Архив с исходником и медией:СКАЧАТЬ или ifolder
Смотреть:СМОТРЕТЬ
Не уверер, что кто-то смотрел код на haxe), а я старался. Так, что показываю здесь
П.С. постарался исправить все ошибки и опечатки.
В этом Уроке я покажу, как я создаю ragdoll'ы
для своих игр С множественным числом я погорячился — для своей игры
Необходимо:
Adobe Flash Studio (у меня CS4) — Для рисования.
Flash Develop + haxe — Для программирования.
Nape — физический двиг.
Как настраивать проект и где брать — не скажу.
Ибо я показываю метод, а не детальное руководство.
Хочется верить, что я программист (
Хотя иногда приходиться открывать штуки для рисования.
ИДЕ у меня появилось не давно — осваивать его решил.
Идея такая не задавать кодом структуру
человечка, а определить функцию, которая считывает
клип с его частями.
Этап 1: Рисование куколок
К сожалению, что во мне спит художник — я точно не верю)
Разбудить мне его не удалось, поэтому не буду
показывать как я рисовал, только результат.
Рисуем части тела по отдельности.
Вот что у меня вышло — ужас):

Теперь конвертируем части тела в клипы:
Я сделал так:

Также, как видно, я добавил еще один символ
— маленький круг — joint
это крепления для частей.
Создаем новый символ ragdoll
и распологаем по местам все наши части,
там где должны быть соединения ставим joint:

И важно, не забыть, прописать всем символам
имена(instance Name).Я написал такие же, как и названия символов.
А Соединениям нужно писать, если голова- join_head, рука — joint_hand_left и тп.
Теперь в свойствах Символа разрешаем ему Экспортироваться
С именем CRagdoll (С большой буквы, ибо Хакс не понимает классы с маленькой)

Все теперь можно нажать Shift+F12 или Publish
Рисование кончалось)
Начинаем прогать.
Этап 2: Куколка живи
Создаем новый хакс проект во ФлещДевелоп

В проекте создаем папку lib
в нее добавим наш ragdoll.swf
Надеюсь нап вы сами скачаете.
У Луки какие-то проблемы с версией под хакс, так что качать лучше код.
Теперь к проекту подключаем библиотеку
Нажать на проект — добавить (Add) — Libraly Asset выбираем наш файл ragdoll.swf
Утомился я писать)
Исходники прикреплю.
Описывать весь процесс не стану — слишком долго, кода вышло много)
опишу методы:
createBoxBySprite — Создает Тело с прикрепленным к нему спрайтом.
createBoxByChild — создает тело по имени ребенка у спрайта
createPivotJoint — создает точечное соединение
createPivotJointByChild — по имени чайлда
createRotaryLimitJoint — создает соединение, ограничивающее углы
createRagdollBySprite — главная наша функция создает регдольчик
Да, много функций для урока) но они потом пригодятся, к примеру для
объектов уровня и тп
Плюс этого метода.
Что теперь художник может нарисовать персонажа
— любого роста и телосложения, а нам — программерам — пофиг)
Что вышло — смотреть ниже (флешку сюда вставить нельзя?, сейчас залью куда-нибудь)
кликаем на экран появляется куколка)
мой нет-бук держит порядка 20 тел, но злоупотреблять не стоит…
Архив с исходником и медией:СКАЧАТЬ или ifolder
Смотреть:СМОТРЕТЬ
Не уверер, что кто-то смотрел код на haxe), а я старался. Так, что показываю здесь
package ;
import flash.Lib;
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.events.Event;
import flash.events.MouseEvent;
import nape.geom.Vec2;
import nape.geom.AABB;
import nape.space.Space;
import nape.space.UniformSleepSpace;
import nape.phys.Body;
import nape.phys.PhysObj;
import nape.phys.Material;
import nape.util.Tools;
import nape.constraint.PivotJoint;
import nape.constraint.RotaryLimitJoint;
class Main extends Sprite
{
static function main()
{
var main:Main = new Main();
Lib.current.addChild(main);
}
static private var GRAVITY:Vec2 = new Vec2(0, 250);
static private var DELTA:Float = 0.016;
static private var WIDTH:Int = 640;
static private var HEIGHT:Int = 480;
static private var WIDTH_H2:Int =320;
static private var HEIGHT_H2:Int = 240;
private var space:Space;
public function new()
{
super();
space = new UniformSleepSpace(new AABB(0, 0, WIDTH, HEIGHT), 30, GRAVITY); //Физика
createBorder(); //Границы мира
this.graphics.beginFill(0x901010);
this.graphics.drawRect(0, 0, WIDTH, HEIGHT);
this.graphics.endFill();
addEventListener(Event.ENTER_FRAME, update); // Обновить мир
addEventListener(MouseEvent.CLICK, click);
}
private function click(e:Event):Void
{
//куколки
createRagdollBySprite(space, this, new Vec2(mouseX, mouseY), new CRagdoll(),(Math.random()>0.9 ? true : false));
}
private function update(e:Event):Void
{
space.step(DELTA);
}
private function createBorder():Void
{
var p:PhysObj;
space.addObject(p = Tools.createBox(-20, HEIGHT_H2, 50, HEIGHT, 0, 0, 0, true, Material.Wood));
addChild(p.graphic);
space.addObject(p = Tools.createBox(WIDTH +20, HEIGHT_H2, 50, HEIGHT, 0, 0, 0, true, Material.Wood));
addChild(p.graphic);
space.addObject(p = Tools.createBox(WIDTH_H2, -20, WIDTH, 50, 0, 0, 0, true, Material.Wood));
addChild(p.graphic);
space.addObject(p = Tools.createBox(WIDTH_H2, HEIGHT + 20, WIDTH, 50, 0, 0, 0, true, Material.Wood));
addChild(p.graphic);
}
//вспомогательные функции для работы с физикой
static private var G2R:Float = 0.017453292519; // Math.PI / 180;
static private var R2G:Float = 57.295779514719; // 180 / Math.PI;
static public inline function createBoxBySprite(space:Space,render:Sprite, pos:Vec2, sprite:Sprite,material:Material, isStatic:Bool, ?data:Dynamic,?collision=0xffffffff):PhysObj
{
if (sprite!=null)
{
var pobj:PhysObj;
pobj = Tools.createBox(0, 0, sprite.width , sprite.height , 0, 0, 0, isStatic, material,collision);
pobj.setPos(pos.px + sprite.x, pos.py + sprite.y, G2R * sprite.rotation);
pobj.assignGraphic(sprite);
pobj.data = data;
if(isStatic) pobj.body.stopAll();
pobj.body.update();
space.addObject(pobj);
render.addChild(pobj.graphic);
return pobj;
}
else return null;
}
static public inline function createBoxByChild(space:Space, render:Sprite, pos:Vec2, parent:Sprite, name:String, material:Material, isStatic:Bool, ?data:Dynamic,?collision=0xffffffff):PhysObj
{
var child:DisplayObject = parent.getChildByName(name);
if (child!=null)
{
var point:Point = child.localToGlobal(new Point());
// parent.removeChild(point);
child.x = point.x-parent.x;
child.y = point.y-parent.y;
child.rotation = parent.rotation;
return createBoxBySprite(space, render, pos, cast(child,Sprite), material, isStatic, data,collision);
}
else return null;
}
static public inline function createPivotJointByChild(space:Space,body1:PhysObj,body2:PhysObj, pos:Vec2,breakable:Bool,maxForce:Float, parent:Sprite,name:String):PivotJoint
{
var child:DisplayObject = parent.getChildByName(name);
if (child!=null)
{
var sumPos:Vec2 = pos.clone();
sumPos.px += child.x;
sumPos.py += child.y;
return createPivotJoint(space, body1, body2, sumPos,breakable,maxForce);
}
else return null;
}
static public inline function createPivotJoint(space:Space, obj1:PhysObj, obj2:PhysObj, pos:Vec2, ?breakable:Bool=false, ?maxForce:Float=1600000):PivotJoint
{
if (obj1 == null || obj2 == null) return null;
else
{
var p:PivotJoint = new PivotJoint(obj1, obj2, pos);
p.breakable = breakable;
if (breakable) p.maxForce = maxForce;
p.biasCoef = 0.5;
p.ignore = true;
space.addConstraint(p);
return p;
}
}
static public inline function createRotaryLimitJoint(space:Space, obj1:PhysObj, obj2:PhysObj, min:Float, max:Float,?breakable:Bool=false,?maxForce:Float=2000000):RotaryLimitJoint
{
if (obj1 == null || obj2 == null) return null;
else
{
var p:RotaryLimitJoint = new RotaryLimitJoint(obj1, obj2, min, max);
p.breakable = breakable;
if (breakable) p.maxForce = maxForce;
p.biasCoef = 0.5;
p.ignore = true;
space.addConstraint(p);
return p;
}
}
static public inline function createRagdollBySprite(space:Space, render:Sprite,pos:Vec2, sprite:Sprite, ?isbreak:Bool=false):Void
{
var head:PhysObj;
var body:PhysObj;
var leftfoot:PhysObj;
var rightfoot:PhysObj;
var lefthand:PhysObj;
var righthand:PhysObj;
var material:Material = Material.Wood;
// # bodyes
leftfoot = createBoxByChild(space, render, pos, sprite, 'foot_left', material,false,null,1);
rightfoot = createBoxByChild(space, render, pos, sprite, 'foot_right',material,false,null,2);
body = createBoxByChild(space, render, pos, sprite, 'body', material,false,null,4);
head = createBoxByChild(space, render, pos, sprite, 'head', material,false,null,8);
lefthand = createBoxByChild(space, render, pos, sprite, 'hand_left', material,false,null,16);
righthand = createBoxByChild(space, render, pos, sprite, 'hand_right',material,false,null,32);
// # pivot joints
createPivotJointByChild(space, head, body, pos, isbreak, 1600000, sprite, 'joint_head');
createPivotJointByChild(space, lefthand, body, pos, isbreak, 1600000, sprite, 'joint_hand_left');
createPivotJointByChild(space, righthand, body, pos, isbreak, 1600000, sprite, 'joint_hand_right');
createPivotJointByChild(space, leftfoot, body, pos, isbreak, 1600000, sprite, 'joint_foot_left');
createPivotJointByChild(space, rightfoot, body, pos, isbreak, 1600000, sprite, 'joint_foot_right');
// # rotary limits
createRotaryLimitJoint(space, lefthand, body, -0.45, 0.45, isbreak);
createRotaryLimitJoint(space, head, body, -0.45, 0.45, isbreak);
createRotaryLimitJoint(space, righthand,body, -0.45, 0.45, isbreak);
createRotaryLimitJoint(space, leftfoot, body, -0.25, 0.25, isbreak);
createRotaryLimitJoint(space, rightfoot,body, -0.25, 0.25, isbreak);
}
}
П.С. постарался исправить все ошибки и опечатки.
- +12
- horror812
Комментарии (22)
по ссылки с исходниками?
может с фолдора ifolder.ru/19844036
у одного из 10…
эта я показать, что в напе легко сделать разрушаемые лжойтны,
пс тоя я и не поню может в боксе также (
Там если джойн сильно натянуть (в зависимости от параметров)
— он порвется.
А в боксе не помню, есть ли такое)
Я же писал про.
к примеру, регдол сильно ударить или упал с большой высоты — конечность то сама оторвется — это удобненько)
Я заполнил весь экран рэгдоллами, а он даже подтормаживать не начал!
Там сейчас, к примеру, несколько куколок коллизится так
голова с голвой
туловище с туловищем
нога с ного и тп)
Я так сделал в свойе игре… забыл убрать
спасибо и +1!
Хотя вот моя старая статья… может пригодится комунибудь…
habrahabr.ru/blogs/Flash_Platform/104176/
Тоже публикуй.
Я же, не сравнивал с боксом.
Я хотел показать, как я беру части из нарисованного sprit'а
и у меня код на хаксе.
а зачем ты спрайт, каждый раз двигаешь, ведь в Напе
нужно просто ФизическиеОбъект.assignGraphics… — это удобней.
ну и так есть замечания) публикуй в комментах напишу.
ТОварищи, а что хакс вот прям такой весь удобный, ьыстрый и крутой по-сравнению с ас3?
Хотя я вот уже планирую вернуться или на ас3 или попробовать, что-то еще.
Хакс — хорош, но нет никаких движух в коммуните, да и коммунити очень маленькое.
Сейчас он как морская свинка — и плавает плохо, и скушать мало) имхо.
Ему скорее нехватает актуальной IDE (в том числе под OSX), способ без хитрых манипуляций подключать AS3-код, проектов, написанных на нём и комьюннити, активно его юзающего.
Как минимум стоит его попробовать. Мне понравилось.
fdt.powerflasher.com/docs/Intro_To_haXe_Development_With_FDT
то полностью согласен…
какое-то время сидел в линуксе с эклипсом и флешбилдером.
привыкнуть смог)
и вроде все есть и побольшей части работает, но не так как-то оно — не то…
кстати, да, было бы круто, если можно было бы нормально вставлять ас3-код...))