XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Желтая пресса: обучающие статьи
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

 
NCrashed

offline
Опыт: 13,553
Активность:
vJass Создание moving system

Введение



Эта статья расскажет об основных приемах создания систем движений (или «moving systems») с использованием возможностей vJass, о правильной организации таких систем и способов их оптимизации. Статья пригодится как новичкам в vJass, так и опытным пользователям. Перед освоением этого материала рекомендуется прочитать статьи «Осваиваем jass»,«Осваиваем JASS - исправления и дополнения» , «Математический подход к движению».

Инструменты


  1. Jass New Gen Pack (далее JNGP) – удобная надстройка над стандартным редактором, имеет встроенный компилятор vJass’а и подсветку кода. Скачать можно в разделе «Утилиты». Проверьте, чтобы пути до карты были английские. Обязательно снимите галочку «Reinventing the Craft-> Enable Reinventing the Craft» (от него только проблем больше =) ).
  2. Прямые руки


Краткий курс теории



Не будем загружать мозги пользователю лишней информацией, но все-таки кое-что знать надо.

Два основных способа описания движения



В геометрии существую два основных направления:
  1. Классический
  2. Векторный

Оба направления имеют свои недостатки и преимущества. В этой статье мы будем оперировать векторами, так как векторная геометрия позволяет просто и понятно реализовать движение в пространстве и добавить правдоподобности движению (так как физика и так является «векторной» наукой )

DEAD URL

Знакомьтесь, это вектор! Это основное понятие стереометрии, но объяснить его можно так: «направленный отрезок». У каждого вектора есть свои координаты, которые можно найти по формуле a={Bx-Ax, By-Ay, Bz-Az}.
Чтобы определить длину вектора можно воспользоваться такой формулой:
|a| = Sqrt( ax^2 + bx^2 + bz^2)
Еще нам понадобится операция «нормирования вектора», то есть установка единичной длины:
a={ax/|a|, ay/|a|, az/|a|}
Вектора можно складывать, вычитать, умножать на число или на другой вектор (об этом по мере необходимости).
Но, однако, координаты вектора не определяют его положения в пространстве, нужна еще точка, из которой он выходит:


DEAD URL


Теперь мы обладаем инструментом, с помощью которого можем попасть в любую точку пространства, получаем универсальную систему уравнений:
Код:
X = Ax + ax
    Y = Ay + ay
    Z = Az + az

Правда, все легко и просто? Именно на этом ките держится вся стереометрия, не точка, а именно вектор (точку вообще можно представить как вектор, исходящий из начала координат в эту точку).

Принципы ООП (объектно ориентированного программирования )



Для правильного понимания что такое структура, обратимся к некой "эволюционной цепочке": переменная->массивы->записи->объекты
Переменные появились очень давно, предназначаются для хранения информации одного типа.
Массивы появились, когда появилась необходимость хранить несколько переменных одного типа.
Записи придумали, когда нужно было хранить одновременно несколько переменных разных типов, например, с помощью записей легко создать телефонный справочник (1 запись: имя абонента и его телефон, потом записи хранят в 1 массиве).
Наконец, объекты - это объединение записей (связки переменных) и функций, которые обрабатывают эти переменные. В итоге мы получили переменную-объект, которая максимально изолирована и может существовать сама по себе (+еще функционировать).
В vJass структуры - имитация объектов. У них есть и разносортные переменные и функции, которые обрабатывают эти переменные (они называются методами). Рассмотрим пример:

Код:
struct MyObject // объявление структуры
        integer i = 4 
        real a = 0.42 //Структура может включать в себя любые переменные
        unit array ua [10] // также может включать массивы
        AnotherObject obj // и даже другие объекты
        
        // Объявление метода
        method DoSomething takes nothing returns noting
            // чтобы обратиться к переменным выше, нужно воспользоваться
            // переменной this, которая независимо сколько аргументов передано методу
            // будет тоже "тайно" передана, пример использования
            this.i = 9 // мы только что изменили параметр i объекта, который описан выше
        endmethod

    endstruct

Но как теперь использовать структуру?

Код:
function MyFuntion takes nothing returns nothing
        local MyObject b = MyObject.create() // так создается структура
        
        set b.r = 9.81 // Таким образом можно обратиться к переменной внутри структуры
        call b.DoSomething() // Так вызывается метод, описанный в структуре    
        
        call b.destroy() // после использования ненужные структуры надо удалять
    endfunction


