Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 2 1 2 ПоследняяПоследняя
Показано с 1 по 10 из 11
  1. #1
    Аватар для red.inc
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.07.2019
    Адрес
    Беларусь, Витебск
    Сообщений
    23
    Репутация:
    0 ±

    Использование динамической зоны

    Всех приветствую дорогие читатели Pro-Pawn.Ru
    Недавно приступил к помощи игрокам и созданиям мануалов. Просьба не судить строго, буду рад каждой помощи

    Преимущество между моим кодом и кодом IsPlayerRangeOfPoint не большая. Вместо того чтобы нагружать сервер проверкой на нужное местоположение, проходит ежесекундная проверка Streamer, конечно можно сделать функцию, которая будет вызываться при нажатие ALT, он будет узнавать ваши координаты и проводить проверку, если вы не находитесь рядом с сферой, то будет происходить завершение.

    Это лишь мои предположение, проверку она не проходило.

    Теперь приступаем к коду изложенный мною.


    1. enum AREAS
    2. {
    3. gExitHospital, // выход из больницы
    4. // и тд
    5. }
    6. new g_areas[AREAS]; // переменная, которая в будущим будет присваивать нашу зону
    7.  
    8. new player_zone[MAX_PLAYERS char]; // переменная которая будет принимать ид территория на игрока


    После переходим к пабликам как OnGameModeInit и OnPlayerEnterDynamic/OnPlayerLeaveDynamic

    1. public OnGameModeInit()
    2. {
    3. g_areas[gExitHospital] = CreateDynamicSphere(/*Ваши координаты X,Y,Z, радиус, виртуальный мир, интерьер, -1 (ид игрока (то есть любой))*/);
    4.  
    5. return true;
    6. }
    7.  
    8. public OnPlayerEnterDynamicArea(playerid,areaid)
    9. {
    10. if(areaid == g_areas[gExitHospital]) player_zone{playerid} = 1; // присваем
    11. return true;
    12. }
    13. public OnPlayerLeaveDynamicArea(playerid,areaid)
    14. {
    15. player_zone{playerid} = 0; // очищаем
    16. }


    Теперь отправляемся к нашему паблику OnPlayerKeyStateChange
    1. public OnPlayerKeyStateChange
    2. {
    3. switch(newkeys)
    4. {
    5. case KEY_WALK:
    6. {
    7. switch(player_zone{playerid})
    8. {
    9. case 1:
    10. {
    11. SetPlayerPos(playerid,/*устанавливаем свои координаты*/);
    12. /*
    13. Дальше убираем виртуальный мир и Т.Д
    14. */
    15. }
    16. default: return 0;
    17. }
    18. }
    19. }
    20. return true;
    21. }


    Код готов, если появятся вопросы либо исправить можно будет как то лучше, то напишите в теме, каждое предложение очень много стоит для меня
    Благодарю всех за внимание
    Последний раз редактировалось red.inc; 31.07.2019 в 10:15.

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

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Во-первых, слабоватый мануал. Я бы сказал, очень слабый :) Информации мало, она не структурирована, оформления нормального нет.

    Во-вторых, идея подобной оптимизации - такая себе. Стример ведь не каким-то волшебным образом узнаёт о том, зашёл ли игрок в динамическую зону или нет. Он постоянно получает позицию каждого игрока и сверяет его с ближайшими объектами/пикапами/зонами и т.п. И подобной "оптимизацией" ты вместо временной нагрузки от вызова IsPlayerInRangeOfPoint получаешь постоянную нагрузку от стримера. Сомнительная оптимизация :)

    Не говоря уже о том, что в коде не учитывается возможность того, что две или более динамические зоны будут накладываться друг на друга. В таком случае твой код просто будет работать некорректно :)
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

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

    Steve Pavlina

  3. #3
    Аватар для red.inc
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.07.2019
    Адрес
    Беларусь, Витебск
    Сообщений
    23
    Репутация:
    0 ±
    Насчёт твоих слов. В некоторых событиях согласен, в оформление я не специалист, важна простота в чтение.
    Хорошо, теперь давай насчёт зоны которую я указал, для начала это не так нагружает ЦП вашего компьютера, потом - не нужно устанавливать для кнопки ALT 100 функций, ведь можно просто через одно перечисление работать. К тому же и банкоматы, так же можно создать у каждого динамическую зону и не проводить проверки по нажатию ALT, где именно игрок находится, легче просто подходя к банкомату задать свой ИД и пользоваться им. Если уже говорить о оптимизации, тут уже можно спорить.

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

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от red.inc Посмотреть сообщение
    важна простота в чтение.
    В том и дело, что сейчас довольно трудно читать сей мануал :)
    Зайди в подраздел "Прочее", походи по темам и сравни их со своей.

    Цитата Сообщение от red.inc Посмотреть сообщение
    для начала это не так нагружает ЦП вашего компьютера,
    Замеры в студию)
    Хотя спойлер: с твоим вариантом нагрузка будет выше. Достаточно лишь знать как работает стример, чтоб понять это ;)

    Чтоб повторить принцип работы стримера, достаточно сохранить несколько координат вокруг какой-то точки на карте, запустить таймер на 1 секунду (хотя стример может и чаще делать проверки) и вставить в таймер проверки "IsPlayerInRangeOfPoint" с сохранёнными координатами. Получится та же самая система динамических зон, за исключением некоторых особенностей. И, как я уже сказал, вместо единоразовой нагрузки от проверок координат, ты заставишь стример постоянно проверять координаты относительно созданных тобой зон. Даже логически должно быть понятно, что такой подход не пахнет оптимизацией.

    Цитата Сообщение от red.inc Посмотреть сообщение
    потом - не нужно устанавливать для кнопки ALT 100 функций, ведь можно просто через одно перечисление работать
    Сути особо не меняется, кроме того, что вместо "IsPlayerInRangeOfPoint(...)" будет "case ...:"


    Цитата Сообщение от red.inc Посмотреть сообщение
    Если уже говорить о оптимизации, тут уже можно спорить.
    Существует такая штука, как "тестирование", которая помогает понять какой из вариантов ОБЪЕКТИВНО оптимизированнее. Сделаешь её и спорить сразу будет бессмысленно :)
    Последний раз редактировалось DeimoS; 30.07.2019 в 23:02.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

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

    Steve Pavlina

  5. #5
    Аватар для Kovshevoy
    Пользователь

    Статус
    Оффлайн
    Регистрация
    11.07.2015
    Сообщений
    190
    Репутация:
    25 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Во-первых, слабоватый мануал. Я бы сказал, очень слабый :) Информации мало, она не структурирована, оформления нормального нет.

    Во-вторых, идея подобной оптимизации - такая себе. Стример ведь не каким-то волшебным образом узнаёт о том, зашёл ли игрок в динамическую зону или нет. Он постоянно получает позицию каждого игрока и сверяет его с ближайшими объектами/пикапами/зонами и т.п. И подобной "оптимизацией" ты вместо временной нагрузки от вызова IsPlayerInRangeOfPoint получаешь постоянную нагрузку от стримера. Сомнительная оптимизация :)

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

  6. #6
    Аватар для red.inc
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.07.2019
    Адрес
    Беларусь, Витебск
    Сообщений
    23
    Репутация:
    0 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    В том и дело, что сейчас довольно трудно читать сей мануал :)
    Зайди в подраздел "Прочее", походи по темам и сравни их со своей.



    Замеры в студию)
    Хотя спойлер: с твоим вариантом нагрузка будет выше. Достаточно лишь знать как работает стример, чтоб понять это ;)

    Чтоб повторить принцип работы стримера, достаточно сохранить несколько координат вокруг какой-то точки на карте, запустить таймер на 1 секунду (хотя стример может и чаще делать проверки) и вставить в таймер проверки "IsPlayerInRangeOfPoint" с сохранёнными координатами. Получится та же самая система динамических зон, за исключением некоторых особенностей. И, как я уже сказал, вместо единоразовой нагрузки от проверок координат, ты заставишь стример постоянно проверять координаты относительно созданных тобой зон. Даже логически должно быть понятно, что такой подход не пахнет оптимизацией.



    Сути особо не меняется, кроме того, что вместо "IsPlayerInRangeOfPoint(...)" будет "case ...:"




    Существует такая штука, как "тестирование", которая помогает понять какой из вариантов ОБЪЕКТИВНО оптимизированнее. Сделаешь её и спорить сразу будет бессмысленно :)
    Хорошо. Я не умею проводить тестирование, у меня нету кода, который смог бы мне это проверить. Теперь переходим к моему коду, да происходит проверка ежесекунда, понимаю что можно сделать функцию, которая будет проверять местоположение по нажатию кнопки, к примеру ALT ,просто поставив через тот же самый areaid. Не знаю, попробую сейчас найти Cortez функцию, для тестирование. Потом отпишу

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

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от NichWell Посмотреть сообщение
    Стример разве не обрабатывает информацию в отдельном потоке (хотя я знаю шо Самп не многопоточен)? Посвятите нуфов, Владислав хД
    Нет, не в отдельном (исходники открыты, так что каждый может самостоятельно убедиться).
    Скажу даже больше: стример обрабатывает данные не тупо по таймеру, а каждые n тиков. И если ваш мод имеет много "тяжеловесного" кода, который забивает поток - функции стримера, по типу динамических зон, будут срабатывать с гораздо большей задержкой, чем, например, на пустом моде с тем же количеством объектов/зон и т.п.

    Стример - не панацея. Он несомненно является очень удобным инструментом, помогающим решать кучу проблем SA-MP, но использовать его нужно с умом :)


    Цитата Сообщение от red.inc Посмотреть сообщение
    Хорошо. Я не умею проводить тестирование, у меня нету кода, который смог бы мне это проверить.
    При этом, начал рассуждать на тему того, как твой код нагружает процессор и т.п. =)

    Цитата Сообщение от red.inc Посмотреть сообщение
    Теперь переходим к моему коду, да происходит проверка ежесекунда, понимаю что можно сделать функцию, которая будет проверять местоположение по нажатию кнопки, к примеру ALT ,просто поставив через тот же самый areaid. Не знаю, попробую сейчас найти Cortez функцию, для тестирование. Потом отпишу
    Тем скриптом ты ничего не проверишь. Тебе не скорость работы конкретного кода проверять нужно, а нагрузку от стримера посмотреть. Но для достаточно мощного процессора нагрузка там будет несущественна, поэтому можно просто посмотреть как сам стример начнёт тормозить.

    Возьми какой-нибудь крупный мод, в котором хотя бы 1000-2000 домов (важно, чтоб пикапы были достаточно сгруппированы хотя бы в одном каком-то месте), и вставь вот этот код сразу после стримера:

    1. stock t_CreateDynamicPickup(modelid, type, Float:x, Float:y, Float:z, worldid = -1, interiorid = -1, playerid = -1, Float:streamdistance = STREAMER_PICKUP_SD, STREAMER_TAG_AREA:areaid = STREAMER_TAG_AREA:-1, priority = 0)
    2. {
    3. CreateDynamicCircle(x, y, 5.0);
    4. return CreateDynamicPickup(modelid, type, x, y, z, worldid, interiorid, playerid, streamdistance, areaid, priority);
    5. }
    6. #if defined _ALS_CreateDynamicPickup
    7. #undef CreateDynamicPickup
    8. #else
    9. #define _ALS_CreateDynamicPickup
    10. #endif
    11.  
    12. #define CreateDynamicPickup t_CreateDynamicPickup


    А в OnPlayerEnterDynamicArea вставь что-нибудь типа такого
    1. new test_string[144];
    2. format(test_string, sizeof(test_string), "areaid: %d", areaid);
    3. SendClientMessageToAll(-1, test_string);


    После зайди на сервер и начни бегать от пикапа к пикапу, следя за тем, как стример поспевает определять твоё нахождение в той или иной динамической зоне.

    Динамические зоны сами по себе работают с некоторой задержкой, ибо там более сложный расчёт координат идёт, нежели для всяких пикапов и т.п. (поэтому автор стримера просто сделал больший интервал между проверками), и при увеличении их количества задержка будет только расти.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

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

    Steve Pavlina

  8. #8
    Аватар для red.inc
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.07.2019
    Адрес
    Беларусь, Витебск
    Сообщений
    23
    Репутация:
    0 ±
    Проведя несколько опытов, я решил немного по другому свой код сделать.
    Показатель дал такой разрыв - что лучше использовать просто IsPlayerDynamicArea.

    (IsPlayerInRangeOfPoint)
    Проверка по нажатию кнопки ALT - результат 8900 мс | 0 FPS

    (IsPlayerDynamicArea)
    Проверка по нажатию кнопки Y - результат 6048 мс | 0 FPS

    (OnPlayerDynamicArea)
    Проверка по нажатию кнопки N - результат 8365 мс | 0 FPS

    На кнопку была проверено 1000 игроками и 22 координаты (X,Y,Z), и результаты дали своё.
    В данном случае, я опустил голову, и считаю что мой способ, в данном случае был лучше конечно IsPlayerInRangeOfPoint, но вот показатель IsPlayerDynamicArea тоже показал себя отлично, на данный момент, пока нельзя сделать выводы.

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

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    IsPlayerInDynamicArea
    И эта функция в твоём случае вообще не применима, ибо динамические зоны могут вообще не относится к пикапам.

    Вообще обычно код теста прикладывают к результатам, дабы другие могли убедиться, что ты не допустил никаких ошибок в коде + могли сами сделать замеры, но в данном случае ты совершенно не понимаешь о чём я тебе говорю.

    Да, если сравнивать конкретную нагрузку от нажатия на кнопку, то твой вариант будет быстрее IsPlayerInRangeOfPoint. Но ты совершенно не учитываешь то, что стример, чтоб узнать в какой из зон находится игрок, постоянно сверяет его координаты со всеми ближайшими зонами. И в результате ты получаешь, вместо единовременной нагрузки от IsPlayerInRangeOfPoint, постоянную нагрузку от стримера, который будет следить за тем, в какой зоне находится игрок.

    Я уже писал, что схожий результат можно получить без стримера, сделав как-то так:
    1. {
    2. SetTimer("@__SomeTimer", 1000, true);
    3. }
    4.  
    5. new PlayerInAreaID[MAX_PLAYERS];
    6.  
    7. public OnPlayerConnect(playerid)
    8. {
    9. PlayerInAreaID[playerid] = -1;
    10. return 1;
    11. }
    12.  
    13. @__SomeTimer();
    14. @__SomeTimer()
    15. {
    16. foreach(new i: Player)
    17. {
    18. if(IsPlayerInRangeOfPoint(playerid, /*Радиус*/, /*координата x*/, /*координата y*/, /*координата z*/))
    19. {
    20. PlayerInAreaID[playerid] = 1;
    21. }
    22. else if(IsPlayerInRangeOfPoint(playerid, /*Радиус*/, /*координата x*/, /*координата y*/, /*координата z*/))
    23. {
    24. PlayerInAreaID[playerid] = 2;
    25. }
    26. else if(IsPlayerInRangeOfPoint(playerid, /*Радиус*/, /*координата x*/, /*координата y*/, /*координата z*/))
    27. {
    28. PlayerInAreaID[playerid] = 3;
    29. }
    30. // И так далее. Тут перечисляются координаты для всех мест, где должна срабатывать кнопка
    31. else
    32. {
    33. PlayerInAreaID[playerid] = -1;
    34. }
    35. }
    36. }
    37.  
    38. public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
    39. {
    40. if(newkeys & KEY_YES)
    41. {
    42. if(PlayerInAreaID[playerid] != -1)
    43. {
    44. switch(PlayerInAreaID[playerid])
    45. {
    46. case 1:
    47. {
    48. // Действие для зоны под ID 1
    49. }
    50. case 2:
    51. {
    52. // Действие для зоны под ID 2
    53. }
    54. case 3:
    55. {
    56. // Действие для зоны под ID 3
    57. }
    58. // И так далее
    59. }
    60. }
    61. }
    62. return 1;
    63. }

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


    Если ты действительно хочешь избавиться от кучи проверок координат при нажатии клавиш, лучше реализовать всё через пикапы: создать на каждой точке пикап и когда игрок будет его подбирать, записывать его ID и уже в OnPlayerKeyStateChange проверять этот самый ID + получать координаты пикапа через Streamer_GetFloatData, проверяя их с позицией игрока через IsPlayerInRangeOfPoint, дабы читеры не могли спокойно телепортироваться, передавая фейковые ID пикапов.

    Вот тут у тебя действительно будет оптимизация, ибо сверкой координат пикапов занимается не сервер, а движок игры у каждого конкретного игрока и уже сам игрок отсылает то, какой пикап он взял. В итоге у тебя получится всего лишь один вызов IsPlayerInRangeOfPoint.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

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

    Steve Pavlina

  10. #10
    Аватар для red.inc
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.07.2019
    Адрес
    Беларусь, Витебск
    Сообщений
    23
    Репутация:
    0 ±
    Хорошо, проверить идею с пикапом, интересная задумка. После замеров, я напишу, как раз таки может и поменяю свой выбор.

 

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

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

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

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

Ваши права

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