Четверг, 25.04.2024, 17:13
Under sky of Half-Life
Приветствую Вас Гость | RSS
Главная | Каталог статей | Регистрация | Вход
Меню сайта

Категории каталога
На движке Valve Source [29]
На движке Half-Life 1 [1]

Главная » Статьи » Статьи по мэппингу » На движке Valve Source

Codding, mapping, modelling tutorial

Внимание! В программном коде ошибка которая не позволяет правильно обрабатывать парент-аттачменты к модели. Результат может быть немного иным..

 

В этом туториале я коротко расскажу о работе в разных сферах девелопинга (коддинг, моделинг, скриптование и маппинг), и как с их помощью их сделать такой эффект Mystify (Windows XP Screensaver)

 http://www.youtube.com/watch?feature=player_detailpage&v=0GmC0Iromrw#t=10

 http://www.youtube.com/watch?feature=player_detailpage&v=p-howMhFecQ#t=11s

только не 2D, а 3D (действие по всему объему карты).

План таков:

1) Делаем модельку, которая будет излучать связующие лазеры (по желанию разной толщины, формы и цвета).

2) Кодим модельную энтитю (модель с предыдущего пункта, хотя можно любую взять) которая будет летать по карте и рандомно менять скорость и угол полета отбиваясь от всех предметов.

3) Маппим карту для испытаний, цепляем лазеры к энтите.

 


Приступим.

1) Создание модели

 Создаем в максе модель этого излучателя (к примеру такую. Калечно, но для примера пойдет):

Сферы- излучатели лезаров. Будут двигаться по этим 2-м отрезкам (палочкам)..

Далее делаем 4 (или более) кости для аттачментов (точек, за которые будем цеплять лазеры к модели). Называем LB1, LB2, LB3, LB4. Если у нас будут статические (не движущиеся) лазеры на модели относительно центра модели, то кости и аттачменты делать не нужно. Но я хочу чтобы они анимировали и сдвигались.

Прицепим шары к костям. Берем инструмент Select and link, нажимаем на шар и перетягиваем на кость.

Делаем анимацию для каждой из кости:

Нажимаем Auto key, перетаскиваем ползунок на 50-й слайд, выделяем и перетягиваем кость на нужное место (появятся 2 маркера на 0-м и 50-м слайде), зажимаем Shift и перетягиваем 0-й маркер на 100-й слайд (скопировали, чтобы положение кости в начале и в конце анимации было одинаково). Теперь сделаем так с остальными костями..

Теперь выделим наши анимированные кости, открываем Curve editor и выделяем наши кривые линии (с точками) и жмем кнопку Set tangents to linear, которая сделает их ровными..

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

  

Модель готова. Скомпилим в игру.. Подробнее о компиляции ->>

К примеру у меня такой исходник QC:

 

$cd "D:\Steam\steamapps\sourcemods\ВашМод\modelsrc"

$scale 1

$modelname "laser_linker.mdl"

$model "body" "laser_linker"

$cdmaterials "models\laser_linker"

$attachment "laser1" LB1 0,0 0,0 0,0 rotate 0.00 0.00 0.00

$attachment "laser2" LB2 0,0 0,0 0,0 rotate 0.00 0.00 0.00

$attachment "laser3" LB3 0,0 0,0 0,0 rotate 0.00 0.00 0.00

$attachment "laser4" LB4 0,0 0,0 0,0 rotate 0.00 0.00 0.00

$sequence idle "laser_linker" fps 30.00

$sequence fly "laser_linker_ani" fps 30 loop

$hboxset "default"

 

laser1- laser4 -имена аттачментови LB1- LB4 -имена костей.

Имя анимации обязательно должно быть FLY.

В конце строчки $sequence fly "laser_linker_anifps 30.00 обязательно добавляем параметр loop чтобы анимация повторялась постоянно..

2) Кодим энтитю.

Сначала извлекаем с Source SDK исходный код движка, потом вписываем в него свою энтитю..