Но иногда нам не нужно, чтобы в структуру передавалась переменная this, тогда указываем что метод "статичный":

Код:
static method DoSomething takes nothing returns noting
        // теперь компилятор выдаст ошибку, если попробуете использовать this
    endmethod


Статичные методы нужны для альтернативного создания структуры:

Код:
struct MyStruct
        trigger tr
        
        static method CreateIni takes nothing returns MyStruct
            local MyStruct st = MyStruct.create()
                set st.tr = CreateTrigger()
                call TriggerAddAction(tr, function SomeFunc)
            return st
        endmethod
    endstruct

    ...
    
    function MyFuntion takes nothing returns nothing
        local MyObject b = MyObject.CreateIni() // теперь вот так можно создать структуру
        // и в ней уже будет инициализирован триггер tr
        
        ...

    endfunction


Иногда необходимо уничтожить еще и структуры или переменные (триггер в нашем примере), которые содержатся внутри структуры (например, вы опишите структуру "точка" и добавите в вектор переменную "point Begin = point.create()"), тогда пишете свой аналог destroy:

Код:
// вар чувствителен к регистру
    // поэтому для него destoy не равно Destroy    
    method Destroy takes nothing returns nothing 
        call this.Begin.destroy() // удаляем точку
    // здесь пишем остальные необходимые действия для полного удаления
        call this.destroy() // и в финале удаляем сам вектор
    endmethod


Первые шаги



Теперь приступим к самому программированию. В vJass добавили возможность создания библиотек – области кода, которые после компиляции будут вставлены выше Custom script карты. Очень полезная вещь, позволяет систему держать в 1 триггере, облегчая импорт вашей наработки.
Удаляем стандартную инициализацию и создаеме триггер «MovingSys», дальше «Правка->Конвертировать в текст», удаляем весь текст из триггера и пишем:

Код:
library MoveSys

endlibrary


Вот и создали библиотеку, теперь нам надо описать вектор.
Вектору необходимы 3 переменные для его координат:

Код:
library MoveSys

struct vector
    real x
    real y 
    real z
endstruct

endlibrary


Теперь добавим методы (те самые функции) для операций над вектором:

Код:
library MoveSys

struct vector
    real x
    real y 
    real z
    // В метод передается еще переменная this, которая позволяет обращаться к собственным переменным
    // пример this.x = 0 
    // Если поставить перед методом "static", то в метод не передастся переменная this
    static method GetFrom2Locs takes real ax,real ay,real az,real bx,real by,real bz returns vector
        local vector v = vector.create() // таким образом создается вектор
            // заполняем переменные, созданного вектора
            set v.x = bx-ax
            set v.y = by-ay
            set v.z = bz-az
            // Возращаем вектор, теперь, чтобы создать вектор можно написать vector.GetFrom2Locs(...)
            return v
    endmethod
    // Сумма векторов, допустим у вас есть 2 вектора - a.Summ(b,1) сложит их
    method Summ takes vector a returns nothing
        set this.x = this.x + a.x
        set this.y = this.y + a.y
        set this.z = this.z + a.z
    endmethod  
    // умножает вектор на число
    // пример a.Multiply(2) умножит вектор а на 2
    method Multiply takes real k returns nothing
        set this.x = k*this.x
        set this.y = k*this.y 
        set this.z = k*this.z 
    endmethod
    // Вычисляет длину вектора
    method Module takes nothing returns real
        return SquareRoot(this.x*this.x+this.y*this.y+this.z*this.z)
    endmethod
    // Нормирование ветора
    method Norm takes nothing returns nothing
    local real m = SquareRoot(this.x*this.x+this.y*this.y+this.z*this.z)
        set this.x = this.x/m
        set this.y = this.y/m
        set this.z = this.z/m
    endmethod
endstruct

endlibrary


Поздравляю, первый «кит» системы готов! Теперь обратим свой взор на объекты движения. Двигать мы будем юнитов, и чтобы к ним привязать векторы скорости, ускорения и силы, создадим еще одну структуру:

