Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.

Реклама


**Как получить V.I.P** (Перейти)
Чтобы заказать рекламу на Pro-Pawn.Ru, обращайтесь в Skype.
Баннерная реклама 200руб/мес, Текстовая 100руб/мес.
Страница 1 из 4 123 ... ПоследняяПоследняя
Показано с 1 по 10 из 37
  1. #1
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,931
    Репутация:
    1502 ±

    Вызов нескольких функций на одну кнопку в OnPlayerKeyStateChange

    Так как я довольно часто помогаю людям с их проблемами в скриптах, этих самых скриптов я видел великое множество и практически везде видел подобную конструкцию:

    PHP код:
    public OnPlayerKeyStateChange(playeridnewkeysoldkeys)
    {
        if(
    newkeys KEY_FIRE)
        {
            
    OnPlayerCommandText(playerid"Команда_1");
            
    OnPlayerCommandText(playerid"Команда_2");
            
    OnPlayerCommandText(playerid"Команда_3");
            
    OnPlayerCommandText(playerid"Команда_4");
            
    OnPlayerCommandText(playerid"Команда_5");
            
    //И не только команды
        
    }
        return 
    1;

    При том это были команды, которые, в большинстве случаев, являются командами для входа в дома/бизнесы и обычно они содержат в себе циклы.


    В этом случае получается, что при нажатии на кнопку ходьбы, вызывается 5 команд. В любом случае. Даже если сработала одна из 5 команд, остальные 4 тоже будут вызваны. И теперь представьте, что каждая из команд имеет в себе код с сложными вычислениями.

    Довольно непродуктивно заставлять мод выполнять каждый раз вызов этих самых команд и я придумал способ, который предотвратит холостой вызов последующих команд, если одна из предыдущих является нужной (это не только к командам относится, но покажу я именно на примере команд).
    Допустим, у нас есть следующий набор команд:
      Открыть/закрыть
    PHP код:
    public OnPlayerCommandText(playeridcmdtext[])
    {
        if (
    strcmp("/вход"cmdtexttrue10) == 0)
        {
            for(new 
    i1000i++)
            {
                if(!
    IsPlayerRangeOfPoint(playeridHouseInfo[i][EnterX], HouseInfo[i][EnterY], HouseInfo[i][EnterZ])) continue;
                
    SetPlayerPos(playeridHouseInfo[i][ExitX], HouseInfo[i][ExitX], HouseInfo[i][ExitX]);
                
    SendClientMessage(playerid0xFF0000FF"Вы вошли в дом!");
                break;
            }
            return 
    1;
        }
        else if (
    strcmp("/выход"cmdtexttrue10) == 0)
        {
            for(new 
    i1000i++)
            {
                if(!
    IsPlayerRangeOfPoint(playeridHouseInfo[i][ExitX], HouseInfo[i][ExitY], HouseInfo[i][ExitZ])) continue;
                
    SetPlayerPos(playeridHouseInfo[i][EnterX], HouseInfo[i][EnterY], HouseInfo[i][EnterZ]);
                
    SendClientMessage(playerid0xFF0000FF"Вы вышли из дома!");
                break;
            }
            return 
    1;
        }
        else if (
    strcmp("/нуль"cmdtexttrue10) == 0)
        {
            if(
    IsPlayerRangeOfPoint(playerid0.0,0.0,0.0)) SendClientMessage(playerid0xFF0000FF"Вы находитесь в нулевых координатах");
            return 
    1;
        }
        return 
    0;


    И нам нужно сделать их вызов при нажатии на кнопку ходьбы. Обычно это сделали бы так
    PHP код:
    public OnPlayerKeyStateChange(playeridnewkeysoldkeys)
    {
        if(
    newkeys KEY_FIRE)
        {
            
    OnPlayerCommandText(playerid"/вход");
            
    OnPlayerCommandText(playerid"/выход");
            
    OnPlayerCommandText(playerid"/нуль");
        }
        return 
    1;

    И при каждом нажатии на кнопку ходьбы все три команды (а с ними и циклы на 1000 итераций) вызывались бы модом в любом случае. Но если подумать, зачем вызывать команду выхода из дома, если игрок вошёл в него? Ведь игрок зашёл в дом не для того, чтобы тут же из него выйди. Да и мы не просто вызываем команду выхода, мы заставляем мод выполнять цикл на 1000 итераций, тем самым забивая поток ненужными действиями. А Pawn - язык однопоточный, если кто не знал :)

    Вот мой способ построения подобного кода. Основан он на использовании всех возможностей оператора возврата. Но сначала нам нужно выставить приоритетность наших команд. Допустим, вызов команды "/нуль" нам нужен в любом случае и вызов этой команды не является причиной, по которой другие команды вызывать не нужно (вспомните пример с командами "/вход" и "/выход"). Это значит, что её мы можем оставить без изменений и нам нужно лишь переместить её в самое начало блока нашего скрипта, который мы пишем.
     То бишь:
    PHP код:
    public OnPlayerKeyStateChange(playeridnewkeysoldkeys)
    {
        if(
    newkeys KEY_FIRE)
        {
            
    OnPlayerCommandText(playerid"/нуль");//При нажатии на кнопку ходьбы первой будет вызвана эта команда
            
    OnPlayerCommandText(playerid"/вход");
            
    OnPlayerCommandText(playerid"/выход");
        }
        return 
    1;


    То же проделываем с остальным кодом, который вызывается вне зависимости от результатов, к которым мы пришли в предыдущих участках кода.
    И остаются у нас команды, которые число логически не могут вызываться вместе. В нашем случае это "/вход" и "/выход". Что же мы делаем с ними? А мы делаем следующее:


    1) Находим сами команды и вырезаем из блока команды все внутренности

     Пояснение:
    PHP код:
    public OnPlayerCommandText(playeridcmdtext[])
    {
        if (
    strcmp("/вход"cmdtexttrue10) == 0)
        {
            
    //Нас интересует код, что расположен ниже
            
    for(new i1000i++)
            {
                if(!
    IsPlayerRangeOfPoint(playeridHouseInfo[i][EnterX], HouseInfo[i][EnterY], HouseInfo[i][EnterZ])) continue;
                
    SetPlayerPos(playeridHouseInfo[i][ExitX], HouseInfo[i][ExitX], HouseInfo[i][ExitX]);
                
    SendClientMessage(playerid0xFF0000FF"Вы вошли в дом!");
                break;
            }
            
    //До самого конца команды
            
    return 1;
        }
        return 
    0;




    2) Создаём новую функцию и помещаем в неё наш код

      Открыть/закрыть
    PHP код:
    stock CommandEnter(playerid)//Имя придумываем сами, естественно
    {
        for(new 
    i1000i++)
        {
            if(!
    IsPlayerRangeOfPoint(playeridHouseInfo[i][EnterX], HouseInfo[i][EnterY], HouseInfo[i][EnterZ])) continue;
            
    SetPlayerPos(playeridHouseInfo[i][ExitX], HouseInfo[i][ExitX], HouseInfo[i][ExitX]);
            
    SendClientMessage(playerid0xFF0000FF"Вы вошли в дом!");
            break;
        }




    3) Внедряем в нашу новую функцию оператор возврата, дабы на основе возвращённого значения возможно было сделать проверку

      Открыть/закрыть

    Начинаем рассуждать:
    Команда представляет собой цикл, который сравнивает местоположение игрока с координатами входа в дома
    Следовательно команда выполниться только тогда, когда этот дом найден
    Значит первый возврат нужно поставить в код, который срабатывает при обнаружении этого самого дома
    PHP код:
    stock CommandEnter(playerid)
    {
        for(new 
    i1000i++)
        {
            if(!
    IsPlayerRangeOfPoint(playeridHouseInfo[i][EnterX], HouseInfo[i][EnterY], HouseInfo[i][EnterZ])) continue;//Это условие выглядит так:
            //Если игрок не находится в точке "координаты входа в дом", начнём новую итерацию
            //Следовательно код ниже выполняется только в случае, когда условие выше не срабатывает (когда игрок находится в точке входа)
            //Значит именно тут и надо нам возвращать значение, ведь в случае телепорта игрока в дом команда является успешно выполненной
            //Но return останавливает выполнение всей функции, а код ниже нам нужен
            //Следовательно ищем конец выполнения данного участка функции
            
    SetPlayerPos(playeridHouseInfo[i][ExitX], HouseInfo[i][ExitX], HouseInfo[i][ExitX]);
            
    SendClientMessage(playerid0xFF0000FF"Вы вошли в дом!");
            break;
    //И он тут
        
    }

    • Напомню, что "break" является подобием return, только для циклов. Он не возвращает значение, а лишь отдаёт команду моду на завершение выполнения цикла. В данном случае цикл создан для "отлова" информации, которая позволит условию выполнится и такая информация (в данном случае!) может быть только в единственном экземпляре (игрок не может войти сразу в несколько домов). А значит и break в нашей функции не нужен, ведь после цикла никакого другого кода нет. Значит именно его мы и заменим возвратом.

    • Теперь настало время поговорить о возврате, когда наша "команда" не сработала. Не сработает она в том случае, когда ни одна из координат не подошла под условие и игрок не стоит на пикапе входа. С точки скрипта, при невыполнении нашего условия, цикл закончит своё выполнение, сделав 1000 итераций, и функция продолжит своё выполнение. Следовательно и возврат определённого значения, означающего невыполнение команды, нужно ставить именно после цикла

     На человеческом языке это выглядит, примерно, так
    PHP код:
    функция
    {
        
    запускаем цикл на 1000 итераций
        
    {
            
    проверяем координаты
            если координаты найдены
    вернём определённое значение
            иначе запускаем следующую итерацию 
    (пока не дойдём до 1000-ойА после завершим выполнение цикла и...)
        }
        
    //...продолжим выполнять этот код до скобки, закрывающей блок функции



    Хорошо, с местом расстановки наших возвратов мы разобрались. Теперь осталось решить для себя то, какие значения при каких условиях мы будем возвращать. Я не зря сказал "для себя". Мы можем вернуть два (или больше. Зависит от числа возвратов и от их предназначения) любых числовых значения. Главное чтоб они были разные, ведь на их основе мы будем делать проверку.
    Я не буду изобретать велосипед и использую общепринятый вид, вернув "0" в случае, когда команда не выполнится, и "1", когда команда выполнится. В итоге у нас получится такой код
    PHP код:
    stock CommandEnter(playerid)
    {
        for(new 
    i1000i++)
        {
            if(!
    IsPlayerRangeOfPoint(playeridHouseInfo[i][EnterX], HouseInfo[i][EnterY], HouseInfo[i][EnterZ])) continue;
            
    SetPlayerPos(playeridHouseInfo[i][ExitX], HouseInfo[i][ExitX], HouseInfo[i][ExitX]);
            
    SendClientMessage(playerid0xFF0000FF"Вы вошли в дом!");
            return 
    1;
        }
        return 
    0;



    Всё. Теперь осталось лишь восполнить то, что мы вырезали из команды, вызовом функции и переписать вызов команды на кнопку, использовав нашу новую функцию.
    • Команда:
    PHP код:
    public OnPlayerCommandText(playeridcmdtext[])
    {
        if (
    strcmp("/вход"cmdtexttrue10) == 0)
        {
            
    CommandEnter(playerid);
            return 
    1;
        }
        return 
    0;

    Не забываем, что наша функция вернёт нуль, если игрок не находится на координатах, следовательно, если установить функцию тут (return CommandEnter(playerid);), мод отобразит в чат "Unknown Command", если игрок не стоит на координатах. Поэтому сокращать тут ничего не стоит.
     НО:
    На основе возврата функции можно сделать следующее сообщение
    PHP код:
    public OnPlayerCommandText(playeridcmdtext[])
    {
        if (
    strcmp("/вход"cmdtexttrue10) == 0)
        {
            if(
    CommandEnter(playerid) == 0) return SendClientMessage(playerid0xFF0000FF"Вы не находитесь у входа в дом");
            else return 
    1;
        }
        return 
    0;


    • Вызов команды на кнопку
    PHP код:
    public OnPlayerKeyStateChange(playeridnewkeysoldkeys)
    {
        if(
    newkeys KEY_FIRE)
        {
            
    OnPlayerCommandText(playerid"/нуль");
            if(
    CommandEnter(playerid) == 1) return 1;//Если команда выполнится, функция вернут 1. А значит можно закончит на этом выполнение паблика
            
    OnPlayerCommandText(playerid"/выход");
        }
        return 
    1;

    Теперь если игрок, нажимая на клавишу ходьбы, хотел войти в дом и вошёл в него, мод не будет выполнять более никаких действий, связанных с клавишей ходьбы и приступит к обработке другой информации. Главное логически верно строить код (ведь мод делает именно то, что указали делать ему вы) и тогда не нужно будет беспокоиться об оптимизации :)


    На этом всё.
    В примере я перевёл лишь одну команду, но вы можете перевести и вторую, если после неё так же имеются вызовы команд/функций, которые вызывать не нужно
    (как правильно строить логическую цепочку в подобных случаях, я показал выше.)

    Если есть какие-либо вопросы, если что-то непонятно объяснено или есть какие-либо дополнения/исправления для данного урока, прошу написать об этом ниже.
    С вами был DeimoS. Спасибо за внимание
    Автор урока - DeimoS

    Специально для портала Pro-pawn.ru
    При копировании данного материала, обязательно указывайте автора и ссылку на эту страницу
    Последний раз редактировалось DeimoS; 10.04.2014 в 14:33.
    Связаться со мной можно в личных сообщениях этой группы

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  2. 9 пользователя(ей) сказали cпасибо:
    #ball (09.08.2014)#Vito (11.08.2014)Edwin (19.02.2014)Just_Fenix (03.06.2014)Osetin (13.02.2014)Salvacore (13.02.2014)Skuba_Lo (11.04.2014)[ForD] (13.02.2014)Копюшон (10.04.2014)
  3. #2
    Аватар для [ForD]
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.11.2013
    Адрес
    Свердловская обл.
    Сообщений
    694
    Репутация:
    104 ±
    Если честно,то я восхищен твоим усердием,это-же так нудно все расписывать,да и к тому-же все настолько понятно как на доп. уроках в школе =\
    В общем я наверно каждую тему буду повторяться,объяснять ты умеешь :3
    PAWN Compiler делает то, что вы приказали ему сделать, а не то, что вы хотели, чтобы он сделал..

    25% времени в программировании уходит на размышления о том, что пользователь может сделать не так.[HR]/Брайан Хьюмс/





    #FIXSAMP

  4. #3
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,931
    Репутация:
    1502 ±
    Цитата Сообщение от [ForD] Посмотреть сообщение
    Если честно,то я восхищен твоим усердием,это-же так нудно все расписывать,да и к тому-же все настолько понятно как на доп. уроках в школе =\
    В общем я наверно каждую тему буду повторяться,объяснять ты умеешь :3
    Ну что сказать. Мне нравится расписывать :D Даже там, где это и не обязательно :с

    Ах да, забыл добавить в теме. Если у вас есть какие-то идеи по поводу темы урока, отписывайтесь. Буду рад ;)
    Связаться со мной можно в личных сообщениях этой группы

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  5. #4
    Аватар для Salvacore
    Инжунер-погромист

    Статус
    Оффлайн
    Регистрация
    10.05.2013
    Адрес
    Аҧсуа бызшәа
    Сообщений
    2,282
    Репутация:
    417 ±
    Отлично.
    Иди учителем работай :D

  6. Пользователь сказал cпасибо:
    [ForD] (13.02.2014)
  7. #5
    Аватар для [ForD]
    Пользователь

    Статус
    Оффлайн
    Регистрация
    14.11.2013
    Адрес
    Свердловская обл.
    Сообщений
    694
    Репутация:
    104 ±
    Цитата Сообщение от Salvador Посмотреть сообщение
    Отлично.
    Иди учителем работай :D
    Ты прям мысли читаешь.
    PAWN Compiler делает то, что вы приказали ему сделать, а не то, что вы хотели, чтобы он сделал..

    25% времени в программировании уходит на размышления о том, что пользователь может сделать не так.[HR]/Брайан Хьюмс/





    #FIXSAMP

  8. #6
    Аватар для Копюшон
    Пользователь

    Статус
    Оффлайн
    Регистрация
    31.03.2013
    Сообщений
    96
    Репутация:
    13 ±
    Да действительно обьяснил на 5+

  9. #7
    Аватар для Caypen
    Пользователь

    Статус
    Оффлайн
    Регистрация
    25.03.2014
    Сообщений
    104
    Репутация:
    16 ±
    Как-то OKstyle говорил что у кого-то цикл прерывающиеся возвратом вызвал рекурсию,он не был уверен в этом,но всё же ваше мнение по этому поводу мне интересно.
    Захожу на pro-pawn.ru - чувствую себя обычным пользователем
    Захожу на gawno-info.ru - чувствую себя самым великим гением
    (С) Caypen

  10. #8
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,931
    Репутация:
    1502 ±
    Цитата Сообщение от Caypen Посмотреть сообщение
    Как-то OKstyle говорил что у кого-то цикл прерывающиеся возвратом вызвал рекурсию,он не был уверен в этом,но всё же ваше мнение по этому поводу мне интересно.
    Если сообщение обращено мне, то вот:
    PHP код:
    main()
    {
        
    printf("Функция вернула %d\n\n"TestFunction());
        print(
    "Рекурсия? Не, не слышал!");
    }

    stock TestFunction()
    {
        print(
    "\n\nЦикл запущен");
        for(new 
    indexindex != 9999999; ++index)
        {
            
    printf("%d",index);
            if(
    index == 10) return index;
            
    printf("• %d\n"index);
        }
        return 
    1;

    Проверьте всё самостоятельно :)
    Связаться со мной можно в личных сообщениях этой группы

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  11. #9
    Аватар для Caypen
    Пользователь

    Статус
    Оффлайн
    Регистрация
    25.03.2014
    Сообщений
    104
    Репутация:
    16 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Если сообщение обращено мне, то вот:
    PHP код:
    main()
    {
        
    printf("Функция вернула %d\n\n"TestFunction());
        print(
    "Рекурсия? Не, не слышал!");
    }

    stock TestFunction()
    {
        print(
    "\n\nЦикл запущен");
        for(new 
    indexindex != 9999999; ++index)
        {
            
    printf("%d",index);
            if(
    index == 10) return index;
            
    printf("• %d\n"index);
        }
        return 
    1;

    Проверьте всё самостоятельно :)
    Да нет, я сам частенько использую возврат в циклах и не разу не встречал рекурсии,не знаю может это просто очередное ошибочное мнение многих как и про то что таймеры продолжают работу после выключения геймода.
    Захожу на pro-pawn.ru - чувствую себя обычным пользователем
    Захожу на gawno-info.ru - чувствую себя самым великим гением
    (С) Caypen

  12. #10
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,931
    Репутация:
    1502 ±
    Цитата Сообщение от Caypen Посмотреть сообщение
    Да нет, я сам частенько использую возврат в циклах и не разу не встречал рекурсии,не знаю может это просто очередное ошибочное мнение многих как и про то что таймеры продолжают работу после выключения геймода.
    Всё можно проверить. Нужно лишь понять суть проблемы (вопроса) и воссоздать ситуацию в виде кода :)
    По поводу таймеров. Работают они или нет - не знаю, но знаю точно, что после рестарта ID таймеров не отчищается (было создано 10 таймеров и после рестарта они займут следующие 10 ID (то бишь, с 10 до 20). В любом случае сами таймеры выдают просто ничтожную нагрузку на процессор
    Связаться со мной можно в личных сообщениях этой группы

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

 

 
Страница 1 из 4 123 ... ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

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