Create a Mod -> Source code only

Создаем папку с именем мода в папке sourcemods, копируем путь..

Ждем завершения (обычно занимает минут 5-10)...

Открываем файл Game_Episodic-2005 в Microsoft Visual Studio.. жмем Next, отключаем Backup.. ждем завершение обработки..

В древе открываем Server Episodic > Source files и добавляем новый элемент Файл C++. Назовем его sdk_modelentity.cpp

 

и вставляем этот код туда:

 

#include "cbase.h"

 

class CMyModelEntity : public CBaseAnimating

{

public:

    DECLARE_CLASS( CMyModelEntity, CBaseAnimating );

    DECLARE_DATADESC();

 

    CMyModelEntity()

    {

        m_bActive = true;

    }

 

    void Spawn( void );

    void Precache( void );

 

    void MoveThink( void );

 

    // Input function

    void InputToggle( inputdata_t &inputData );

 

private:

 

    bool    m_bActive;

    float   m_flNextChangeTime;

};

 

LINK_ENTITY_TO_CLASS( my_model_entity, CMyModelEntity );

 

// Start of our data description for the class

BEGIN_DATADESC( CMyModelEntity )

 

    // Save/restore our active state

    DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ),

    DEFINE_FIELD( m_flNextChangeTime, FIELD_TIME ),

 

    // Links our input name from Hammer to our input member function

    DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),

 

    // Declare our think function

    DEFINE_THINKFUNC( MoveThink ),

 

END_DATADESC()

 

// Name of our entity's model

#define ENTITY_MODEL    "models/laser_linker.mdl"

 

//-----------------------------------------------------------------------------

// Purpose: Precache assets used by the entity

//-----------------------------------------------------------------------------

void CMyModelEntity::Precache( void )

{

    PrecacheModel( ENTITY_MODEL );

 

    BaseClass::Precache();

}

 

//-----------------------------------------------------------------------------

// Purpose: Sets up the entity's initial state

//-----------------------------------------------------------------------------

void CMyModelEntity::Spawn( void )

{

    Precache();

 

    SetModel( ENTITY_MODEL );

    SetSolid( SOLID_BBOX );

    UTIL_SetSize( this, -Vector(20,20,20), Vector(20,20,20) );

 

    int iSequence;//this is to store your Sequence number

 

iSequence = LookupSequence("fly");//store

 

ResetSequence( iSequence );//this sets the animation

 

m_flAnimTime = gpGlobals->curtime;

 

SetCycle( 0 );

}

 

//-----------------------------------------------------------------------------

// Purpose: Think function to randomly move the entity

//-----------------------------------------------------------------------------

void CMyModelEntity::MoveThink( void )

{

    // See if we should change direction again

    if ( m_flNextChangeTime < gpGlobals->curtime )

    {

        // Randomly take a new direction and speed

        Vector vecNewVelocity = RandomVector( -300.0f, 300.0f );

        SetAbsVelocity( vecNewVelocity );

 

        // Randomly change it again within one to three seconds

        m_flNextChangeTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 3.0f );

    }

 

    // Snap our facing to where we're heading

    Vector velFacing = GetAbsVelocity();

    QAngle angFacing;

    VectorAngles( velFacing, angFacing );

    SetAbsAngles( angFacing );

 

    // Think every 20Hz

    SetNextThink( gpGlobals->curtime + 0.05f );

 

 

    StudioFrameAdvance();

 

//  DispatchAnimEvents( this );

 

}

 

//-----------------------------------------------------------------------------

// Purpose: Toggle the movement of the entity

//-----------------------------------------------------------------------------

void CMyModelEntity::InputToggle( inputdata_t &inputData )