Код:
// Обзовем новую структуру "телом"
struct body
    unit u // Его будем двигать
    real m // масса юнита
    vector v // вектор скорость
    vector a // ускорение
    vector f // сила, приложенная к телу
    // метод создания тела с инициализированием переменных
    // пример создания тела: local body b = body.Create(unit,mass)
    // не путай с  body.create() это разные функции
    static method Create takes unit u, real mass returns body
        local body b = body.create()
            set b.u = u
            set b.m = mass
            set b.v = vector.create()
            set b.a = vector.create()
            set b.f = vector.create()
            // Это нужно для изменения координаты z
            call UnitAddAbility(u,'Amrf')
            call UnitRemoveAbility(u,'Amrf')  
        return b
    endmethod
    // уничтожение тела, когда оно больше не нужно
    method Destroy takes nothing returns nothing
        call this.v.destroy()
        call this.a.destroy()
        call this.f.destroy()
        call this.destroy()
    endmethod
endstruct


Основная часть движка



Теперь остался последний кит – сам цикл движения. Есть два способа двигать тело: обсчитывать координаты, а потом перемещать юнита в точку с этими координатами; брать за основу координаты юнита и перемещать относительно них. Может быть, вам не видно разницы между этими способами? Тогда приведу примеры:

Код:
set x = …
set y = …
set z = …
call SetUnitX(u,x)
call SetUnitY(u,y)
call SetUnitFlyHeight(u,z,0)


Это пример первого способа. Все вычисления производятся вне нативных функций, при этом не учитываются «желания» юнита передвигаться, поэтому придется делать еще триггер сброса приказа (или добавлять способность москитов), так как при попытке бежать юнит будет дергаться.
Код:
call SetUnitX(u,GetUnitX(u)+dx)
call SetUnitY(u, GetUnitY(u)+dy)
call SetUnitFlyHeight(u, GetUnitFlyHeight(u)+dz,0)


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

Создаем массив тел, по которому будет бегать цикл:
Код:
globals
    body array mvs_Sb [1000]
    integer mvs_si = -1 // при первой записи, элемент запишется в ячейку 0
endglobals


Теперь создадим функцию, которая нам запустит систему:
Код:
library MoveSys initializer IniMove // Здесь объявляется функция-инициализатор

…

private function Engine takes nothing returns nothing

endfunction

function IniMove takes nothing returns nothing
        // нам таймер в глобалку сохранять незачем, так как он работает всю игру
        // период 0.025 выбран в результате практики, при 0.05 видны "рывки"
        call TimerStart(CreateTimer(), 0.025, true, function Engine)
endfunction

endlibrary


Пора наполнить содержанием функцию «Engine»:
Код:
private function Engine takes nothing returns nothing
    local integer i = 0
    local body b
    loop
        exitwhen i > mvs_si
            if mvs_Sb[i] != 0 then
                set b = mvs_Sb[i] // для читаемости кода
                // 
                // Считаем ускорение тела и обнуляем силу, чтобы она не накапливалась
        if b.m > 0 then  //  для защиты системы от деления на нуль
                    set b.a.x = b.f.x/b.m
            set b.a.y = b.f.y/b.m
                    set b.a.z = b.f.z/b.m
        endif
                set b.f.x = 0
                set b.f.y = 0
                set b.f.z = 0
                // Теперь считаем скорость и перерасчитываем ее при изменении координат в точка/с
                set b.v.x = b.v.x + b.a.x
                set b.v.y = b.v.y + b.a.y
                set b.v.z = b.v.z + b.a.z
                // Финальная часть - передвигаем юнит
                call SetUnitX(b.u, GetUnitX(b.u) + b.v.x*0.025)
                call SetUnitY(b.u, GetUnitY(b.u) + b.v.y*0.025)
                call SetUnitFlyHeight(b.u, GetUnitFlyHeight(b.u) + b.v.z*0.025,0)
            else // Опа! Нашли удаленный с помощью body.Remove() элемент массива. Приговор: удалить и закрыть дырку последним элементом.
                set mvs_Sb[i] = mvs_Sb[mvs_si]
                set mvs_Sb[mvs_si] = 0
                set mvs_si = mvs_si - 1
        set i = i - 1 // иначе тело, которым мы заткнули дырку, не обработается за это прохождение
                //  цикла, то есть пропустит квант времени
            endif
        set i = i + 1
    endloop
endfunction


Последний шаг




Теперь осталось научится добавлять тело в этот стек. Для этого в структуру body добавьте такой метод:


