/* <behavior jsname="behavior_moveBetweenPoints" description="Move scene node between 2 points"> <property name="EndPoint" type="vect3d" default="100.0, 100.0, 100.0" /> <property name="Speed" type="float" default="0.02" /> </behavior>*/behavior_moveBetweenPoints = function(){ this.LastTime = null; this.StartPoint = null;};// вызывается каждый кадр. // 'node' - это узел сцены, к которому привязано это поведение.// 'timeMs' - текущее время сцены в миллисекундах.// Возвращает'true' (истина), если что-то изменилось, и 'false' (ложь), если нет.behavior_moveBetweenPoints.prototype.onAnimate = function(node, timeMs){ // получаем время последнего кадра if (this.LastTime == null) { // мы раньше не вызывали функцию, поэтому сохраним время и отменим this.LastTime = timeMs; this.StartPoint = ccbGetSceneNodeProperty(node, 'Position'); return false; } var delta = timeMs - this.LastTime; this.LastTime = timeMs; if (delta > 200) delta = 200; // не позволяем перемещений дольше 200 миллисекунд // перемещение var pos = ccbGetSceneNodeProperty(node, 'Position'); var movementVector = this.EndPoint.substract(this.StartPoint); if (pos.substract(this.StartPoint).getLength() > movementVector.getLength()) { // достигнута конечная точка, переключаем направление и перезапускаем var tmp = this.StartPoint; this.StartPoint = this.EndPoint; this.EndPoint = tmp; movementVector = this.EndPoint.substract(this.StartPoint); } // перемещение movementVector.normalize(); pos.x += movementVector.x * delta * this.Speed; pos.y += movementVector.y * delta * this.Speed; pos.z += movementVector.z * delta * this.Speed; // устанавливаем новую позицию ccbSetSceneNodeProperty(node, 'Position', pos); return true;}
behavior_moveBetweenPoints = function(){ this.LastTime = null; this.StartPoint = null;};
behavior_moveBetweenPoints.prototype.onAnimate = function(node, timeMs){ ...}
// параметры: клавиша: код клавиши которая нажата или отпущена // нажатие: true (истина) если клавиша нажата, false (ложь) если отпущенаbehavior_moveBetweenPoints.prototype.onKeyEvent = function(key, pressed){ if (key == 32) // клавиша 'Пробел' { if (pressed) this.Speed = 0.02; else this.Speed = 0.0; }}
// mouseEvent (событие мыши): 0=мышь движется, 1=движется колёсико мыши, 2=левая кнопка мыши отпущена,// 3=левая кнопка мыши нажата, 4=правая кнопка мыши отпущена, 5=правая кнопка мыши нажатаbehavior_moveBetweenPoints.prototype.onMouseEvent = function(mouseEvent, mouseWheelDelta){ // здесь обработка событий мыши }
// используем текущий выбранный в редакторе узел var meshnode = editorGetSelectedSceneNode(); var bufferCount = ccbGetSceneNodeMeshBufferCount(meshnode);if (bufferCount == 0) alert('The selected node has no 3D geometry.');else{ // получаем старую текстуру этого узла var oldTexture = ccbGetSceneNodeMaterialProperty(meshnode, 0, "Texture1"); // удаляем все буферы меша, содержащие геометрию, потому что мы хотим заменить ее совершенно новой геометрией for (var i=0; i<bufferCount; ++i) ccbRemoveMeshBuffer(meshnode, 0); // добавляем новый буфер ccbAddMeshBuffer(meshnode); // отключаем динамическое освещение и устанавливаем текстуру ccbSetSceneNodeMaterialProperty(meshnode, 0, 'Lighting', false); ccbSetSceneNodeMaterialProperty(meshnode, 0, "Texture1", oldTexture); // добавляем 4 вершины ccbAddMeshBufferVertex(meshnode, 0, new vector3d(0,10,0)); ccbAddMeshBufferVertex(meshnode, 0, new vector3d(10,10,0)); ccbAddMeshBufferVertex(meshnode, 0, new vector3d(0,0,0)); ccbAddMeshBufferVertex(meshnode, 0, new vector3d(10,0,0)); // назначаем цвета вершинам ccbSetMeshBufferVertexColor(meshnode, 0, 0, 0x77400000); ccbSetMeshBufferVertexColor(meshnode, 0, 1, 0x77400000); ccbSetMeshBufferVertexColor(meshnode, 0, 2, 0x77400000); ccbSetMeshBufferVertexColor(meshnode, 0, 3, 0x77400000); // устанавливаем текстурные координаты ccbSetMeshBufferVertexTextureCoord(meshnode, 0, 0, new vector3d(0,1,0)); ccbSetMeshBufferVertexTextureCoord(meshnode, 0, 1, new vector3d(1,1,0)); ccbSetMeshBufferVertexTextureCoord(meshnode, 0, 2, new vector3d(0,0,0)); ccbSetMeshBufferVertexTextureCoord(meshnode, 0, 3, new vector3d(1,0,0)); // Добавляем 6 индексов, чтобы создать из них 2 треугольника. // Обратите внимание, что порядок вершин по часовой стрелке важен. // Если вы добавляете индексы 0,1,2, то вы создаете треугольник обращенный к вам лицевой стороной, // если вы добавите 0,2,1, то он будет смотреть в противоположном направлении. ccbAddMeshBufferIndex(meshnode, 0, 0); ccbAddMeshBufferIndex(meshnode, 0, 1); ccbAddMeshBufferIndex(meshnode, 0, 2); ccbAddMeshBufferIndex(meshnode, 0, 1); ccbAddMeshBufferIndex(meshnode, 0, 3); ccbAddMeshBufferIndex(meshnode, 0, 2); // обновляем габаритный прямоугольник узла ccbUpdateSceneNodeBoundingBox(meshnode);}
Самым простым дополнением CopperCube, является программирование сценария действия.
Если вы перезапустите CopperCube, то будет доступно новое действие с именем «Move Position».
Поскольку мы изменили код JavaScript, чтобы использовать свойство 'MoveWhat' «Что двигать» для изменения положения узла сцены, теперь вам нужно выбрать узел сцены в свойстве 'MoveWhat', на который следует повлиять.
Что такое "Действие", и что такое "Поведение", и чем они отличаются?
CopperCube включает в себя несколько поведений и действий, которые могут быть добавлены к любому трехмерному и двумерному объекту в сцене. Благодаря этому, возможно не только анимировать трехмерные объекты, но и добавить интерактивность вашему трехмерному приложению: реагирование на нажатия клавиш и кнопок, воспроизведение звуков или даже создание игровых персонажей, контролируемых искусственным ителлектом (AI).
CopperCube включает в себя несколько действий, которые могут быть вызваны поведением и другими действиями. С их помощью можно не только анимировать трехмерные объекты, но и добавить интерактивность вашему трехмерному приложению: реагирование на нажатия клавиш и кнопок, воспроизведение звуков или даже создание игровых персонажей, контролируемых ИИ.
Походу, действия - это более простые расширения CopperCube, чем более комплексные поведения.
В конструкторе мы инициализируем две переменные, которые нам понадобятся позже: вторая - это значение времени, когда поведение было запущено, чтобы мы могли плавно перемещать куб, независимо от текущей частоты кадров, и первая - это точка узла сцены, к которому привязано данное поведение, в данном случае куб.
Мы используем это, чтобы иметь возможность плавно перемещать куб: каждый раз мы сохраняем текущее время в которое вызвали функцию, чтобы рассчитать разницу во времени между этим и последним вызовом, и соответствующим образом переместить узел сцены.
ЦитироватьВ конструкторе мы инициализируем две переменные, которые нам понадобятся позже: вторая - это значение времени, когда поведение было запущено, чтобы мы могли плавно перемещать куб, независимо от текущей частоты кадров, и первая - это точка узла сцены, к которому привязано данное поведение, в данном случае куб.В конструкторе мы инициализируем две переменные, которые нам понадобятся позже: this.LastTime - значение времени последнего раза, когда это поведение было выполнено, чтобы мы могли плавно перемещать куб независимо от текущей частоты кадров, и this.StartPoint - начальное положение узла сцены, к которому привязано данное поведение, в данном случае куба.
ЦитироватьПоходу, действия - это более простые расширения CopperCube, чем более комплексные поведения.Ну, ладно, пока будем так считать.
Поведения - это настраиваемые «способности», которые вы прикрепляете к типам актеров или сценам. Вместе они составляют «мозги» игры, обрабатывая все взаимодействия, происходящие в игровом мире.
// регистрируем события клавиатурыccbRegisterKeyDownEvent("keyPressedDown");function keyPressedDown(keyCode){ if (keyCode == 88) { // пользователь нажимает клавишу 'X', и тем самым, немного перемещает узел 'cubeMesh1' var cube = ccbGetSceneNodeFromName("cubeMesh1"); var pos3d = ccbGetSceneNodeProperty(cube, "Position"); pos3d.y += 2; ccbSetSceneNodeProperty(cube, "Position", pos3d); }}
// регистрируем событие рисованияccbRegisterOnFrameEvent("onFrameDrawing");function onFrameDrawing(){ var mouseX = ccbGetMousePosX(); var mouseY = ccbGetMousePosY(); // test collision var cube1 = ccbGetSceneNodeFromName("cubeMesh1"); var cube2 = ccbGetSceneNodeFromName("cubeMesh2"); var endPoint3d = ccbGet3DPosFrom2DPos(mouseX, mouseY); var startPos3D = ccbGetSceneNodeProperty(ccbGetActiveCamera(), "Position"); var cube1Hovered = ccbDoesLineCollideWithBoundingBoxOfSceneNode(cube1, startPos3D.x, startPos3D.y, startPos3D.z, endPoint3d.x, endPoint3d.y, endPoint3d.z); var cube2Hovered = ccbDoesLineCollideWithBoundingBoxOfSceneNode(cube2, startPos3D.x, startPos3D.y, startPos3D.z, endPoint3d.x, endPoint3d.y, endPoint3d.z); ccbSetSceneNodeMaterialProperty(cube1, 0, "Wireframe", cube1Hovered); ccbSetSceneNodeMaterialProperty(cube2, 0, "Wireframe", cube2Hovered);}
Опубликуйте его как файл Windows (.exe) (или Mac OS X (.app)), используя 'Tools -> Test as Windows Application' или 'File -> Publish -> Publish as Windows Application', «Инструменты -> Тестировать как приложение Windows» или «Файл -> Опубликовать -> Опубликовать как приложение Windows».
Теперь создайте пустой текстовый файл, в том месте где вы сохранили файл test.ccb, и назовите его 'test.js'.
Когда вы снова запустите приложение ('Tools -> Test As Windows Application (.exe)' «Инструменты -> Тестировать приложение Windows (.exe)»), куб будет немного перемещаться вверх каждый раз, при нажатии на клавишу 'X'.