Статьи

Бросок в кости с помощью физического движка Jiglib и Away3D

В этом уроке мы построим коробку, в которую можно бросать кости. Для этого мы будем использовать Away3D в качестве 3D-движка и Jiglib в качестве физического движка. Давайте застрять в ..




Как следует из заголовка, сначала мы создадим новый файл ActionScript 3.0.

прочь учебник по flash3d

На панели «Свойства» нажмите кнопку «Изменить».

прочь учебник по flash3d

Выберите профиль Flash Player 9 и нажмите «ОК».

прочь учебник по flash3d

Сохраните ваш файл как «3D Dice.fla» в новой папке под названием «3D Dice». Теперь загрузите движок Away3D с Away3D Downloads . Мы будем использовать версию 2.3.3 для Flash Player 9. Распакуйте архив и скопируйте все папки в папку «3D Dice».

Вам нужно установить программу SVN, чтобы получить эти исходные файлы. Вот адрес SVN. Если вы не хотите иметь дело со всем этим, вы также можете получить их из исходных файлов для этой статьи. После перемещения классов Away3D и Jiglib в папку 3D Dice ваши документы должны выглядеть следующим образом:

прочь учебник по flash3d

Я нарисовал несколько текстур для нашей кости. Конечно, вы можете изменить их, но они неплохие 🙂 Вы можете найти другие текстуры в исходном файле.

Кости Текстуры:

Текстура обучающей программыпрочь учебник Flash3d текстуры
Текстура обучающей программыТекстура обучающей программы
Текстура обучающей программыТекстура обучающей программы

Теперь нам нужно дать им имена связей, чтобы прикрепить их во время выполнения (сделайте это для каждого изображения в вашей библиотеке по одному):

Выберите изображение, затем щелкните правой кнопкой мыши> Свойства

прочь учебник по flash3d

Экспорт для ActionScript> Удалить часть «.png»

прочь учебник по flash3d

ОК, мы готовы начать кодирование. Сначала мы импортируем наши классы:

1
2
3
4
5
import away3d.cameras.*;
import away3d.containers.*;
import away3d.materials.*;
import away3d.primitives.*
import away3d.lights.DirectionalLight3D
1
2
3
4
import jiglib.physics.RigidBody;
import jiglib.plugin.away3d.Away3DPhysics;
import jiglib.plugin.away3d.Away3dMesh;
import jiglib.math.JNumber3D

После импорта наших классов нам нужно определить наши переменные, чтобы использовать их на следующих этапах.

1
2
3
4
5
var scene:Scene3D;
var camera:HoverCamera3D;
var view:View3D;
var light:DirectionalLight3D;
var physics:Away3DPhysics;
1
2
3
4
var boxWidth:Number = 250
var boxHeight:Number = 30
var boxDepth:Number = 250
var boxThickness:Number = 5
1
2
3
4
5
6
var diceTextures:Array = [ new WhiteShadingBitmapMaterial( new diceTexture1(0,0) ),
                           new WhiteShadingBitmapMaterial( new diceTexture2(0,0) ),
                           new WhiteShadingBitmapMaterial( new diceTexture3(0,0) ),
                           new WhiteShadingBitmapMaterial( new diceTexture4(0,0) ),
                           new WhiteShadingBitmapMaterial( new diceTexture5(0,0) ),
                           new WhiteShadingBitmapMaterial( new diceTexture6(0,0) ) ]
1
2
var wallTexture:WhiteShadingBitmapMaterial = new WhiteShadingBitmapMaterial( new walltexture(0,0))
var groundTexture:WhiteShadingBitmapMaterial = new WhiteShadingBitmapMaterial( new groundtexture(0,0))
1
2
3
var diceScale:Number = 30
var dices:Array = new Array()
var diceRandomForce:Number = 50

Как вы уже догадались, первые для Away3D. Имена переменных просты, поэтому вы можете догадаться, для чего они.

DiceTextures содержит текстуры лица костей. Мы берем изображения текстуры кости из библиотеки и помещаем их в WhiteShadingBitmapMaterial. Мы выбираем этот материал, потому что он будет держать свет и для дальнейшего повышения производительности он также будет плоским. WhiteShadingBitmapMaterial — лучшее для наших нужд.

wallTexture и groundTexture используют разные изображения. Использование любого из них в нашем случае выглядело бы ужасно.

Далее нам нужно собрать Away3D.

1
2
function initAway3D():void {
  scene = new Scene3D();
1
2
camera = new HoverCamera3D();
  camera.distance = 300
01
02
03
04
05
06
07
08
09
10
light = new DirectionalLight3D({color:0xFFFFFF, ambient:0.25, diffuse:0.75, specular:0.9})
   scene.addChild(light)
    
   view=new View3D({scene:scene,camera:camera});
   view.x=stage.stageWidth/2;
   view.y=stage.stageHeight/2;
   addChild(view);
     
    physics = new Away3DPhysics(view,4)
}

Первая строка этой функции создает нашу трехмерную сцену, в которую мы добавляем трехмерные объекты. Для камеры выбираем HoverCamera3D. HoverCamera — лучший способ повернуть камеру вокруг объектов. На самом деле вам не нужно использовать свет для этого проекта, но это делает эксперимент классным 🙂 Мы создаем вид и устанавливаем его в середине сцены.