Код:
// Помещаем тело в стек для обработки движком + добавляем защиту от переполнения
    method Start takes nothing returns boolean
      if mvs_si < 1000 then  
        set mvs_si = mvs_si + 1
        set mvs_Sb[mvs_si] = this
        return true
      else
        return false
      endif
    endmethod


Теперь можно создать тело, задать ему начальные параметры и поместить в движок с помощью этого метода.
Последний штрих – сделать пространство объемным. Для этого к z юнита прибавлять разницу высот. Тогда главная часть движка примет вид:

Код:
globals
    body array mvs_Sb [1000]
    integer mvs_si = -1 // при первой записи, элемент запишется в ячейку 0
    location GZL = Location(0,0) 
endglobals

    function GetZ takes real X, real Y returns real        
        call MoveLocation(GZL,X,Y)
        return GetLocationZ(GZL)
    endfunction
    
private function Engine takes nothing returns nothing
    local integer i = 0
    local body b
    loop
        exitwhen i > mvs_si
            if mvs_Sb[i] != 0 then
                set b = mvs_Sb[i] // для читаемости кода
                // 
                // Считаем ускорение тела и обнуляем силу, чтобы она не накапливалась
        if b.m > 0 then  //  для защиты системы от деления на нуль
                    set b.a.x = b.f.x/b.m
            set b.a.y = b.f.y/b.m
                    set b.a.z = b.f.z/b.m
        endif
                set b.f.x = 0
                set b.f.y = 0
                set b.f.z = 0
                // Теперь считаем скорость и перерасчитываем ее при изменении координат в точка/с
                set b.v.x = b.v.x + b.a.x
                set b.v.y = b.v.y + b.a.y
                set b.v.z = b.v.z + b.a.z
                // Добавление разности высот, чтобы сделать мир "объемным"
                call SetUnitFlyHeight(b.u,GetUnitFlyHeight(b.u) - GetZ(GetUnitX(b.u) + b.v.x*0.025,GetUnitY(b.u) + b.v.y*0.025) + GetZ(GetUnitX(b.u),GetUnitY(b.u)),0)
                // Финальная часть - передвигаем юнит
                call SetUnitX(b.u, GetUnitX(b.u) + b.v.x*0.025)
                call SetUnitY(b.u, GetUnitY(b.u) + b.v.y*0.025)
                call SetUnitFlyHeight(b.u, GetUnitFlyHeight(b.u) + b.v.z*0.025,0)
            else // Опа! Нашли удаленный с помощью body.Remove() элемент массива. Приговор: удалить и закрыть дырку последним элементом.
                set mvs_Sb[i] = mvs_Sb[mvs_si]
                set mvs_Sb[mvs_si] = 0
                set mvs_si = mvs_si - 1
        set i = i - 1 // иначе тело, которым мы заткнули дырку, не обработается за это прохождение
                //  цикла, то есть пропустит квант времени
            endif
        set i = i + 1
    endloop
endfunction

function IniMove takes nothing returns nothing
        // нам таймер в глобалку сохранять незачем, так как он работает всю игру
        // периoд 0.025 выбран в результате практики, при 0.05 видны "рывки"
        call TimerStart(CreateTimer(), 0.025, true, function Engine)
endfunction



А в метод уничтожения тела корректируем вот так (при удалении в стеке все равно остается записано тело, точнее integer - номер ячейки где он хранился. ). На самом деле все переменные, ссылающиеся на структуру являются типом integer, который есть номер ячейки массива, в котором вар хранит структуру:


Код:
// уничтожение тела, когда оно больше не нужно
    method Destroy takes nothing returns nothing
    local integer i = 0
        loop // Ищем в массиве движка наше тело и убираем его от туда
            exitwhen i > mvs_si
                if mvs_Sb[i] == this then
                    set mvs_Sb[i] = mvs_Sb[mvs_si]
                    set mvs_Sb[mvs_si] = 0
                    set mvs_si = mvs_si - 1
                    set i = mvs_si // выход из цикла              
                endif
            set i = i + 1
        endloop
    // Удаление вложенных структур
        call this.v.destroy()
        call this.a.destroy()
        call this.f.destroy()
    // Удаление самой структуры
        call this.destroy()
    endmethod


Добавляем физические явления (удар об землю, трение и т.п.)



Теперь создадим отдел параметров системы для удобства настройки:


Код:
library MoveSys initializer IniMove

