Добавлен , опубликован
Раздел:
1 месяц
Так как часто сижу в Q/A и общаюсь с "jass программистами" в гарене, то видел много систем движения где для каждого отдельного объекта создавался свой таймер, а данные о юните и о том как его двигать крепились на хэш по хэндлу этого таймера.
Объяснять каждому по отдельности надоело,поэтому решил написать эту статью,кроме того спелы сделанные этим способом являются муи(как выяснилось для многих муи кажется очень сложной задачей).
В этой статье будем рассматривать что то наподобие 1 спела бары только без отталкивания врагов и нанесения им урона(простое движение юнита а к юниту б).

Создание структуры

library mylibrary initializer init{ // объявляем библиотеку
	define private SPELL='A000' // равкод вашего спела
	define private SPEED=800/40 // скорость, с которой наш юнит будет мчаться к цели, делённая на 40

	struct mystruct extends array{ //объявляем структуру с именем mystruct
		unit caster //юнит которого мы будем двигать
		unit target //юнит к которому мы будем двигать
		static thistype count=0; //количество объектов

		static thistype new(unit caster,unit target){ //статичный метод new создающий экземпляр структуры
			thistype this=count;
			count++;
			this.caster=caster //заносим в структуру юнита которого будем двигать
			this..target=target //заносим в структуру юнита к которому будем двигаться
		}

Создание метода move(движение) и delete(удаление структуры)

	bool move(){
		float dx=GetUnitX(target)-GetUnitX(caster) //разница координат x
		float dy=GetUnitY(target)-GetUnitY(caster) //разница координат y
		float r=SquareRoot(dx*dx+dy*dy) //расстояние между юнитами
		float cos=dx/r
		float sin=dy/r
		if (r<=SPEED){
			return delete();
		else
			SetUnitX(caster,GetUnitX(caster)+SPEED*cos //двигаем caster
			SetUnitY(caster,GetUnitY(caster)+SPEED*sin //двигаем caster
		}
		return true;
	}

	bool delete(){
		caster=null;
		target=null;
		count--;
		if(this<count){
			caster=count.caster;
			target=count.target;
			return false;
		}
		return true;
	}
	
} // закрытие структуры

Перебор структур,реакция на спел и инициализация системы

	private void update(){
		mystruct myStruct=mystruct.count - 1;
 		loop{
			exitwhen myStruct < 0;
  			if (myStruct.move()){
				myStruct--;
			}
		}
	}

	private void action(){
		mystruct.new(GetTriggerUnit(),GetSpellTargetUnit()) // вызываем статичный метод new 
	}

	private bool cond(){
		return GetSpellAbilityId()==SPELL;
	}

	private void init(){
		trigger a=CreateTrigger() // создание триггера
		timer b=CreateTimer() // создание таймера
		TriggerAddAction(a,function action) // добавление действия
		TriggerAddCondition(a,Condition(function cond)) // добавление условия
		TriggerRegisterAnyUnitEventBJ(a,EVENT_PLAYER_UNIT_SPELL_EFFECT) // добавление события
		TimerStart(b,.025,true,function update) // запускаем таймер с функцией update
	}
	
} // закрытие библиотеки

Всё вместе

library mylibrary initializer init{ // объявляем библиотеку
	define private SPELL='A000' // равкод вашего спела
	define private SPEED=800/40 // скорость, с которой наш юнит будет мчаться к цели, делённая на 40

	struct mystruct extends array{ //объявляем структуру с именем mystruct
		unit caster //юнит которого мы будем двигать
		unit target //юнит к которому мы будем двигать
		static thistype count=0; //количество объектов

		static thistype new(unit caster,unit target){ //статичный метод new создающий экземпляр структуры
			thistype this=count;
			count++;
			this.caster=caster //заносим в структуру юнита которого будем двигать
			this..target=target //заносим в структуру юнита к которому будем двигаться
		}
		
		bool move(){
			float dx=GetUnitX(target)-GetUnitX(caster) //разница координат x
			float dy=GetUnitY(target)-GetUnitY(caster) //разница координат y
			float r=SquareRoot(dx*dx+dy*dy) //расстояние между юнитами
			float cos=dx/r
			float sin=dy/r
			if (r<=SPEED){
				return delete();
			else
				SetUnitX(caster,GetUnitX(caster)+SPEED*cos //двигаем caster
				SetUnitY(caster,GetUnitY(caster)+SPEED*sin //двигаем caster
			}
			return true;
		}

		bool delete(){
			caster=null;
			target=null;
			count--;
			if(this<count){
				caster=count.caster;
				target=count.target;
				return false;
			}
			return true;
		}
	
	} // закрытие структуры
	
	private void update(){
		mystruct myStruct=mystruct.count - 1;
 		loop{
			exitwhen myStruct < 0;
  			if (myStruct.move()){
				myStruct--;
			}
		}
	}

	private void action(){
		mystruct.new(GetTriggerUnit(),GetSpellTargetUnit()) // вызываем статичный метод new 
	}

	private bool cond(){
		return GetSpellAbilityId()==SPELL;
	}

	private void init(){
		trigger a=CreateTrigger() // создание триггера
		timer b=CreateTimer() // создание таймера
		TriggerAddAction(a,function action) // добавление действия
		TriggerAddCondition(a,Condition(function cond)) // добавление условия
		TriggerRegisterAnyUnitEventBJ(a,EVENT_PLAYER_UNIT_SPELL_EFFECT) // добавление события
		TimerStart(b,.025,true,function update) // запускаем таймер с функцией update
	}
	
} // закрытие библиотеки
1
28
11 лет назад
1
если высшим силам неугодна эта статья то переместите её в мой блог
4
21
11 лет назад
Отредактирован Buulichkaa
4
лучше б написал как это все реализовано на нормальном джассе, вот то интересно, там больше места для самореализации.
3
28
11 лет назад
3
Buulichkaa, есть мануал по вджассу, там показано во что компилируются .create() и .destroy() а всё остальное также
я не понимаю твою нелюбовь к vjass и cjass,они ведь намного удобнее чем просто jass
3
25
11 лет назад
3
nvc123, они требуют ставить на редактор v и c, которые убивают его на 50%.
0
21
11 лет назад
0
nvc123, просто незачем есть конфетку в обертке, если её можно съесть и без обертки.
раньше использовал cjass, использовал бы и сейчас, не будь он такой баганный, мне и своих багов хватает.
1
32
11 лет назад
1
nvc123, ура ты всё такие её написал =)
0
28
11 лет назад
0
Buulichkaa, проще сделать структуру чем доп переменные которые нужны для поиска свободных индексов
баганные там локалки вроде и массивы в структурах иногда тупят,больше багов я не заметил
sleep, последний jngp включает в себя v и c
0
17
11 лет назад
Отредактирован Sergant1000
0
Поправь меня если я ошибаюсь.
Этим примером мы создаем в триггере 2 подтригера:
  1. действие при использовании спелла.
  2. триггер на время для замены вэйта
5
14
11 лет назад
5
Прочел статью, оставлю, пожалуй, я тут это:
Отступ
PS: Да и абзацы, стоит отделять друг от друга.
0
28
11 лет назад
0
Sergant1000, этим примером мы создаём примитивную систему движения,которую на вейтах создать невозможно
2 комментария удалено
0
7
8 лет назад
0
exitwhen a==1
Ошибку выдает.
Загруженные файлы
1
28
8 лет назад
1
ELB359, даже не знаю что сказать
видимо у тебя другая версия jngp
если коротко то твоя ошибка переводится следующим образом "я не могу сравнить 2 числа одного типа т.к. мне кажется что они разных типов хотя это и не так"
могу лишь предложить костыль но хз сработает он или нет
добавь ещё 1 переменную
mystruct ONE=1
и вместо
exitwhen a==1
пиши
exitwhen a==ONE
0
7
8 лет назад
0
видимо у тебя другая версия jngp
Это было бы очень странно. Только что скачал его, никаких модулей не ставил, подключал только "cj_types_priv" и "cj_typesEx_priv". Попробую костыль и отпишусь.
nvc123, увы, но теперь он говорит, что я не перегрузил соответствующие операторы для своей структуры :D
Прикладываю код. Он не 100% рабочий, т.к. я как раз начал переписывать его под структуры (с хэштаблицей работал). В структурах же почти полный ноль, не смотря на опыт в сиподобных языках.
код
struct KB_data {
    unit u;
    real a;
    int times;
    KB_data MIN = 1;
    KB_data MAX = 500;
    
    void move() {
        real x = GetUnitX(.u);
        real y = GetUnitY(.u);
        x = TranslateX(x,KB_POWER,.a);
        y = TranslateY(y,KB_POWER,.a);
        SetUnitX(.u,x);
        SetUnitY(.u,y);
    }
    
    static void new(unit targ, real angle) {
        KB_data data = KB_data.create();
        if (data>MAX) {
            data.destroy();
            return;
        }
        data.times = 10;
        data.u = targ;
        data.a = angle;
    }
    
    static void delete() {
        .u = null;
        .destroy();
    }
    
    private void update() {
        KB_data data=MAX;
        loop {
            data.move()
            exitwhen (data==MIN);
            data--;
        }
    }
}
Чтобы оставить комментарий, пожалуйста, войдите на сайт.