Наконец, мы создаем новую Away3DPhysics. Первый параметр — «View3D», а второй — «сила тяжести» (я использую 4, но если вы хотите, вы можете попробовать другое число).

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function createWalls():void {
    var left:RigidBody = physics.createCube({width:boxThickness, height:boxHeight, depth:boxDepth});
    left.movable = false;
    left.x = -(boxWidth+boxThickness)/2
    Away3dMesh(left.skin).mesh.material = wallTexture
     
    var right:RigidBody = physics.createCube({width:boxThickness, height:boxHeight, depth:boxDepth});
    right.movable = false;
    right.x = (boxWidth+boxThickness)/2
    Away3dMesh(right.skin).mesh.material = wallTexture
     
    var front:RigidBody = physics.createCube({width:boxWidth, height:boxHeight, depth:boxThickness});
    front.movable = false;
    front.z = (boxDepth+boxThickness)/2
    Away3dMesh(front.skin).mesh.material = wallTexture
     
    var back:RigidBody = physics.createCube({width:boxWidth, height:boxHeight, depth:boxThickness});
    back.movable = false;
    back.z = -(boxDepth+boxThickness)/2
    Away3dMesh(back.skin).mesh.material = wallTexture
     
    var ground:RigidBody = physics.createCube({width:boxWidth, height:boxThickness, depth:boxDepth, segmentsW:2, segmentsH:2});
    ground.movable = false;
    ground.y = -(boxHeight+boxThickness)/2
    Away3dMesh(ground.skin).mesh.material = groundTexture
    Away3dMesh(ground.skin).mesh.pushback = true
}

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


Мы используем кубы в качестве стен, но для этого мы используем физику. Создаем куб, вы не можете напрямую устанавливать параметры материала. Плагин Jiglib Away3D не позволяет этого (хотя вы можете изменить файл Away3DPhysics.as, чтобы разрешить его, если хотите). Чтобы изменить материал, нам нужно получить оригинальный объект Away3D:

1
Away3dMesh(rigidObject.skin).mesh

Используя это, мы прикрепляем наши текстуры к граням наших стен. Мы устанавливаем значение «движимое» в «ложь», потому что не хотим, чтобы они перемещались, верно? 🙂 Когда мы создаем землю, мы также устанавливаем для ее свойства pushback значение true, поэтому земля не сможет перепрыгнуть через стены.

01
02
03
04
05
06
07
08
09
10
11
12
function createDice():void {
    var dice:RigidBody = physics.createCube({width:diceScale, height:diceScale, depth:diceScale});
    dice.y=500
    dice.movable=true
    Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.left = diceTextures[0]
    Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.right = diceTextures[1]
    Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.front = diceTextures[2]
    Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.back = diceTextures[3]
    Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.top = diceTextures[4]
    Cube(Away3dMesh(dice.skin).mesh).cubeMaterials.bottom = diceTextures[5]
    dices.push(dice)
}

Как видите, все очень просто. Мы в основном создаем куб и прикрепляем текстуры к его граням. Чтобы прикрепить разные текстуры к разным граням, мы используем cubeMaterials. У cubeMaterials есть 6 свойств, которые мы используем. Эти:

  • фронт
  • назад
  • верх
  • дно
  • осталось
  • право

Вы можете установить для них любой материал, но мы используем элементы diceTextures, которые мы создали на шаге 8.

01
02
03
04
05
06
07
08
09
10
11
function resetOnlyPositions():void {
    for(var i:int = 0; i<dices.length; i++) {
        dices[i].moveTo( new JNumber3D( 0, 100 + i*(diceScale+10) , 0 ) )
    }
}
function resetAllDices(e:MouseEvent):void {
    for(var i:int = 0; i<dices.length; i++) {
        dices[i].moveTo( new JNumber3D( 0, 100 + i*(diceScale+10) , 0 ) )
        addRandomForce(dices[i])
    }
}

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

01
02
03
04
05
06
07
08
09
10
function addRandomForce(rigid:RigidBody) {
     
    var forceX:Number = + Math.random()*( diceRandomForce )
    var forceY:Number = + Math.random()*( diceRandomForce )
    var forceZ:Number = + Math.random()*( diceRandomForce )
     
    rigid.addBodyForce(new JNumber3D(forceX,forceY,forceZ) , new JNumber3D( rigid.x + diceScale ,rigid.y,rigid.z) )
    rigid.addBodyForce(new JNumber3D(-forceX,-forceY,-forceZ) , new JNumber3D(rigid.x — diceScale,rigid.y,rigid.z) )
     
}

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

1
2
3
4
function initListeners():void {
    stage.addEventListener(Event.ENTER_FRAME, render);
    stage.addEventListener(MouseEvent.MOUSE_DOWN,resetAllDices)
}

В этой функции мы добавляем на сцену слушателей MOUSE_DOWN и ENTER_FRAME.

01
02
03
04
05
06
07
08
09
10
11
function render( e:Event ):void {
    view.render();
    camera.targetpanangle = stage.mouseX/stage.stageWidth*360
    camera.targettiltangle = stage.mouseY/stage.stageHeight*30
    camera.hover();
    physics.step();
     
    light.x = camera.x
    light.y = camera.y
    light.z = camera.z
}

Первая строка этой функции визуализирует 3D. Затем мы используем истинную пропорцию в математике, чтобы вращать камеру с помощью позиций мыши. Затем мы выравниваем направление света в соответствии с позициями нашей камеры. Это делает наш свет динамичным и делает наш эксперимент довольно крутым.

1
2
3
4
5
6
initAway3D();
createWalls();
createDice();
createDice();
resetOnlyPositions()
initListeners();

Мы называем наши функции одну за другой. Я дважды вызывал функцию createDice (), поэтому в демонстрационной версии есть 2 кубика. Вы можете добавить сколько угодно.

Ok. Мы готовы. Проверьте свою работу и нажмите на сцену 🙂

В этом уроке мы узнали, как использовать Jiglib с Away3D и построить простой эксперимент.

Надеюсь, вам понравилось, спасибо за чтение!