// Параметры системы, обычно их сюда помещают для удобства настройки системы
// private - переменная будет доступна только внутри библиотеки
globals
    private real g = 14 // Ускорение свободного падения
    private real Rest = 0.4 // Коэффициент восстановления после удара об землю
    private real mu = 0.4 // Коэффициент трения
endglobals

...

endlibrary


Советую всегда при создании систем выносить коэффициенты к заголовку библиотеки и давать пояснительные комментарии к ним. Это поможет разобраться в собственной системе через несколько месяцев.

Теперь удары об землю и границы карты:

Код:
private function Engine takes nothing returns nothing
    local integer i = 0
    local body b
    local real x
    local real y
    loop
        exitwhen i > mvs_si
            if mvs_Sb[i] != 0 then
                set b = mvs_Sb[i] // для читаемости кода
                // Удар об землю
                if GetUnitFlyHeight(b.u) < 2 then
                    if b.v.z < 0 then
                        set b.v.z = - b.v.z*Rest
                    endif
                endif
                // Границы карты
        set x = GetUnitX(b.u)
        set y = GetUnitY(b.u)
                if x < minX then
                    call SetUnitX(b.u,minX)
                elseif x > maxX then
                    call SetUnitX(b.u,maxX)
                endif
                if y < minY then
                    call SetUnitY(b.u,minY)
                elseif y > maxY then
                    call SetUnitY(b.u,maxY)
                endif
                // Считаем ускорение тела и обнуляем силу, чтобы она не накапливалась
                if b.m > 0 then  //  для защиты системы от деления на нуль
                    set b.a.x = b.f.x/b.m
                        set b.a.y = b.f.y/b.m
                    set b.a.z = b.f.z/b.m - g // на этой оси еще действует mg
        endif
        ...
globals
    private real maxX
    private real maxY
    private real minX
    private real minY
endglobasl

function IniMove takes nothing returns nothing
        // нам таймер в глобалку сохранять незачем, так как он работает всю игру
        // периoд 0.025 выбран в результате практики, при 0.05 видны "рывки"
        call TimerStart(CreateTimer(), 0.025, true, function Engine)
    set maxX =  GetRectMaxX(bj_mapInitialPlayableArea) 
    set maxY =  GetRectMaxY(bj_mapInitialPlayableArea) 
    set minX =  GetRectMinX(bj_mapInitialPlayableArea) 
    set minY =  GetRectMinY(bj_mapInitialPlayableArea) 
endfunction



Сейчас добавим сухое трение:
Принцип такой, если на тело действует сила больше mu*(mg-Fz), тогда вычитаем из вектора силы тела силу трения, иначе отнимаем от скорости эту величину деленную на массу:
Код:
private function Engine takes nothing returns nothing
    local integer i = 0
    local body b
    local real x
    local real y
    loop
        exitwhen i > mvs_si
            if mvs_Sb[i] != 0 then
                set b = mvs_Sb[i] // для читаемости кода
                // Удар об землю
                if GetUnitFlyHeight(b.u) < 2 then
                    if b.v.z < 0 then
                        set b.v.z = - b.v.z*Rest
                    endif
                    // Обсчитываем трение
                    if b.m > 0 then
                            if SquareRoot(b.f.x*b.f.x + b.f.y*b.f.y) > mu*(b.m*g - b.f.z) then // силы трения недостаточно, чтобы останавливать тело
                                set b.f.x = b.f.x - b.f.x*mu*(b.m*g - b.f.z)/b.f.Module()
                                set b.f.y = b.f.y - b.f.y*mu*(b.m*g - b.f.z)/b.f.Module() 
                            elseif SquareRoot(b.v.x*b.v.x + b.v.y*b.v.y) < RAbsBJ(mu*(b.m*g - b.f.z))/b.m then // остановка тела
                                    set b.v.x = 0
                                    set b.v.y = 0
                            else // отнимаем от скорости
                                    if RAbsBJ(b.v.x) > 0 then
                                        set b.v.x = b.v.x - b.v.x*mu*(b.m*g - b.f.z)/(b.v.Module()*b.m)
                                    endif    
                                    if RAbsBJ(b.v.y) > 0 then
                                        set b.v.y = b.v.y - b.v.y*mu*(b.m*g - b.f.z)/(b.v.Module()*b.m)
                                    endif
                            endif
                    endif
                endif
                // Границы карты
        set x = GetUnitX(b.u)
        set y = GetUnitY(b.u)
                if x < minX then
                    call SetUnitX(b.u,minX)
                elseif x > maxX then
                    call SetUnitX(b.u,maxX)
                endif
                if y < minY then
                    call SetUnitY(b.u,minY)
                elseif y > maxY then
                    call SetUnitY(b.u,maxY)
                endif
        ...