{

    // Toggle our active state

    if ( !m_bActive )

    {

        // Start thinking

        SetThink( &CMyModelEntity::MoveThink );

 

        SetNextThink( gpGlobals->curtime + 0.05f );

 

        // Start moving

        SetMoveType( MOVETYPE_FLY );

 

        // Force MoveThink() to choose a new speed and direction immediately

        m_flNextChangeTime = gpGlobals->curtime;

 

        // Update m_bActive to reflect our new state

        m_bActive = true;

    }

    else

    {

        // Stop thinking

        SetThink( NULL );

 

        // Stop moving

        SetAbsVelocity( vec3_origin );

        SetMoveType( MOVETYPE_NONE );

 

        m_bActive = false;

    }

}

 

 (Похожий исходный код с комментариями и учебник по нему: <<Ссылка)

Сохраняем, жмем F7 для компиляции.. (занимает около 5-10 мин).  

Должны получить в логе компила:

>Затраченное время: 00:04:37.16

========== Построение: успешно: 2, с ошибками: 0, без изменений: 0, пропущено: 0 ==========

Получаем выходные файлы:

D:\Steam\steamapps\sourcemods\CMM\game\server\bin\server.dll D:\Steam\steamapps\sourcemods\CMM\game\client\bin\Client.dll

Кидаем их в свой мод (только не в мод созданный на Source cod'е. Если нету- создаем. О создании мода <<Ссылка), в папку bin (создаем).

Открываем gameinfo.txt и меняем параметр SteamAppId на 218. ВНИМАНИЕ! тут есть трабла. Код запускается только с 218, а хаммер работает с 420. Приходится переключать (и перезапускать стим) или же создавать еще один мод. Один для маппинга другой с кодом (в него копируем карту +модель +материалы после компила).

Если уж так не терпится увидеть наше творение, то подпрыгиваем (а то спавнится в полу) и в прыжке открываем консоль и пишем:

give my_model_entity

ent_fire my_model_entity toggle

(если игрок застрянет в моделе (99% что так оно и будет) пишем в консоль noclip)

Первая команда создает энтитю, вторая- активирует ее.

Создадим файл конфигурации для хамера. В папке sourcemods\CMM \bin создаем текстовый файл myconfig.fgd Пишем в нем:

@PointClass base(Targetname, Angles) studio("models/laser_linker.mdl") = my_model_entity : "Tutorial model entity."

[

                input Toggle(void) : "Starts and stops the entity moving."

]

 

Заходим в настройки хаммера и добавляем наш новый конфиг:

 

Создаем карту (dev room). Ставим 4 наших энтити my_model_entity в 4-х углах карты (да в принципе все равно куда ставить, они сами разлетятся рандомно по карте).

Внимание, сразу программируем префаб, т. е. в конце имен ВСЕХ энтитей добавляем приставку _&&i чтобы они самопереименовывались. Так проще.

Имена:

laser_spawner_1_&&i

laser_spawner_2_&&i

laser_spawner_3_&&i

laser_spawner_4_&&i

ВНИМАНИЕ! В коде энтити ошибка которая на данный момент не исправлена. Мы вынуждены будем поставить возле наших энтитей prop_dynamic_override с моделью models/laser_linker.mdl  и припарентить к нашим новым энтитям.

Имена:

laser_model_spawner_1_&&i

laser_model_spawner_2_&&i

laser_model_spawner_3_&&i

laser_model_spawner_4_&&i

Припаренчиваем к рядом стоящим "my_model_entity"

Указываем параметр:

Render Mode: Dont render

Создаем logic_autoАутпуты:

OnMapSpawn -> laser_spawner_* -> Toggle    Delay: 0.00

OnMapSpawn -> laser_spawner_* -> Toggle    Delay: 0.10

OnMapSpawn -> laser_model_spawner_* -> SetAnimation Параметр: Fly  

 

Звездочка * в имени значит что аутпут будет обращаться ко всем энтитям которые начинаются с данного имени.

Подаем 2 аутпута на включение т. к. почему-то с первого энтитя не запускается.

Создаем 16 env_beam, программировать их удобно вот в таком положении:

Внимание! Во избежание проблем исчезанием лазеров после начала движения следует использовать энтитю env_laser . (выяснилось после теста).

 

Brightness: 255

Beam color:  255 0 0 (я выбрал красный)

Life: 0

Width beam: 1

Флаги (опции):

Start On

 

Имена (по часовой стрелке, начинаем с левого нижнего):

Одна сторона:

effect_laser_1_1_&&i

effect_laser_1_2_&&i

effect_laser_1_3_&&i

effect_laser_1_4_&&i

Следующая:

effect_laser_2_1_&&i

effect_laser_2_2_&&i

effect_laser_2_3_&&i

effect_laser_2_4_&&i

И так далее..

Соеденяем лазеры:

Имеем 4 групы (грани)  по 4 энтити. Указываем первые (по имени) энтити в групе, потом вторые и т. д.

Например:

Энтитя: effect_laser_1_1_&&i

Start entity: effect_laser_1_1_&&i

Ending entity: effect_laser_2_1_&&i

 

Энтитя: effect_laser_2_1_&&i

Start entity: effect_laser_2_1_&&i

Ending entity: effect_laser_3_1_&&i

 

Энтитя: effect_laser_3_1_&&i

Start entity: effect_laser_3_1_&&i

Ending entity: effect_laser_4_1_&&i

 

Энтитя: effect_laser_4_1_&&i

Start entity: effect_laser_4_1_&&i

Ending entity: effect_laser_1_1_&&i

 

Свяжем по кругу и у нас получится:

 

Выделяем каждую групу и припаренчиваем к своему prop_dynamic_override

Внимание! Если исправить проблему с кодом то будем парентить прямо к нашей энтите.

Переносим каждую группу к припаренченому prop_dynamic_override (к которому парентили). Каждую энтитю лазера располагаем возле своего аттачмента (в нашем случае круглая сфера)

 

Добавим в logic_auto аутпуты для точки аттачмента лазеров:

OnMapSpawn -> effect_laser_%_1_&&i -> SetParentAttachmentMaintainOffset  С параметромlaser% Задержка: 0.20

OnMapSpawn -> effect_laser_%_2_&&i -> SetParentAttachmentMaintainOffset  С параметромlaser% Задержка: 0.20

 

OnMapSpawn -> effect_laser_%_3_&&i -> SetParentAttachmentMaintainOffset  С параметромlaser% Задержка: 0.20

OnMapSpawn -> effect_laser_%_4_&&i  -> SetParentAttachmentMaintainOffset С параметромlaser% Задержка: 0.20

Где % это номер группы (1, 2, 3, 4). Всего должно быть 16 аутпутов.

Внимание! Если исправить проблему с кодом то следует использовать просто команду SetParentAttachment. Она перенесет и прицепит лазеры в нужное место и  групы  лазеров не нужно будет переносить.

Внимание! Во избежания сбивания лазеров в одну точку рекомендуется не использовать этот пункт (команды SetParentAttachmentMaintainOffset до починки кода).

PS. Автор приносит свои извинения за траблу с кодом.

PSS. Автор плакалъ..

Теперь нам нужно передвинуть энтити my_model_entity в рядом стоящие prop_dynamic_override. Одна в одну. По размеру они одинаковые.

По желанию все энтити выделяются, нажимается кнопка Create prefab и сохраняется. Префаб создан, можно натыкать на карте кучу и наблюдать.. o_0

К примеру мои настройки logic_auto:

Не особо то важны самы параметры задержки, главное чтобы сначала срабатывал SetParentAttachmentMaintainOffset, потом SetAnimation и потом Toggle.

Все это должно выглядеть примерно так..

Архив со всеми исходниками, скомпиленным кодом, картой, конфигом хаммера, материалами и моделями и их исходников прилагаю.

Исходники>>

Не бейте сильно.. Код не осилил исправить..

Категория: На движке Valve Source | Добавил: stridemann (28.01.2012) | Автор: Stridemann
Просмотров: 2842
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа
Логин:
Пароль:

Поиск

Друзья сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

© 2024, MonoLife