Данный урок был сделан по реквесту Степан Колесниченко. Свои реквесты можете оставлять в группе вк или в комментариях к записи.
Разбираем акторы
Перед началом, скачайте wad с MEGA.
Затем, откройте в нем файл DECORATE. Там находятся 3 актора:
- rune_part — руна, которая спавнит rune_part_generator каждые 10 тиков (1 тик = 1/35 секунды)
- rune_part_generator — невидимый актор, спавнит вокруг себя несколько частиц, придавая им скорость.
- my_rune — актор частицы, со временем исчезает.
Вот код наших акторов.
actor my_rune : Inventory 10000 {
ActiveSound SFIRE
height 32
radius 32
+float
+floatbob
states {
spawn:
TNT1 A 0 A_LoopActiveSound
RUNE A 0 A_SpawnItemEx("rune_part_generator",0,0,0,0,0,0,0,0,0,0)
RUNE A 10 Bright
loop
pickup:
RUNE A 1 A_StopSound
stop
}
}
actor rune_part_generator {
+NOGRAVITY
+noclip
states {
spawn:
TNT1 AAAAAAAAA 1 A_SpawnItemEx("rune_part",random(20,-20),random(20,-20),random(-10,20),0,0,random(2,6),0,128,0)
stop
}
}
actor rune_part {
+noclip
+NOGRAVITY
scale 0.3
states {
spawn:
PART AAAAAAAAAA 2 Bright A_FadeOut
stop
}
}
Разберем эти акторы.
+float
+floatbob
Эти флаги заставляют спрайт актора передвигаться вверх/вниз.
ActiveSound SFIRE
В качестве звука активации, устанавливаем звук огня. Звук SFIRE, как и все другие, задаются в SNDINFO.
spawn:
TNT1 A 0 A_LoopActiveSound
RUNE A 0 A_SpawnItemEx("rune_part_generator",0,0,0,0,0,0,0,0,0,0)
В стейте spawn, включаем повтор звука активации (огня) с помощью комманды A_LoopActiveSound
И спавним rune_part_generator.
actor rune_part_generator {
+NOGRAVITY
+noclip
states {
spawn:
TNT1 AAAAAAAAA 1 A_SpawnItemEx("rune_part",random(20,-20),random(20,-20),random(-10,20),0,0,random(2,6),0,128,0)
stop
}
Он же в свою очередь, спавнит несколько частиц, находящийся на случайном расстоянии вокруг руны. Так-же, скорость частицы случайна random(2,6), и направленна вверх по оси z.
У генератора частиц, нет ни гравитации (+NOGRAVITY), ни коллизии (+noclip), т.к. они ему не нужны.
actor rune_part {
+noclip
+NOGRAVITY
scale 0.3
states {
spawn:
PART AAAAAAAAAA 2 Bright A_FadeOut
stop
}
}
Сама частица, постепенно становится прозрачной (A_FadeOut), и затем исчезает.
Также, при подбирании руны, отключается звук огня.
pickup:
RUNE A 1 A_StopSound
stop
С руной разобрались. Перейдем к ACS коду.
Разбираем ACS код.
Функции drawImage, drawString, drawInt, я разбирать не буду т.к. разбирал здесь
Нас сейчас интересуют две скрипта:
- player_loop — проверяется наличие нужной руны
- simple_rune — скрипт, который вызывается, если подобрана.
Т.е. в этом скрипте
script "player_loop" ENTER {
SetHudSize(640, 480,0);
if (CheckInventory("my_rune") > 0)
{
ACS_NamedExecute("simple_rune",0);
}
Delay(1);
restart;
}
Вызывается скрипт simple_rune. Самое приятное то, что ACS_NamedExecute, не позволит вызвать скрипт simple_rune, пока он не закончит свою работу, поэтому проблем с синхронизацией не возникнет.
ACS_NamedExecute("simple_rune",0);
Если количество предметов my_rune больше 0 (если есть в наличии).
if (CheckInventory("my_rune") > 0)
Далее идем скрипт simple_rune.
script "simple_rune" (void) {
int my_timer = 1000;
while(CheckInventory("my_rune") > 0) {
drawInt(my_timer, 1, 1000,1000);
drawImage("RUNEA0",5,2000,12000);
if (my_timer <= 0) break;
if ((my_timer % 35) == 0) {
HealThing(10);
}
SpawnForced("rune_part_generator",GetActorX(0),GetActorY(0),GetActorZ(0),0,0);
my_timer--;
Delay(1);
}
TakeInventory("my_rune", 1);
Delay(1);
}
В нем хранится переменная my_timer, которая указывает время действия руны в тиках.
Если руна в инвентаре (подобрана)
while(CheckInventory("my_rune") > 0) {
То, рисуем значение таймера, и картинку руны, на экране.
drawInt(my_timer, 1, 1000,1000);
drawImage("RUNEA0",5,2000,12000);
Если таймер <= 0, то выходим из цикла.
if (my_timer <= 0) break;
Каждые 35 тиков (1 секунда) мы выдаем игроку 10 хп.
if ((my_timer % 35) == 0) {
HealThing(10);
}
Спавним на месте игрока, частицы руны.
SpawnForced("rune_part_generator",GetActorX(0),GetActorY(0),GetActorZ(0),0,0);
Уменьшаем на единицы таймер, чтобы цикл не был бесконечным. И делаем заддержку в 1 тик.
my_timer--;
Delay(1);
После того, как руна отработала свое, мы её отбираем.
TakeInventory("my_rune", 1);
Разбираем по мелочи.
Осталось разобрать GLDEFS который добавляет свечение акторам, и SNDINFO добавляющий звуки.
GLDEFS, я подробно разбирал здесь.
FLICKERLIGHT rune_light
{
Color 1 0 0
OffSet 0 8 0
Size 20
SecondarySize 35
Chance 0.2
}
object rune_part
{
frame PARTA0 {light rune_light}
}
У SNDINFO синтаксис элементарный.
название_переменной название_файла
- название_переменной — название звука в коде Decorate и ACS.
- название_файла — имя файла без расширения, которое будет проигрываться при вызове название_переменной
Собственно, вот код SNDINFO.
SFIRE SFIRE
ZLOVESCH ZLOVESCH