Заключение




Скелет системы готов, теперь на него можно наращивать остальные части, например: притяжение к земле, трение, столкновения с другими телами. В карте примере находится эта система, но уже с сухим трением и притяжением к земле. Для примера я сделал на основе этой системы спелл «Прыжок», чтобы показать систему в действии. Теперь, освоив эту статью, вы можете легко делать реалистичные заклинания. Идеи черпал из моей физической библиотеки «Fisics Dynamik System», по сути, это та же система, но усложненная.

P.S. Это моя первая статья, так что сильно не бить =), но критику излагать в полном объеме.
Прикрепленные файлы
Тип файла: w3x MoveSys.w3x (28.1 Кбайт, 588 просмотров )

Отредактировано NCrashed, 08.10.2009 в 23:32.
Старый 06.09.2009, 19:56
Daemonik

offline
Опыт: 5,084
Активность:
Статья супер! Все разжеванно, все предельно понятно и ясно. К тому же с этого можно начать знакомство с vJass.
ИМХО. Одна из самых понятных статей. Понять сможет любой новичок хоть чуть-чуть знакомый с векторами.
Старый 06.09.2009, 20:51
NCrashed

offline
Опыт: 13,553
Активность:
Уфф... я то думал, что не достаточно разжевал =)
Старый 06.09.2009, 20:54
DragonSpirit
у - уходи
offline
Опыт: 22,625
Активность:
NCrashed, спасибо,статья хорошая,особенно помогает новчкам научиться работать со структурами и методами,имхо зачёт
Старый 06.09.2009, 21:03
Doc

offline
Опыт: 63,163
Активность:
Статья тру мне понравилось, продолжай писать еще)
Старый 06.09.2009, 22:33
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
NCrashed, огромное спасибо! только сейчас понял за чем писать i=i-1 когда удаляем data)
Опа! Нашли "порченный" элемент массива. Приговор: удалить и закрыть дырку последним элементом.
и что представляет собою вектор. бесконечный респект тебе, NCrashed я кстати еще и методы почти понял )
щяс налью чашечку кофе, и внимательно перечитаю.... ыыы завтра школу просплю а на матике как раз про векторы раскажут)) их же в 9 проходят? спасибо еще раз...
Старый 06.09.2009, 22:46
NCrashed

offline
Опыт: 13,553
Активность:
их же в 9 проходят?
с 9того и до конца =) . Очень нужная штука.
Старый 06.09.2009, 22:49
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
ага, спасибо =)
Старый 06.09.2009, 22:52
Garret
Недоброе творится
offline
Опыт: 3,893
Активность:
Не нашёл дестроя структур. Да, в вДжасс на шарю совсем.
Старый 06.09.2009, 23:14
NCrashed

offline
Опыт: 13,553
Активность:
для любой структуры пишешь
<твоя структура>.destroy()
И она удалится, но иногда необходимо уничтожить еще и структуры, которые содержатся внутри структуры, тогда пишешь свой аналог, например в статье создан для тела метод:
    method Destroy takes nothing returns nothing
        call this.v.destroy()
        call this.a.destroy()
        call this.f.destroy()
        call this.destroy()
    endmethod
NCrashed добавил:
Сейчас добавлю это в статью
NCrashed добавил:
Да, в вДжасс не шарю совсем
Вот и шанс понять хоть немного, и я когда-то не шарил в джаззе вовсе
Старый 06.09.2009, 23:25
Garret
Недоброе творится
offline
Опыт: 3,893
Активность:
NCrashed:
Вот и шанс понять хоть немного, и я когда-то не шарил в джаззе вовсе
Спасибо конечно, но нахрен не надо
Я просто указываю на те моменты, которые можно улучшить для новичков. Если описываются всякие добавления в массив, то можно (скорее нужно) показать, что мы будем делать для его убирания из массива. На данный момент я вижу только какие-то "порченные элементы" - мне мало понятно, а совсем новичкам тем более.
Старый 06.09.2009, 23:33
NCrashed

offline
Опыт: 13,553
Активность:
Ну так бы сразу и сказал. Поправим
NCrashed добавил:
Исправил. Статью совсем новички не смогут понять, сначала нужно освоить обычный джазз.
Старый 06.09.2009, 23:39
Garret
Недоброе творится
offline
Опыт: 3,893
Активность:
Есть такая штука, как onDestroy. По мне удобнее, чем писать "заменяющий" метод. Оставляю на усмотрение автора.
З.Ы. завтра приду проверю ещё одну весчь, есть сомнения
Старый 06.09.2009, 23:45
NCrashed

offline
Опыт: 13,553
Активность:
для onDestroy создается триггер, отлавливающий это событие, да и ADOLF упомянул что им пользоваться нежелательно. Быстрее работает заменяющий метод.
NCrashed добавил:
Добавлен раздел о принципах ооп, все что используется в статье от ооп попытался тщательно разжевать.
Старый 07.09.2009, 00:37
truth troll
Silenced by truth troll
offline
Опыт: 7,396
Активность:
NCrashed, Ну ты тип О_о тебе череп не жмёт? ( это комплимент =))) )
Старый 07.09.2009, 09:15
Sebra

offline
Опыт: 5,603
Активность:
Статья, оно, конечно, дело хорошее. Но кое-что надо исправить!
  1. Методы векторов пишешь, но не используешь. Понятно, что так быстрее, но это обучающая статья.
  2. Защита от нулевой массы отвратительно сделана. Либо отсечка при создании тела, либо игнорирование силы в саамом движке. Вдруг кто-то захочет сделать тело массой -0,001...
  3. Если движок находит удалённое тело, то передвинутое для заполнения дырки пропустит квант времени.
  4. Не используется 0 элемент массива.
  5. Не отслеживается падение на землю, но это уже мелочь.
В целом статья хорошая, исправляй.
Старый 07.09.2009, 12:47
adic3x

offline
Опыт: 108,439
Активность:
body array mvs_Stek
улыбнуло... мб таки stack?
ооп в вЖасс реализации будут медленее по производительности
использованный метод хранения стеком являться не может, т.к. нарушает его главный принцип - достаем первым то, что положили последним
а статейка интересная, новичкам будет полезно
да и ADOLF упомянул что им пользоваться нежелательно
я вообще противник ооп (в вЖасс реализации, ибо она достаточно черезжопаня)
просто тут мы имеем дело с так называемым "узким местом"
карта пример уныленькая таки, да
код мона заоптимизить очень и очень, это так, к слову...
Старый 07.09.2009, 13:41
NCrashed

offline
Опыт: 13,553
Активность:
Методы векторов пишешь, но не используешь. Понятно, что так быстрее, но это обучающая статья.
В самой системе нет, а вот в примере "прыжок" использует.
Защита от нулевой массы отвратительно сделана. Либо отсечка при создании тела, либо игнорирование силы в саамом движке. Вдруг кто-то захочет сделать тело массой -0,001...
Исправим
body array mvs_Stek
0_o я это написал? Не верю, случайно вышло. Исправлю
использованный метод хранения стеком являться не может, т.к. нарушает его главный принцип - > достаем первым то, что положили последним
В статье не сказано, что это стек, исправлю имя массиву и будет совсем не стек. Я понял, что внушаю новичкам неправильное представление о стеке)
карта пример уныленькая таки
Это же карта пример, она не обязана быть веселой
код мона заоптимизить очень и очень
Например? Очень-очень не надо, ибо чрезмерная оптимизация здесь вредит пониманию материала
Если движок находит удалённое тело, то передвинутое для заполнения дырки пропустит квант времени.
Исправим вставкой строки "set i = i - 1"
Не используется 0 элемент массива.
Ну решил я не путать народ и начать с 1 ячейки.
Не отслеживается падение на землю, но это уже мелочь.
В карте-примере отслеживаются и границы карты

Отредактировано NCrashed, 07.09.2009 в 21:37.
Старый 07.09.2009, 19:45
TYRans_ShaRhy
Welcome to the World
offline
Опыт: 4,653
Активность:
Полезно, даже очень полезно...
Старый 07.09.2009, 21:31
XOR

offline
Опыт: 38,159
Активность:
Круто.. Очень Полезно) на фсгуи джона потянет
Старый 07.09.2009, 21:47

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 03:11.