Перейти к содержимому

Как делать скрипты для игр

  • автор:

Туториал 0: Юнити и C# скрипт — основы

Скажу честно, я не программист, так что вполне возможно будут какие-то неточности. Это не игровой туториал. Я постараюсь рассказать, как работают скрипты в Юнити 3Д.

С# относительно не сложный язык. Точнее сама основа языка простая, сложности начинаются, когда уже совсем далеко углубляешься в него. Но на самом деле с помощью Юнити3Д можно делать простенькие игрушки только используя основы С#. C# объектно ориентированный язык програмирования. Это пишут все, но как я понял большинство не особо понимает смысл этого, как и я. Но учитывая, что придется работать со скриптами, это не так и важно для начала. Не стоит пытаться создать один огромный трудно понимаемый скрипт для всей игры. Пробуйте разделить игру на части. В свою очередь эти части могут взамодействовать друг с другом. Используйте эти части как кирпичи для создания итоговой игры. В C# используется class, который исполняет роль кирпичика. В Юнити довольно просто создать такой class. Создаете новый C# скрипт и называете его по желанию. И, грубо говоря, созданный скрипт и выполняет роль class в Юнити3Д. Далее можно использовать скрипт как компонет для игрового объекта.

Небольшой пример:

Как пример, решили сделать простенькую космическую стрелялку. Что-то похожее на этот шедевр:

В Юнити3Д это будет сцена с множеством игровых объектов: фон, звезды, камера, враг, астероид, игрок. Каждый объект в игре это GameObject. И все GameObjects состоят из Components. Некотрые компоненты заранее заготовленны в Юнити3Д. Как пример: Transform (определяет позицию объекта в пространстве), Sprite Renderer (рисует заданный объект в мире), UI Text (показывает текст в интерфейсе) и много других компонентов. И ваши C# скрипты тоже будут компонентами, которые будут присоединяться к объектам. У C# скриптов есть доступ к другим компонетами. По сути, вся работа со скриптами это просто работа с переменными.

Как использовать C# скрипты ?

Создадим empty GameObject(пустышку) в сцене. У этого объекта уже будет Transform компонент (у каждого объекта в Юнити3Д есть Transform компонент). У созданного объекта пока нет компонента отвечающего за отрисовку, поэтому мы не увидим его игре. Поэтому добавим ешё один компонент Sprite Renderer. И укажем какую картинку должен рисовать этот компонент, например астероид. Тогда мы сможем увидеть астероид в игре.

Просто смотреть на астероид скучно, поэтому можно сделать скрипт для его управления.

Не забываем, это не игровой туториал, только вкратце о принципе работы с Юнити3Д.

Создаём новый С# скрипт и называем его(например Moving, так как этот скрипт будет перемещать астероид). Если мы откроем скрипт, то увидим следующую заготовку:

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

// Use this for initialisation
void Start () >

//Update is called once per frame
void Update () >
>

Небольшое объяснение строчек:

Using UnityEngine; Добавляем доступ на UnityEngine библиотеку. Это набор различных классов/функций от Юнити3Д.
using System.Collections; Это стандартная библиотека от Microsoft .NET.
public class Moving : MonoBehaviour

public даёт возможность доступа на этот скрипт с других скриптов. class Moving название нашего скрипта/класса. MonoBehaviour это основной класс от Юнити3Д, в нём такие важные функции как Update(), Start (). Смотрите Unity Documentation для более точного описания.
// Use this for initialization Это просто комментарий. Только для вашего удобства.
void Start () <> void Обозначение, что последующая функция не будет возвращать параметр (то-есть никаких вернувшихся переменных после её вызова не намечается). Start () <> эта функция выполнится один раз при старте скрипта.
void Update () <> Эта функция будет выполняться заново каждый игровой кадр.

Теперь мы можем передвинуть астероид в центр игрового мира (находится на координатах (0, 0, 0)). Позиция игрового объекта определяется в Transform компоненте. Нам надо присоединить наш скрипт к астероиду. С этого скрипта мы можем менять переменные в Transform компонент. Эти переменные и определяют положение объекта в сцене.

Например мы хотим переместить астероид в центр при старте игры.

Если надо получить доступ на какой-то компонент игрового объекта, то обычно надо сделать следующие шаги:

1. Найти нужный игровой объект: Тут много разных вариантов, все зависит от условий.
— Можно использовать поиск из C# скрипта GameObject.Find («Name») / GameObject.FindWithTag («Tag»). Это поиск по имени или тэгу.
— можно создать переменную типа игровой объект public GameObject; и потом в эдиторе указать к какому объекту привязана эта переменная.
— можно получить линк на игровой объект с различных функций. Например: (Trigger, Raycast. ).
— и не нужен поиск объекта, если скрипт уже находится на этом объекте.

2. Получить доступ на компонент этого объекта: через команду gameobject.GetComponent (); или GetComponent (); если скрипт на том-же объекте.

Доступ к Transform компоненту:

Для удобства есть простой путь доступа на свой Transform компонент, если компонент и скрипт находятся на одном объекте. Просто используете transform. Для доступа на другие компоненты используйте GetComponent (в старых версиях Юнити таких быстрых доступов было больше, не забываем об этом при работе с неактульными туториалами)

Позиция в игровом мире это вектор (x,y,z). Если мы хотим поместить астероид в центр, то нам надо изменить координаты вектора на (0,0,0). C# строчка будет:
transform.position = new Vector3 ( 0 , 0 , 0 );
Если мы хотим сделать это перемещение один раз в начале игры, то нам надо поместить эту строчку в функцию void Start () <> . И наш скрипт будет:

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

// Use this for initialisation
void Start () //сменить местоположение игрового объекта
transform.position = new Vector3 ( 0 , 0 , 0 );
>

//Update is called once per frame
void Update () >
>

Если мы запустим нашу игру, то астероид будет перемещён в центр игрового мира.
Теперь посмотрим на Transform компонент:

Используйте команду transform. для доступа к Transform компоненту на том-же игровом объекте. И в нём можно изменить позицию, вращение и размер игрового объекта (пример: transform.localScale = new Vector3 (0.5F, 1, 1);). Ваш IDE (редактор) будет пытаться помочь в наборе команд и будут показанны различные возможные варианты.

Можно не только изменять переменные, но и просто запросить их значения.

Теперь посмотрим как работать с другими компонентами. У нашего астероида есть компонент для его отрисовки (рендерер).

Например мы хотим зеркально повернуть астероид вдоль y-оси. Так как наш скрипт уже прикреплён к астероиду, то нам не нужен его поиск в игровом мире. Мы можем получить доступ на компонент командой GetComponent ().. Название компонента можно посмотреть в инспекторе игрового объекта (только осторожно с пробелами). C# команда будет:
GetComponent< SpriteRenderer >().flipY = true ;
И скрипт будет:

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

// Use this for initialisation
void Start () //сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//доступ к компоненту отрисовки и сменить переменную, отвечающую за зеркальное отображение по оси Y
GetComponent< SpriteRenderer >().flipY = true ;
>

//Update is called once per frame
void Update () >
>

Не забываем, при наборе кода ваш IDE будет пытаться показывать возможные варианты.

Обычно, если планируете работать часто с каким-нибудь компонентом, то лучше сделать ссылку на этот компонент. Для этого вам надо создать ссылочную переменную того же типа, что и компонент (тип переменной будет как и название компонента). И потом указать ссылку на этот компонент GetComponent (). Потом сможете использовать эту переменную для быстрого доступа к компоненту.

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;

// Use this for initialisation
void Start () //сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
>

//Update is called once per frame
void Update () >
>

Похожим образом мы можем получить и доступ к компонентам на других игровых объектах.
Для начала нам надо «найти» другой игровой объект. Как я уже и писал, тут довольно много различных вариантов в зависимости от ситуации. Например в сцене есть другой игровой объект. Его имя Ship и тэг Player (Tag используется для идентификации объектов (похоже на имя, только скорость обработки быстрее)).

1. Если игровой объект находится в сцене с самого начала и не пропадает до запроса к нему, то мы можем создать открытую ссылочную переменную playerShip (с тимпом GameObject) в нашем скрипте и добавить этот объект в эту переменную через инспектор (просто перетащить объект на переменную в редакторе). И тогда через эту переменную у нас будет доступ на игровой объект. Например мы хотим поместить корабль на позицию (1, 1, 0) при старте игры. C# строчка будет:
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;
//публичная ссылочная переменная для корабля игрока
public GameObject playerShip;

// Use this for initialisation
void Start () //сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
//получаем доступ к transform компоненту игрока и меняем его местоположение
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
>

//Update is called once per frame
void Update () >
>

2. Мы можем найти игровой объект в сцене через поиск и сделать на него ссылку через скрипт с помощью команды GameObject.Find («Name») or GameObject.FindWithTag («Tag»). Поиск по тэгу производится быстрее чем по имени. C# строчка будет:
playerShip = GameObject .Find( «Ship» );
или:
playerShip = GameObject .FindWithTag( «Player» );

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;
//публичная ссылочная переменная для корабля игрока
public GameObject playerShip;

// Use this for initialisation
void Start () //сменить местоположение игрового оьъекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
//ищем в сцене корабль игрока и делаем ссылку на него
playerShip = GameObject .FindWithTag( «Player» );
//получаем доступ к transform компоненту игрока и меняем его местоположение
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
>

//Update is called once per frame
void Update () >
>

Не забываем: используйте GetComponent ();, если хотите получить доступ на отличный от Transform компонент (transform. это просто укороченный вариант для этого компонента). Например если хотите зеркально повернуть корабль по X-оси из скрипта на астероиде, то комманда в C# будет:
playerShip.GetComponent < SpriteRenderer >().flipX = true ;

using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

//декларация ссылочной переменной для компонента отрисовки спрайтов
SpriteRenderer sr;
//публичная ссылочная переменная для корабля игрока
public GameObject playerShip;

// Use this for initialisation
void Start () //сменить местоположение игрового объекта
transform.position = new Vector3 ( 0 , 0 , 0 );
//делаем ссылку на компонент
sr = GetComponent< SpriteRenderer >();
//меняем переменную, отвечающую за зеркальное отображение по оси Y
sr.flipY = true ;
//ищем в сцене корабль игрока и делаем ссылку на него
playerShip = GameObject .FindWithTag( «Player» );
//получаем доступ к transform компоненту игрока и меняем его местоположение
playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
//указываем, что работаем с кораблем игрока, получаем доступ к компоненту отрисовки и зеркально отображаем по оси Х
playerShip.GetComponent < SpriteRenderer >().flipX = true ;
>

//Update is called once per frame
void Update () >
>

3. Мы можем получть объект с различных игровых функций. Я покажу некотрые из них в последующих туториалах (как пример: OnTriggerEnter2D (Collider2D otherCollider) <> Ссылка на объект попавший в триггер будет в otherCollider переменной).

Наверняка уже заметили, что создание игры в Юнити — это просто работа с переменными в компонентах игровых объектов (я сейчас не говорю о создании музыки, моделей, текстов . Это уже совсем другая история). Теперь посмотрим на основы С# скриптов. Описание будет довольно коротким и затронет только базовые части. Так что для подробностей придется немножко погуглить или побродить по форумам.

Основы С# скриптов:

1. Переменные:

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

Spoiler int:
Этот тип переменных может принимать значение целого (не дробного) числа. Переменная лежит в диапазоне от -2 147 483 648 до 2 147 483 647. Обычно используется для подсчета количества объектов или индексации массивов/циклов (о них чуть позже). int score;
int healthPoint = 5 ;
float:
Этот тип для чисел с плавающей запятой (дробные числа). Переменная лежит в диапазоне от -3.4 × 10^38 до +3.4 × 10^38. Обычно используется там, где важна дробная часть (как пример — расстояние до цели). Используйте точку для разделения знаков. float speed;
float distanceToShoot = 10.5 ;
bool:
Это тип переменных имеющих всего два значения true/false (истинно/ложно). Используется в проверке условий (условные операторы). bool isDead;
bool canMove = false;
char:
Тип переменных для символов Юникода. Например отдельные буквы. Используйте одинарные кавычки при инициализации. char litera;
char firstLitera = ‘A’ ;
string:
Тип переменных для символьной последовательности/текст (на самом деле это ссылочная переменная, то есть в ней хранится ссылка на область памяти, где находится эта символьная последовательность. Но её принцип работы похож на обычные переменные). В классе string содержится несколько функций. Одна из них string.Length, позволяющая узнать количество символов в строке. Для инициализации используйте кавычки. string newText;
string enemyText = «Stop! Don’t move»;
//пример использования функции string.Length
int howManyLetters = enemyText.Length; Vector3:
Я поместил вектор3 к обычным переменным, но на самом деле это структура. Структуры довольно похожи на классы, но в отличии от класса со значениями стурктуры можно работать напрямую, а не через ссылку. Поэтому они частично похожи на переменные. Возможны арифметические операции. Далее структура Vector3 содержит довольно много функций для работы с векторами. Смотрите Unity Documentation для более точного описания. При инициализации вектора3 надо создавать новую инстанцию с помощью new или использовать уже существующий вектор3 (тогда будет созданна его копия). Часто используется для определения местоположения объектов или их скорости и направления движения. Vector3 move;
Vector3 enemyPos = new Vector3 ( 1 , 1 , 0 );
//считывание длинны вектора
float vectorLength = enemyPos.magnitude; Существуют и другие векторы. Например Vector2 или Vector4, но принцип их работы не отличается (кроме многомерности). var:
Это ключевое слово, с помощью которого можно задекларировать переменную без обозначения её типа. Тип переменной будет определен позже в контексте программы. var summe;
float a = 1 ;
float b = 1 ;
//переменная summe получит тип float
summe = a + b;

2. Ссылочные переменные классов:

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

Spoiler GameObject:
Все объекты в сцене Юнити это игровые объекты. Поэтому GameObject как базовый класс используется довольно часто. Как и большинство классов содержит в себе не только различные переменные, но и функции. Смотрите Unity Documentation для более точного описания. GameObject player;
//поиск оьъекта с тэгом Enemy и создание переменной с ссылкой на него
GameObject enemy = GameObject .FindWithTag ( «Enemy» );
Transform:
Один из очень часто используемых компонентов. Этот компонент есть у любого игрового объекта в Юнити. Отвечает за местоположение и размеры объекта в игровом мире. Так как в Юнити есть упрощённый доступ к компонету Transform у игрового объекта через команду gameobject.transform. , то используется как ссылочная переменная не так уж и часто. Смотрите Unity Documentation для более точного описания. Transform enemyPosition;
//считывание координаты х из трансформ компонента
float x = enemyPosition.position.x;
Sprite:
Класс представляющий 2Д картинку (спрайт) в качестве рессурса в Юнити. Если вы импортируете спрайт в Юнити, то будет автоматически создан новый класс содержащий этот спрайт с его различными настройками. В качестве ссылочной переменной понадобится при работе с компонентом отрисовки спрайтов. Смотрите Unity Documentation для более точного описания. Sprite enemyBullet;
SpriteRenderer:
Класс отвечающий за отрисовку (рендеринг) спрайта на экране. Рессурс для отрисовки берется из Sprite (см. выше). Как и большинство компонентов содержит в себе различные переменные и функции. Смотрите Unity Documentation для более точного описания. SpriteRenderer sr;
//активация переменной, отвечающей за зеркальное отображение по оси Y
GetComponent< SpriteRenderer >().flipY = true ;
С# скрипты и другие компоненты:
Как я уже говорил, ваши скрипты являются компонентами в Юнити. Поэтому ссылочные переменные работают аналогичным образом.
1. создаёте переменную по типу компонента (используйте его название).
2. получаете доступ к компоненту через ссылочную переменную: variable = GetComponent ();

В качестве примера скрипт из вступления: Moving moving;
moving = GetComponent< Moving >();
moving.playerShip.transform.position = new Vector3 ( 1 , 1 , 0 );
Все остальные компоненты работают аналогично. Не стану их описывать, так как их просто огромное количество.

3. Массивы (статические и динамические):

Массив это упорядочненая структура данных состоящая из элементов одного типа. Массивы могут быть не только одномерными, но и многмерными. Все элементы массива проиндексированны, для целенаправленного доступа к ним. Статический массив имеет определённый размер (количество элементов), который нельзя изменить после декларации. Размер динамического массива можно менять. Индексация массива начинается с 0, то есть первый элемент массива имеет индекс [0].

Spoiler статические массивы:
Так как размер такого массива заранее определен, то скорость работы с таким массивом выше. Поэтому используйте статические массивы, если размер массива заранее известен и будет постоянен. //декларация двумерного массива типа int, состояшего из 2*5 элементов
int [,] numbers = new int [ 2 , 5 ];
//декларация одномерного массива типа GameObject, размер массива определяется через инспектор игрового объекта
public GameObject [] enemy;
//декларация одномерного массива типа string, c его последующей инициализацией
string [] animals = new string [2] < "кот" , "собака" >;
динамические массивы:
Динамические массивы используют класс List. Этот класс находится в пространстве System.Collections.Generic, поэтому лучше присоединить это пространство к скрипту с помощью using System.Collections.Generic;. Динамические массивы позволяют различные действия с размером массива. Можно добавлять, вставлять и удалять элементы. Смотрите MSDN для более точного описания. //присоединение пространства для работы с классом List
using System.Collections.Generic;
//декларация динамического массива типа string
List < string >cars = new List < string >();
//добавление к массиву нового элемента
cars.Add( «Запорожец» );
//вставка нового элемента в массив как первый элемент
cars.Insert(0, «Ауди» );
//удаление элемента «Запорожец»
cars.Remove( «Запорожец» );

4. Модификаторы доступа:

В С# переменные могут быть с разным уровнем доступа. Уровень доступа определяет возможность обращения к переменной.

Spoiler private:
По умолчанию (если вы никак не обозначили переменную) она получает приватный уровень доступа. Так же этот уровень можно и указать с помощью private. Доступ к таким перменным возможен только внутри их содержащих классов. float speed;
private int score;
public:
Уровень доступа public даёт неограниченный доступ. Например такие переменные можно изменить из других классов. Так же переменная с публичным доступом будет видна в редакторе, это даёт возможность её настройки через инспектор. У компонентов в Юнити публичный уровень доступа. public float speed;
public GameObject player;
protected:
Уровень доступа для базового и наследуемых классов.

5. Области видимости(действия) переменных:

Место декларации переменной определяет область её видимости в содержащем скрипте.

Spoiler глобально в классе:
Переменная декларированная в классе, но не входящая в функции этого класса может быть использована глобально всеми функциями этого класса.
локально в функции:
Переменная декларированная в функции, может быть использована только в этой функции.
локально в цикле:
Область видимости такой переменной ещё меньше, она используется только локально в пределах цикла. using UnityEngine;
using System.Collections;

public class Moving : MonoBehaviour

//переменная speed может быть использованна любой функцией этого класса
public int speed;

void RandomFunction () //переменная isMoving может быть использованна только в пределах RandomFunction () <. >
bool isMoving = true;
//переменная i может быть использованна только в пределах цикла
for ( int i = speed; i < 0 ; i--) speed = i;
>
isMoving = false;
>
>

6: Арифметические операторы:

С переменными, содержащими значения, возможны различные арифметические действия. Тут приведу только основные примеры.

Spoiler Будьте осторожны при арифметических действиях с разными типами переменных. Если например записать дробный результат в целую переменную, то дробная часть потеряется. float a = 10 ;
float b = 5 ;
float c;
//сложение: c = 10 + 5
c = a + b;
//вычитание: a = 10 — 2
a = a — 2 ;
//деление: b = 8 / 2
b = a / 2 ;
//умножение: с = 10 * 1.5
с = 10 * 1.5 ;
//присвоение: a = 15
a = c;
//инкремент: увеличение а на единицу
a++;
//декремент: уменьшение а на единицу
a—;
//инкремент/декремент: могут стоять до или после переменной, изменяя порядок вычислений

7. Математические функции:

В С# есть структура Mathf для различных математических функций. Смотрите Unity Documentation для более точного описания.

Spoiler //функция вернет значение -1, так как проверочный результат отрицательный
float sign = Mathf .Sign (-5);

8. Условия и логические операторы:

Для разветвления (выбора другого варианта исполнения) программ есть различные условные операторы. Для сравнения вариантов используются логические операторы сравнения.

Spoiler логические операторы сравнения:
Результат сравнения это бинарный результат, то есть ложно или истинно (true/false). Возможны следующие сравнения:
== — равно
!= — не равно
> — больше
< - меньше
>= — больше или равно

условные операторы:
Условные операторы позволяют провести сравнение и выполнить определенную часть кода в зависимости от результата.
if . else:
Краткая форма этого условного оператора состоит только из условия и выполняемой части кода, если условие истинно. if (hp isDead = true ;
canFight = false ;
> Полная форма состоит из условия, выполняемой части кода, если условие истинно и выполняемой части кода, если условие ложно. if (hp isDead = true ;
canFight = false ;
> else isDead = false ;
canFight = true ;
> Возможно объединение различных условий в одну конструкцию. if (hp isDead = true ;
canFight = false ;
> else if (hp == 100 ) isDamaged = false ;
> бинарные логические операторы:
С помощью таких операторов можно создавать более сложные условия, состоящих из нескольких подусловий.
&& — логическое И . Будет истинно, если оба условия истинны. Или ложно, если оба или одно из них ложно.
|| — логическое ИЛИ . Будет истинно, если одно из условий истинно. И ложно, если оба условия ложны.
if (hp < 0 || hp >0 ) isZero = false ;
> else isZero = true ;
> switch:
Этот логический оператор используется для обработки множества вариантов при нахождении истинного значения. string direction = «left» ;

//искомое выражение
switch (direction) //возможный вариант, если совпадает, то выполняется последующий код
case ( «up» ):
move = Vector2 .up;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//возможный вариант, если совпадает, то выполняется последующий код
case ( «down» ):
move = Vector2 .down;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//в данном примере выполнится эта часть кода и работа логического оператора будет завершена
case ( «left» ):
move = Vector2 .left;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//возможный вариант, если совпадает, то выполняется последующий код
case ( «right» ):
move = Vector2 .down;
isMoving = true ;
//прерывает дальнейшее выполнение логического оператора (при совпадении варианта)
break ;
//если ни один из вариантов не был истинной, то выполняется часть кода стоящая после default
default :
move = Vector2 .zero;
isMoving = false ;
//прерывает дальнейшее выполнение логического оператора
break ;
>

9. Циклы:

Циклы используются для многократного исполнения определенных задач (фрагментов кода).

Spoiler for:
Этот цикл выполняется определённое количество раз. //для примера, декларация массива на 10 целых элементов
public int [] numbers = new int [ 10 ];

//int i = 0; декларация с инициализацией счетчика цикла
//i < 10;проверка возможности запуска следующего цикла (пока условие истинно)
//i++; изменение счетчика цикла
for ( int i = 0 ; i < 10 ; i++) //исполняемая часть кода при каждом новом цикле
//в данном примере, заполнение массива числами от 0 до 9
numbers [i] = i;
> Хоть это и не обязательно, но советую использовать в счетчиках циклов целые значения, чтобы избежать ошибок от дробных вычислений.

while:
Этот цикл выполняется пока условие истинно. //для примера, декларация массива на 10 целых элементов
public int [] numbers = new int [ 10 ];
//декларация с инициализацией переменной к, которую будем использовать для проверки условия цикла
int k = 9 ;

//проверка условия цикла, выполнить цикл, если условие истинно
while (k >= 0 ) //выполняемый фрагмент кода в фигурных скобках
//заполнение массива числами от 9 до 0 в обратном порядке
numbers [k] = k; //уменьшение переменной на 1 (чтобы получить ложное условие)
k—;
> Будьте осторожны с циклами, чтобы не получить «вечный» цикл, когда условие всегда истинно и цикл повторяется вечно.

do. while:
Отличие этого цикла от цикла while только в том, что проверка условия производится после выполнения фрагмента кода. Поэтому этот цикл выполнится всегда как минимум один раз. //декларация публичной текстовой переменной
public string testText;
//декларация и инициализация целой переменной, для условия цикла
int j = 0 ;

//выполнение фрагмента кода цикла
do //добавление к текстовой переменной цифры преобразованной в текстовый символ
testText = testText + j.ToString();
//увеличение j на единицу
j ++;
//проверка условия, повторить цикл, если условие истинно
> while (j < 10 );
//результат работы цикла это текст «0123456789»
foreach:
Цикл для работы с массивами. Перебирает все элементы по одному. //декларация и инициализация массива
int [] numbers = new int [ 5 ] < 21 , 28 , 13 , 4 , 15 >;
//декларация массива для копирования
int [] numbersCopy = new int [ 5 ];

//вспомогательная переменная для индекса массива
int i = 0 ;
//запуск цикла проходяшего по всем элементам массива
//переменная number должна совпадать с типом элементов массива
foreach ( int number in numbers) //копирование текущего элемента в другой массив
numbersCopy [i] = number;
//увеличение индекса на 1, для доступа к следующему элементу в массиве для копии
i++;
>
//итог цикла это копирование элементов в новый массив
операторы break и continue:
Эти операторы помогают управлять исполнением циклов.
break — этот оператор полностью прекращает цикл и переходит к дальнейшему исполнению программы
continue — этот оператор прекращает текущее исполнение цикла и начинает новое
//вспомогательная переменная для индекса массива
int i = 0 ;
//запуск цикла проходяшего по всем элементам массива
//переменная number должна совпадать с типом элементов массива
foreach ( int number in numbers) //копирование текущего элемента в другой массив
numbersCopy [i] = number;
//увеличение индекса на 1, для доступа к следующему элементу в массиве для копии
i++;
//как переменная для индекса стала равна 3, прекращаем исполнение цикла
if (i == 3 )
break ;
>

10. Функции:

Функция это обособленный фрагмент кода для выполнения определенной задачи. Функция может вызываться многократно в тех случаях, когда нужно решить эту задачу. Это позволяет избежать повторения кода. Функции могут быть как сделанные вами индивидуально для достижения ваших целей, так и заготовками от Юнити для стандартных решений. Функции являются частью классов. Функции, как и переменные, имеют различные уровни доступа. К public функциям возможен доступ из других классов, доступ к private функциям возможен только внутри их содержащих классов. Для работы функциям могут понадобиться входные данные — аргументы (функции могут использовать и глобальные переменные их содержащих классов). После своей работы функция может возвращать какой-то результат (используйте Return для возвращения результата). Тип функции должен соответсвовать типу возвращаемого результата. Существуют и функции не возвращающие результат, такие функции имеют тип void.

Spoiler стандартные функции от Юнити:
Существует много различных функций в Юнити. Тут я точно не смогу показать и малой части. Поэтому пока ограничимся несколькими примерами. В дальнейшем в туториалах будут попадаться и новые функции.

Instantiate:
Эта функция помещает клон объекта в сцену. Обычно используется для клонирования префаба(образца). //создаёт клон префаба в сцене на заданной позиции (Vector3) с заданным вращением (Quaternion)
Instantiate (prefab, position, rotation); Destroy:
Эта функция удаляет объект из сцены. //удаляет игровой объект из сцены после заданного интервала (или сразу, если время не указать)
Destroy (gameobject, time); функции классов:
Часто, если используете какой-то компонент (класс), то он содержит различные функции для работы с ним. Список этих функций можно увидеть в редакторе C# после набора ссылочной переменной (+ точка) указывающей на этот компонент. //изменяет дробную переменную в компоненте аниматор
GetComponent < Animator >().SetFloat ( «Speed» , 0 );
функции пользователя:
Конечно можно использовать и свои функции для выполнения нужных задач. //функция нанесения повреждений
public void DoDamage ( int damage) hp = hp — damage;
if (hp Destroy (gameObject);
>

11. События:

События похожи на функции, только их запуск привязан к различным событиям. Приведу только несколько примеров.

Spoiler void Awake() //это событие вызывается один раз при загрузке скрипта. Обычно используется для инициализации объектов.
void Awake() //C#
> void Start() //это событие вызывается один раз после того, как все void Awake() были выполнены. Используется для инициализации переменных.
void Start() //C#
> void Update() //это событие вызывается заново каждый новый кадр. Обычно содержит основной код для управления игровым объектом.
void Update() //C#
> void LateUpdate() //это событие вызывается заново каждый новый кадр после обработки всех Update(). Обычно используется для управления камерой, чтобы отрисовать уже готовую сцену.
void LateUpdate() //C#
> void FixedUpdate() //это событие вызывается через фиксированный интервал (стандарт 0.02). Используется в расчетах физики (физика не считается в Юнити каждый кадр).
void FixedUpdate() //C#
> OnTriggerEnter2D()
Возможны и другие варианты срабатывания триггера (Enter, Exit, Stay). //это событие вызывается при попадании коллайдера2Д в триггер2Д. Переменная other будет содержать ссылку на попавший в триггер объект.
void OnTriggerEnter2D( Collider2D other) //C#
>

Создай свою игру. Часть 9 – Базовые скрипты

Вот наконец-то ожидаемая и наводящая ужас глава Семинара Чурреры: Базовые скрипты. В девятой главе мы рассмотрим в забавной и детализированной форме систему скриптов, позволяющую нам максимально персонализировать нашу игру с применением различных функций. За нашими клавиатурами открывается целый новый мир. Используйте эту «силу» с умом. И помните, что с великой силой приходит и великая ответственность.

Глава 9: Базовые скрипты

Базовые скрипты?

Да, так точно. А этой главе мы пропишем сценарий Dogmole Tuppowski и научимся некоторым базовым принципам скриптов.

Система скриптов Чуррера очень простая, и кажется сильно ограниченной, но приложив немного умения, ты сможешь делать и более сложные системы. К тому же, в каждой новой версии Чуррера мы добавляем новые функции, так что при некотором опыте ты сможешь делать для своих игр довольно мудреные сценарии. Правила Dogmole специально созданы простыми, чтобы показать простое поведение и на них научиться. Дальше мы увидим скрипты различных мохоновских игр, чтобы ты увидел, какие штуки нам удалось сделать.

Система скриптов содержит множество команд и различных проверок. Так как я не хочу из этого урока делать нескончаемый список, я предлагаю тебе обратиться к архиву motor_de_clausulas.txt, который находится в папке /script Чурреры: там есть список всего того, что msc может скомпилировать. Ни одного чурроса там не забыли.

Освежим наши знания

Мы помним, что скрипт состоит из секций, и каждая секция включает условия. Условие – это просто список проверок и команд: если все проверки получают положительный результат, команды выполняются.

Мы контролируем выполнение условий, прописывая их в ту или иную секцию. Мы помним, какие есть секции, и когда они выполняются:

ENTERING GAME: Эта секция выполняется только при начале игры.

ENTERING ANY: Эта секция выполняется при входе на каждый экран, и когда мы встаем на врага. Да, никакой логики тут нет, но это так, потому что так удобнее для некоторых явлений.

ENTERING SCREEN n: Эта секция выполняется при входе на экран N.

PRESS_FIRE AT ANY: Эта секция выполняется при нажатии на кнопку действия, не важно, в каком окне мы находимся.

FRESS_FIRE AT SCREEN n: Эта секция выполняется при нажатии на кнопку действия, если мы находимся в окне N, и когда мы встаем на врага. Тоже никакой логики, но это удобно.

ON_TIMER_OFF: Эта секция выполняется, если у нас есть таймер, который дошел до 0, и мы прописали это в config.h.

Вперед!

Перед тем как начать, вспомним, почему важно точно знать, что мы делаем. Так что вспомним сценарий нашей игры Dogmole Tuppowsky:

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

Дальше нам надо запрограммировать логику подиума, находящегося внутри университета. Если дотронуться до подиума, доставляя туда ящик, ящик вычитается из нашего арсенала, а флаг, считающий количество доставленных предметов, увеличивается. Когда это количество доходит до 10, игра выиграна.

Скрипт этой игры будет очень простой. Прежде всего, нам надо разместить несколько флагов для сохранения. В нашем случае, так как движок сам считает убитых, нам надо только считать доставленные ящики, и нам надо помнить, убран ли камень или нет. Мы будем использовать 2 флага: 1 и 3. Почему эти два, а не какие-нибудь другие? Да потому что. На самом деле, это абсолютно все равно.

Мы помним из прошлой главы, что было бы интересно определить, что делает каждый флаг в начале нашего скрипта:

# 1 – общий подсчёт предметов

# 3 – 1 = дверь университета открыта.

Считаем мертвяков

Видел название, а? Прежде всего, посмотрим, как считать мертвяков, чтобы избавиться от камня во втором окне. Для начала посмотрим, что нам надо убрать. Вот второе окно, и я показал камень, который нам надо убрать через скрипт:

piedro

Если посчитаем, увидим, что камень занимает координаты (12, 7). Ставим их.

Мы говорили, что будем использовать флаг 3, чтобы помнить, убили ли мы уже всех врагов. Если флаг 3 равен 1, то это значит, что мы убили всех врагов, и в этом случае окно должно быть изменено: камень должен исчезнуть из точки, которую мы уже определили. Почему бы отсюда и не начать? Создаем условие, которое выполняется при входе на экран 2:

# Вход в университет ENTERING SCREEN 2 # контроль двери университета. IF FLAG 3 = 1 THEN SET TILE (12, 7) = 0 END END

Особенно ничего нового в этом условии сценария мы не написали: речь идет о проверке значения флага. В случае IF TRUE, который мы до этого момента использовали, IF FLAG3 = 1, что позволяет проверить, что значение нашего флага 3 равно 1. В этом случае выполнится содержание условия: SET TILE (12, 7) = 0 – на месте, которое занимал камень, появится пустой тайл, заменив его. Таким образом, когда мы входим в это окно с флагом 3 = 1, камень исчезнет, и препятствия не будет. Концепция понятна?

Ну, тогда продолжаем. Мы сказали, что флаг 3 = 1 означает, что все враги убиты, но флаг 3 не станет равен 1 сам по себе. Нам необходимо создать правило, которое проставит это значение.

Так как в окне, где появляется камень, врагов нет, у нас не будет такой ситуации, в которой последний колдун будет убит в окне с камнем. То есть, мы всегда будем в другом окне, когда убьем последнего негодяя. Это значит, что лучшее место для проверки, все ли колдуны убиты, – это вход в любое окно, то есть наша секция ENTERING ANY. С той замечательной особенностью, что эта команда выполняется и когда мы наступаем на врага. Каждый раз как заходим на новый экран, проверяем, что количество убитых врагов равняется 20, и, если это условие выполняется, ставим флаг 3 = 1:

# Вход в университет ENTERING ANY IF ENEMIES_KILLED_EQUALS 20 IF FLAG 3 = 0 THEN SET FLAG 3 = 1 SOUND 7 SOUND 8 SOUND 9 SOUND 7 SOUND 8 SOUND 9 END END

Благодаря этому получаем ровно то, что хотели. Посмотри на новую проверку: IF ENEMIES_KILLED_EQUALS 20 – она проверяет, равно ли количество убитых врагов (трупаков) двадцати. Если это верно, то следующим действием проверяем значение флага 3 (равно ли оно 0). Таким образом, мы удостоверяемся, выполняется ли это условие 1 раз, или, наоборот, при входе в любое окно.

Если условия выполнены, ставим флаг 3 = 1 (чего мы, собственно и добивались), а игра исполняет серию радостных звуков. Да, команда SOUND n исполняет звук n. Здесь речь идет о звуках движка. Можешь посмотреть, чему соответствует каждый номер в архиве beeper.h, в конце.

Так мы получили список первой части нашего сценария: если все враги убиты, ставим значение флага 3 равное 1. В окне 1, если флаг 3 равен 1, убираем камень.

Логика ящиков

Теперь нам осталось только прописать вторую часть сценария. Если помнишь, наш движок имеет конфигурацию ONLY_ONE_OBJECT. Это значит, что максимальное количество предметов, которые можем собрать за один раз = 1, т.е. можно взять только один ящик.

Цель игры – доставить 10 ящиков на подиум университета, соответственно, мы должны прописать в скрипте логику, которая позволяет нам применить следующий сценарий: если мы собираем предмет и активируем подиум, объект там остаётся, а счетчик доставленных предметов увеличивается, – и в этом нам поможет флаг 1.

Если помнишь, наш подиум находится в окне 9: мы нарисовали его с помощью SET TILE нашего скрипта в секции ENTERING SCREEN 0. Он занимает координаты (3, 7) и (4, 7).

Теперь мы напишем часть скрипта, которая, при нажатии кнопки действия в окне 0, будет проверять, касается ли персонаж подиума, и есть ли в его арсенале предмет, чтобы «отнять» его и засчитать.

Прежде всего, мы должны определить касание подиума. Если он занимает один тайл (x, y), то все просто:

IF PLAYER_TOUCHES x, y

Если один из пикселей игрока касается тайла (х, у), это условие выполняется. Но проблема в том, что наш подиум занимает 2 тайла. Решением могло бы быть написание двух идентичных условий, одно PLAYER_TOUCHES 3, 7, и другое PLAYER_TOUCHES 4, 7, но это не будет нужно, так как у нас есть другие инструменты.

Чтобы проверить, что мы находимся внутри какой-либо области, у нас есть специальные проверки:

IF PLAYER_IN_X x1, x2
IF PLAYER_IN_Y y1, y2

coordenadas

Первая проверяет, находится ли координата х, в пикселях, верхнего левого угла квадрата спрайта нашего персонажа между х1 и х2. Вторая проверяет, находится ли координата у, в пикселях, верхнего левого угла квадрата спрайта нашего персонажа между у1 и у2.

Рассмотрим это на рисунке. Здесь мы видим область, определенную x1, x2 и y1, y2. Игрок будет «внутри» этой области, если пиксель, отмеченный красным (левого верхнего угла спрайта), находится «внутри» этой зоны.

Когда мы хотим проверить, что наш персонаж находится внутри прямоугольника, который занимают тайлы, мы используем следующую формулу, чтобы определить значения x1, x2, y1 и y2. Если (tx1,ty1) – координаты (в тайлах) верхнего левого угла прямоугольника и (tx2, ty2) – координаты (тоже в тайлах) нижнего правого угла, то получается вот что:

coordenadas

С областью, определенной таким образом, значения x1, x2 у1, y2, которые мы должны использовать в скрипте, определяются по следующим формулам:

x1 = tx1 * 16 - 15 x2 = tx2 * 16 + 15
y1 = ty1 * 16 - 15 y2 = ty2 * 16 + 15

Чтобы это увидеть, еще один рисунок. Обрати внимание, что я дорисовал спрайт поверх, чтобы ты увидел, что для «касания» тайлы должны быть в прямоугольнике, определенном координатами (x1, y1) и (x2, y2):

coordenadas

Да, если ты не привык программировать эти значения, это кажется тебе чертовой мешаниной, но на самом деле все будет проще, когда ты запомнишь формулу, а еще лучше – поймешь ее. Мы умножаем на 16, когда переходим от координат тайлов к координатам пикселей, потому что тайлы состоят из 16х16 пикселей. Суммирование и вычитание значения 15 делается, чтобы обеспечить «столкновение ячейки» спрайта.

Я знаю, что мы могли бы создать скрипт, чтобы несколько скрасить эти действия, но здесь, пусть и заставляя программиста самостоятельно выполнить пару математических действий, мы все же значительно упрощаем код, давая движку «замаскированные» данные.

Чтобы с этим покончить, перейдем к нашему случаю и выполним необходимые действия, используя данные из нашей игры. Здесь прямоугольник образуется только значениями тайлов в координатах (3, 7) и (4, 7). Угловые тайлы – это как раз эти 2 тайла, поэтому tx1 будет равняться 3, ty1 будет равняться 7, будет равняться 4 и ty2 будет равняться также 7. Таким образом, получаем формулы:

x1 = 3 * 16 - 15 = 33 x2 = 4 * 16 + 15 = 79
y1 = 7 * 16 - 15 = 97 y2 = 7 * 16 + 15 = 127

Итак, чтобы коснуться подиума, спрайт должен находиться между 33 и 79 по оси X и между 97 и 127 по оси Y. Теперь посмотрим, как это будет выглядеть на этом сложном графике: чтобы спрайт дотронулся до подиума, верхний левый пиксель квадрата его спрайта (отмечен красным) должен быть внутри зоны, которую мы определили:

coordenadas4-0536[1]

Мы также должны проверить, что у нас есть ящик в инвентаре. Будет как-то так:

PRESS_FIRE AT SCREEN 0 # Определяем подиум. # Определяем положение прямоугольника из пикселей # Затем проверяем, имеет ли игрок код предмета # Если все условия выполняются, снижаем количество объектов в инвентаре # и увеличиваем значение Флага 1 IF PLAYER_IN_X 33, 79 IF PLAYER_IN_Y 97, 127 IF PLAYER_HAS_OBJECTS THEN INC FLAG 1, 1 DEC OBJECTS 1 SOUND 7 END END

Здесь все, что мы уже с вами видели раньше: сначала проверяем положение Dogmole, выполняя IF PLAYER_IN_X и IF_PLAYER_IN_Y. Если все условия выполняются, проверяем, что имеем собранный объект, выполняя IF PLAYER_HAS_OBJECTS. Если это верно, то делаем три вещи: сначала увеличиваем на 1 значение флага 1 путем выполнения FLAG 1, 1. Затем вычитаем 1 из количества предметов в наличии (оно вернется к 0, и мы снова можем собирать ящики) функцией DEC OBJECTS 1. И проигрываем звук под номером 7.

Когда все сделано, нам остается только одно: проверить, собрали ли мы 10 ящиков. Отличное место для выполнения этой проверки – как раз после предыдущего условия. Так как все условия секции выполняются по порядку, как раз за подсчетом ставим проверку, что мы уже доставили 10 ящиков, чтобы закончить игру. Таким образом, дополняем секцию PRESS_FIRE AT SCREEN 0 новым условием. Будет так:

PRESS_FIRE AT SCREEN 0 # Определяем подиум. # Определяем положение прямоугольника из пикселей # Затем проверяем, имеет ли игрок код предмета # Если все условия выполняются, снижаем количество объектов в инвентаре # и увеличиваем значение Флага 1 IF PLAYER_IN_X 33, 79 IF PLAYER_IN_Y 97, 127 IF PLAYER_HAS_OBJECTS THEN INC FLAG 1, 1 DEC OBJECTS 1 SOUND 7 END # Конец игры # Если собрано 10 коробок, мы выиграли! IF FLAG 1 = 10 THEN WIN GAME END IF END

Снова все просто: если мы доставили 10 ящиков (т.е. если флаг 1 = 10), мы выиграли. Команда WIN GAME успешно завершает игру и показывает финальное окно.

Видишь, все было не так страшно? Да, согласен, про координаты все же запутано, но рыдать не из-за чего. Ну конечно, если ты не сильно чувствительный.

Интересное дополнение

Ну что, мы сконфигурировали нашу игру, так что игроку остается только нажать на кнопку действия, чтобы активировать подиум и положить туда ящик. Это не проблема, но было бы еще круче, если бы игроку вообще ничего не надо было бы нажимать. Как раз для этого мы и добавили в движок то, что назвали «зоной огня», т.е. fire zone. Эта зона огня – просто прямоугольник в окне, определенный пикселями. Если игрок входит в этот прямоугольник, движок ведет себя так, как будто была нажата кнопка действия. Зона огня автоматически дезактивируется при смене экрана, так что если мы определим ее в ENTERING SCREEN n, она будет активна, только пока мы будем находиться в этом окне.

Это чудесно подходит к нашей игре: если при входе в окно 0 мы определим зону огня рядом с подиумом, когда игрок до него дотронется, будет выполняться логика, запрограммированная нами в скрипте для доставки предмета и увеличения счетчика.

Зона огня определяется командой SET_FIRE_ZONE, которая получает координаты x1, y1, x2, и y2 периметра, который хотим использовать в качестве зоны огня. Если мы хотим, чтобы зона огня совпадала с прямоугольником, заданным тайлами, как в нашем случае, применяются те же формулы, которые мы объясняли раньше. Так что мы будем использовать ровно те же значения.

Прежде всего, говорим движку, что мы будем использовать зоны огня. Для этого активируем команду, соответствующую нашему config.h:

Поле этого нам остается только изменить секцию ENTERING SCREEN 0, добавив команду SET_FIRE_ZONE x1, y1, x2, y2 в самом конце.

# Вестибюль университета ENTERING SCREEN 0 # декорации и подиум IF TRUE THEN # Подиум SET TILE (3, 7) = 22 SET TILE (4, 7) = 23 # Декорации SET TILE (1, 5) = 29 SET TILE (1, 6) = 20 SET TILE (1, 7) = 21 SET TILE (6, 6) = 20 SET TILE (6, 7) = 21 SET TILE (7, 7) = 28 SET TILE (1, 2) = 27 SET TILE (1, 3) = 28 SET TILE (2, 2) = 29 SET TILE (2, 3) = 27 SET TILE (3, 2) = 32 SET TILE (3, 3) = 33 SET TILE (9, 1) = 30 SET TILE (9, 2) = 30 SET TILE (9, 3) = 31 # Fire zone (x1, y1, x2, y2): SET_FIRE_ZONE 33, 97, 79, 127 END END

Вопрос, который ты себе сейчас задаешь: «Какого #@!! я не внес это в игру?» Да потому что эта характеристика, изначально созданная для версии 4.0 (игра Hobbit), была снова применена в версии 3.99.1.

Чувак, я малость запутался

Беру вину на себя. Надо еще вбить себе в башку работу скрипта. Я думаю, что лучше всего начинать с чего-то очень простого, в том числе более простого, чем Dogmole, который мы видели, и потихоньку увеличивать сложность.

Мне пришла в голову гениальная идея: мы закончим здесь главу о базовых скриптах, но мы могли бы вместе рассмотреть скрипты некоторых наших игр. Я выберу несколько игр с простым скриптом, и мы объясним их шаг за шагом. Было бы интересно, чтобы вы параллельно играли в эти игры, чтобы посмотреть, как выполняются различные условия.

Cheril Perils

Премьера движка скриптов состоялась с выпуском игры Cheril Perils. Конечно, это все было на уровне детского сада и очень просто. Скрипт Cheril Perils – это самый простой скрипт из всех наших игр со скриптом: здесь выполняется только 1 вещь: когда мы убили всех врагов, мы можем вынести добычу с первого окна. Вот так:

mojon-twinscheril-perils-0602[1]

В принципе, все похоже на то, что мы сделали в Dogmole: при входе на экран, проверяем, что мы убили всех врагов (всего их 60). Если это условие выполняется, на месте нашей добычи рисуем пустые тайлы:

ENTERING SCREEN 20 IF ENEMIES_KILLED_EQUALS 60 THEN SET TILE (2, 7) = 0 SET TILE (2, 8) = 0 END END

Но здесь происходит то, чего нет в Dogmole: в окне, откуда мы должны вынести добычу, есть враги. Так что эта проверка на входе на экран нам ничего не даёт, и если мы убиваем последнего жучару в этом окне (что может случиться), то нам надо выйти и снова зайти в это окно, чтобы движок сработал. Нам нужен дополнительный код, который определяет, что мы убили последнего врага, и который сработает, когда мы его убиваем. Мы помним особенность движка: когда мы прыгаем на врага, выполняется секция PRESS_FIRE AT SCREEN, относящаяся к текущему окну. Так что получилось гениально: поставив в этой секции тот же код, что в ENTERING SCREEN, решаем проблему.

Не откладывая в долгий ящик:

PRESS_FIRE AT SCREEN 20 IF ENEMIES_KILLED_EQUALS 60 THEN SET TILE (2, 7) = 0 SET TILE (2, 8) = 0 END END

Теперь нам надо определить выход с экрана. Если ничего не менять, то при выходе влево с экрана 20, попадем в экран 19… Который, к тому же, находится на другом конце карты. В оригинальной игре это было решено грязным хаком, но для текущей версии Чурреры мы смогли все сделать по-честному.

Прежде всего, надо определить зону огня, которая займет левую часть окна, чтобы выполнялась секция PRESS_FIRE AT SCREEN 20, когда мы в нее зайдем. Затем добавим определение зоны огня в секции ENTERING SCREEN 20 (также не забываем активировать эту функцию в config.h). Вот что получается:

ENTERING SCREEN 20 IF ENEMIES_KILLED_EQUALS 60 THEN SET TILE (2, 7) = 0 SET TILE (2, 8) = 0 END IF TRUE THEN SET_FIRE_ZONE 0, 0, 15, 159 END END

Все понятно? При входе на 20 экран происходят 2 вещи: прежде всего, проверяется, равно ли количество убитых врагов 60, и в таком случае исчезают тайлы, которые блокируют выход. Затем в любом случае (IF TRUE) определяется зона огня, занимающая всю левую сторону шириной 15 пикселей. И когда игрок заходит в эту зону (он не сможет это сделать, если не убрал загородку: он просто не сможет пройти), выполнится секция PRESS_FIRE AT SCREEN 20. Теперь надо добавить код в секцию PRESS_FIRE AT SCREEN 20 , чтобы определить, что игрок собирается выйти с левой стороны и, в этом случае, закончить с успехом игру. Вот что получается:

PRESS_FIRE AT SCREEN 20 IF ENEMIES_KILLED_EQUALS 60 THEN SET TILE (2, 7) = 0 SET TILE (2, 8) = 0 END IF PLAYER_IN_X 0, 15 THEN WIN END END

Повторим, чтобы было понятно. Рассмотрим что будет происходить шаг за шагом. Представим, что заходим на 20 экран после того, как убили всех злодеев. Это последовательность событий:

  1. При входе в окно 20, после его прорисовки и т.д., выполняется секция ENTERING SCREEN 20. Она проверяет, имеем ли мы 60 убитых врагов, что подтверждается – и решетка открывается. К тому же определяется зона огня в 15 пикселей шириной в левой части игры.
  2. Выполняется основной сценарий игры. Игрок продолжает играть, видит открытую решетку и идет влево.
  3. Когда игрок заходит в зону огня, выполняется секция PRESS_FIRE AT SCREEN 20. В ней проверяется, что мы имеем 60 убитых врагов, и убирается решетка. Это повторяет предыдущие действия и может быть заменено на флаг, но нам все равно… это не сильно заметно. Важно то, что происходит потом: проверка координаты Х игрока, в пикселях: находится ли она между 0 и 15, и, когда получается подтверждение (что мы уже включили в эту секцию, когда вошли в зону огня, определенную как раз в этой зоне), выполняется команда WIN: появляется финальный экран игры.

Все поняли? Посмотрим еще один? Хочешь посмотреть на скрипт с флагом, чтобы избежать повторения? Отлично.

У нас все флаги свободны, поэтому будем использовать первый. Метод простой: ставим его на значение 0 при входе в экран и на 1, когда убираем решетку, а решетку мы можем командой PRESS_FIRE AT SCREEN 20, только если флаг равен 0. Теперь посмотрим на это всё вместе, всё должно быть понятно:

ENTERING SCREEN 20 IF TRUE THEN SET_FIRE_ZONE 0, 0, 15, 159 SET FLAG 1 = 0 END IF ENEMIES_KILLED_EQUALS 60 THEN SET TILE (2, 7) = 0 SET TILE (2, 8) = 0 SET FLAG 1 = 1 END END PRESS_FIRE AT SCREEN 20 IF ENEMIES_KILLED_EQUALS 60 IF FLAG 1 = 0 THEN SET FLAG 1 = 1 SET TILE (2, 7) = 0 SET TILE (2, 8) = 0 END IF PLAYER_IN_X 0, 15 THEN WIN END END

Так, давайте посмотрим еще один.

Sgt. Helmet Training Day

Сейчас рассмотрим чуть более длинный скрипт, но тоже легкий. В этой игре (Sgt. Helmet Training Day) задание – собрать 5 бомб, отнести их к экрану с компьютером (окно 0) и снова вернуться в начало (экран 24).

Если много способов сделать это. Тот, который используем мы, очень простой:

Мы можем посчитать количество доставленных предметов через скрипт, потому что бомбы – нормальные и часто встречающиеся объекты в движке. Размещаем их с помощью Разместителя в качестве хотспота 1-го типа.

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

Используем флаг 1 для проверки, что мы расположили бомбы. В начале игры он равен 0, значение изменится на 1, когда мы разместим бомбы.

Когда мы заходим в окно 24, являющееся основным окном, проверяем значение флага 1, и если оно равно 1, игра завершается.

К тому же добавим текст в окно с указанием того, что теперь надо сделать. Вспомним, что в config.h есть три команды, которые мы уже упоминали в некоторых главах:

#define LINE_OF_TEXT 0 // If defined, scripts can show text @ Y = # #define LINE_OF_TEXT_X 1 // X coordinate. #define LINE_OF_TEXT_ATTR 71 // Attribute

Они определяют, где появляется текст, который мы можем прописать в скрипте командой TEXT. Для этого оставляем пустое место в зоне маркировки: посмотри, в верхней строчке есть место, потому что мы уже запрограммировали текстовую строку в координатах (x, y) = (1, 0).

helmet-title-0632[1]

Первое, что делает наш скрипт, это определяет несколько сообщений, которые появляются по умолчанию при входе в каждое окно, в зависимости от значения флага 1. Это мы делаем в секции ENTERING ANY. Мы помним, что эта секция выполняется при входе на любой экран, сразу перед секцией ENTERING SCREEN n с соответствующим номером. Внимание: мы можем определить общий текст, который будет появляться при необходимости в любом конкретном окне, а тот текст, которые будет написан ENTERING SCREEN n заменит предыдущий текст, так как эта команда выполняется последней.

Чтобы написать текст в определенной таким образом строчке, используем команду ТЕХТ. Текст пишется без кавычек. Используем нижнее подчеркивание вместо пробелов. Также важно заполнять текст дополнительными пробелами, для ситуация в которых более короткий текст должен появиться поверх более длинного.

Максимальная длина текстов будет зависеть от твоего экрана маркировки игры, и от того, каким образом мы определил его позицию. В нашем случае мы его расположили в (x, y) = (1, 0), т.к. слева и справа у нас есть граница, так что максимальная длина будет 30 символов.

Пишем нашу секцию ENTERING ANY. Мы говорили, что сделаем 2 разных текста, в зависимости от значения флага 1:

ENTERING ANY IF FLAG 1 = 0 THEN TEXT НАЙДИ 5 БОМБ И КОМПЬЮТЕР! END IF FLAG 1 = 1 THEN TEXT МИССИЯ ВЫПОЛНЕНА! ВОЗВРАЩАЙСЯ НА БАЗУ! END END

Никакого волшебства, правда? Если флаг 1 = 0, т.е. идентичен начальной ситуации игры (в начале все флаги равны 0), при входе на каждый экран в зоне маркировки будет появляться текст «НАЙДИ 5 БОМБ И КОМПЬЮТЕР», определённый для текстовой строки. Если флаг 1 = 1, что произойдет, когда мы разместим бомбы возле компьютера, текст по умолчанию, который появится при входе на экраны, будет «МИССИЯ ВЫПОЛНЕНА! ВОЗВРАЩАЙСЯ НА БАЗУ!».

Сделаем дурацкий набросок окна, чтобы увидеть, как будут располагаться компьютер и бомбы:

esquema

Теперь перейдем к серьезным вещам. Первое, что мы сделаем, это пропишем условия для окна с компьютером, под номером 0. В этом окне мы должны сделать несколько вещей. Прочисти мозги прежде чем начинать. При каждом входе мы должны рисовать компьютер, который состоит из тайлов с 32 по 38 тайлсета. Делаем это, как уже говорили, через команду SET TILE.

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

Если мы снова зайдем в это окно, после того как разместили бомбы (все возможно), мы должны пририсовать еще и бомбы.

Если заходим на экран в первый раз (еще не оставили бомбы), пишем сообщеньице-подсказку, которое говорит: «ЗАЛОЖИ 5 БОМБ И УЛЕПЕТЫВАЙ».

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

Теперь мы с сами опытные ребята и соображаем, что первые 4 действия выполняются при входе на экран, а последняя при нажатии на кнопку действия (или при входе в зону огня). Разберем все по отдельности. Начнем с тех действий, которые совершаются при входе в это окно. Мне нравится начинать с тех вещей, которые будут повторяться при любом стечении обстоятельств: нарисуем компьютер и определим зону огня:

ENTERING SCREEN 0 # Всегда: рисовать компьютер IF TRUE THEN SET TILE (6, 3) = 32 SET TILE (7, 3) = 33 SET TILE (8, 3) = 34 SET TILE (6, 4) = 36 SET TILE (7, 4) = 37 SET TILE (8, 4) = 38 SET_FIRE_ZONE 80, 32, 159, 95 END

Видишь, мы использовали формулы, которые объяснили раньше, чтобы определить широкую область вокруг компьютера. Конкретно? Эта зона соответствует прямоугольнику, формируемому тайлами (x, y) = (5, 2) и (9, 5). Т.е. область в 1 тайл шириной вокруг 6 тайлов, означающих компьютер. Если не слишком занят, нарисуй это на листочке в клетку.

Продолжаем: если мы заходим на экран после того, как расположили бомбы (ну мало ли), нам надо добавить бомбы к рисунку. Ничего проще:

# Если мы уже расположили бомбы, нарисовать их IF FLAG 1 = 1 THEN SET TILE (4, 4) = 17 SET TILE (4, 2) = 17 SET TILE (7, 1) = 17 SET TILE (10, 2) = 17 SET TILE (10, 4) = 17 END

Мы всё зарисовали, чтобы знать, куда разложить бомбы. Бомба находится в 17-ом тайле, это тайл, использующийся для рисования предметов, если помнишь.

Теперь осталось только добавить текст-подсказку, если мы еще не разместили бомбы. Смотри, получилось, как мы и говорили: так как эта секция выполняется после ENTERING ANY, этот текст замещает тот, что был до этого. Поэтому мы используем пробелы вокруг текста, чтобы заместить все символы предыдущего текста, который длиннее нового:

# Если нет, сообщеньице IF FLAG 1 = 0 THEN TEXT ЗАЛОЖИ 5 БОМБ И УЛЕПЁТЫВАЙ END END

Готово. Теперь осталось настроить реагирование на зону огня в секции PRESS_FIRE AT SCREEN 0. Добавим проверки и анимацию:

PRESS_FIRE AT SCREEN 0 IF PLAYER_IN_X 80, 159 IF PLAYER_IN_Y 32, 95 IF OBJECT_COUNT = 5 IF FLAG 1 = 0 THEN SET FLAG 1 = 1 SET TILE (4, 4) = 17 SHOW SOUND 0 SET TILE (4, 2) = 17 SHOW SOUND 0 SET TILE (7, 1) = 17 SHOW SOUND 0 SET TILE (10, 2) = 17 SHOW SOUND 0 SET TILE (10, 4) = 17 SHOW SOUND 0 TEXT МИССИЯ ВЫПОЛНЕНА! ТЕПЕРЬ ВОЗВРАЩАЙСЯ НА БАЗУ! END END

Теперь спокойно рассмотрим это, потому что есть некоторые новые вещи:

Прежде всего, проверяем, что мы находимся там, где должны быть (игрок всегда может просто нажать на кнопку действия вместо того, чтобы войти в зону огня, и будет не здорово, если команда выполнится, если игрок находится где-то еще). Выполняем это, как уже говорили раньше: с помощью PLAYER_IN_X и PLAYER_IN_Y с координатами зоны огня.

Следующий шаг – проверить, что в арсенале имеется 5 бомб, или, что то же самое, 5 предметов. Это выполняется через OBJECT_COUNT, который представляет собой количество предметов, которые собрал игрок.

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

Если все эти условия выполняются, ставим значение 1 у флага 1 (мы уже установили бомбы) и добавляем анимацию, которая состоит в прорисовке бомб по одной и звуках. Обрати внимание на команду SHOW, необходимую, чтобы те изменения, которые мы делаем на этом экране, не были видны до актуализации, что обычно происходит при возвращении к основному сценарию игры, но не посреди выполнения условия. Так как нам надо, чтобы каждая бомба появилась после того, как мы ее нарисовали, обращаемся к SHOW. К тому же каждый звук задержит выполнение сценария на некоторое время (мы в режиме 48К), что отлично для нас. В конце печатаем текст подсказки, снова с пробелами вокруг, чтобы заполнить 30 символов и заменить предыдущий текст.

И таким образом мы закончили всё, что надо было сделать в окне 0.

Если мы продолжим наш сценарий, следующее, что мы должны сделать, это вернуться в начальное окно под номером 24. То, что нам осталось сделать, очень просто: надо проверить при входе на экран 24, что флаг 1 = 1. Это условие может быть выполнено, только если до этого мы разместили бомбы, для чего нам нужно было выполнить еще много всего… Просто проверяем это, и если условие выполняется, завершаем с успехом игру… Нет ничего проще:

ENTERING SCREEN 23 IF FLAG 1 = 1 THEN WIN END END

Ура! Мы запрограммировали игру. В скрипте Sgt. Helmet есть еще одна штуковина: наше привычное «Продаю подержанный мотоцикл». Но это пока оставим, в этом нет ничего особенного: нарисовать тайлы, определить зону огня, определить позицию и написать текст. Ты все это уже умеешь.

Гав-гав

Можно было бы продолжать, но лучше мы тут остановимся. В следующей главе мы продолжим разбирать примеры шаг за шагом, но уже с более сложными скриптами, как, например, скрипт Cadàveriön. И потом продолжим изучать такие интересные вещи, как игры 128K, изменение музыки и эффектов, сжатые фазы, уф, так мы никогда не закончим.

Между тем, напоминаю тебе, что в архиве motor_de_clausulas.txt в /script можно найти список доступных команд и проверок, на случай, если тебе стало любопытно.

[ Перевод на русский язык — сайт viva-games.ru. При перепечатке статьи или любой её части ссылка на viva-games.ru обязательна. Оригинал статьи тут. ]

Понравилась публикация? Поделись с друзьями

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? ⁠ ⁠

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

«Если вы хотите использовать нейросеть для получения помощи в написании кода на C# для Space Engineers, то необходимо учитывать ряд факторов, чтобы задать правильный вопрос нейросети.

Так начинается ответ на этот вопрос, о нейросети ChatGPT. Наверное, вы уже догадались, что речь пойдет о ней, хотя, возможно, вы никогда не слышали о ней. Я не буду вдаваться в подробности о том, что такое нейросеть. В статье речь пойдет о конкретных примерах использования на практике для решения простых или узкоспециализированных задач. Все, конечно, зависит от вашей фантазии и навыков. Я не умею писать на C#, но я немного понимаю Python и работаю с SQL-базами данных, поэтому некоторые операторы (функции работы), например if/else, мне понятны.

Давайте же начнем. Для начала найдем рабочую версию чата. Если у вас есть доступ к оригинальному сайту, вам повезло. Я же попробовал несколько телеграмм-ботов. Вы можете их найти через поисковик или внутри самого Телеграмм по названию. После того как вы нашли подходящую для вас систему, можете попробовать написать запрос. Я начал с такого: «Привет. Что ты знаешь об Space Engeeners?». Бот ответил, что это игра — песочница, и другую информацию из Вики. Мне показалось, что бота нужно постепенно вводить в контекст моего запроса, чтобы он лучше меня понял. Я продолжил и узнал у него о «Программируемом блоке». На что он дал ответ о подобных блоках в реальной жизни для сборки электроники. «Ага, недостаточный контекст» — подумал я. Задал вопрос снова, но написал уже «Programmable block» в Space Engeneers. Бот услужливо ответил, что он знает такой блок, из какой игры, и что код для этого блока пишется на C#. Вот тут я понял, что нащупал что-то интересное.»

Основная часть.

Я написал боту: «Напиши пример кода, чтобы вывести текст на дисплей, который имеет в названии D1». Подумав 10-15 секунд, бот ответил. Моему восторгу не было предела, когда я понял, что он не только написал мне готовый код, но и описал его работу.

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

«Вау! Да это же примитивный «Hello world»! Интересно, заработает ли он в игре. Срочно бежим туда! Ставим программируемый блок, ставим дисплей, даем нужное название дисплею. Здесь стало ясно, что бот меня понял неверно и он ищет дисплей с названием D1, а не с D1 в названии этого дисплея. Ладно, для первого раза это не проблема. Переименовываем дисплей, включаем отображение текста, затем копируем код в программный блок и запускаем проверку. И. Облом, сплошные ошибки.»

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

«Я уже был расстроен, пока внимательно не прочитал текст: «Обратите внимание, что этот код должен быть помещен в метод Main для выполнения в Programmable Block. Также убедитесь, что у вас есть блок дисплея с именем «D1″ на корабле или станции». Так, дисплей есть, а вот Main в тексте кода я не вижу. Пишу боту: «Поместите код выше в метод Main». Снова 5-10 секунд ожидания и ответ был такой:»

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

«Копируем, запускаем проверку: компиляция завершена успешно. «Ага!» — воскликнул я! Тут же в мою кровь выплеснулся адреналин от азарта. Нажимаю кнопку «Выполнить», и на моем экране D1 появляется заветное «Hello world».»

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

«Моему восторгу не было предела! Работает, собака! Мысли заметались в голове, и я понял, что бот понимает, как работать с кодом, и знает, как найти конкретный блок именно в игре. То есть он понимает внутреннюю систему. Срочно еще один тест!»

Та часть, где все пошло не по плану.

«Давай найдем. эммм. Все батареи на структуре, на которой установлен программируемый блок, выведем название этих батарей, максимальную емкость, текущую емкость и выведем построчно в дисплей [D1]» — такое задание появилось у меня в голове, но нужно было сформировать это в понятный список целей.

1. Найди все блоки батарей на структуре, на которой установлен programmable block.

2. Вычисли максимальную емкость каждого блока батарей в ваттах, текущую емкость в ваттах.

3. Выведи на дисплей [D1] для каждой новой строки: Название каждого блока батареи, его максимальную емкость, его текущую емкость.

4. Обновляй информацию о батареях каждые 5 секунд.

Вот, уже понятнее. Запускаем!

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Уже наученный опытом, я вижу что отсутствует метод Main. Указываю боту на ошибку.

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Отлично, копируем, вставляем, проверяем на ошибки.

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

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

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Ого, он понимает что допустил ошибку именно для этой среды. Ладно, пробуем запустить этот код!

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Опять ошибка, уже другая. Но мы уже знаем что делать! К сожалению я допустил ошибку в слове «type».

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Копирую, запускаю и тут заветная надпись: «Компиляция завершена успешно!» УРА! Запускаю выполнение кода, а программируемый блок пишет что код для него слишком сложный.

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Тут моя радость перешла в грусть и обиду. Казалось я почти на пороге открытия (для себя). Ничего не работает! Зачем я пишу эту статью? Надо передохнуть.

Та часть, где все снова стало солнечно.

Выпив чаю, да, закусив французской булкой я вернулся к боту и написал: «Привет. Space Engeneers. Programmable block». Бот ответил, что готов мне помочь. Так, запишем что мне нужно, при этом немного поменяю запрос:

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Копирую, проверяю опять ошибка! Указываем на ошибку боту и запускаем снова. Компиляция — ОК! Выполнение — ОК!

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

УРА! ПОБЕДА! Код выполняет функцию! Правда показывает мегаватты, а пишет что ватты. Но тут моя ошибка, ошибся когда, писал задание. Главное — функцию свою выполняет и проверяет самостоятельно наличие новых батарей. Поставил дополнительную батарею (Батарея 4) рядом. Останется только причесать инфу на дисплее, что бы глаз радовался.

Как написать свой первый скрипт для игры Space Engeeners, если никогда не занимался программированием? Программирование, ChatGPT, Csharp, Space Engineers, Игры, Длиннопост

Заключение.

Естественно ChatGPT это не панацея. Настоящие знания ничем не заменить, и при создании запроса приходится сталкиваться с глупыми ошибками как при постановке задачи, так и внутри кода. И здесь эти ошибки присутствуют. Плюс нейросеть при любом новом обращении может дать совершенно другой ответ, или попытаться использовать стороннюю библиотеку, что не поддерживается в Space Engeeners. Использовать такой код, написанный нейросетью, в работе, на сложных проектах я бы не советовал. В игре — почему бы и нет. Это закроет минимальные задачи, а может сподвигнет изучать язык самому. Я не кодер, да и строю я откровенные табуретки, но стало интересно, и я загорелся идеей попробовать написать код для игры таким образом. Я уверен что, ваш код будет куда лучше и интереснее, будет выполнять уйму разных полезных и нужных вам функций. Главное правильно ставьте задачу, а лучше учите язык!

Спасибо за внимание, и желаю вам классных приключений в игре!

10 месяцев назад

Класс! Буквально сегодня тестил на ардуинке, работает!

Так же просто превосходно работает с трудными формулами в Эксель.

Отлично пишет базовые запросы в sql. Но с ними такое дело, сложный запрос легче написать самостоятельно, чем описать нейросети что нужно конкретно достать 🙂 зато, кстати, чатгпт достаточно понятно может объяснить про шардирование и индексы

Молодец! Классная статья!

раскрыть ветку
5 месяцев назад

На странице магазина стима в последнем видео есть фрагмент, где поршни со сварщиками туды-сюды двигаются вокруг конструкции которую возводят, как перфораторы. Помогите со скриптом(( Я в целом не совсем соображаю как такое организовать.

раскрыть ветку
Похожие посты
2 месяца назад
Подписаться

Как нейросети постепенно засрут интернет (а точнее уже засрали)⁠ ⁠

Год назад я наткнулся на статью, которая предсказывала деградацию нейросетей и автор приводил интересную теорию:

● Нейросети обучаются на контенте из интернета, который по большей части делает человек.

● Качество итоговой работы нейросети на данный момент ниже, чем оригинальный контент живого автора. Логические и смысловые ошибки, а так же некое «отсутствие души».

● Несмотря на это, нейросети массово используют для создания контента. Растет количество некачественных материалов в интернете и нейросеть начинает брать эти данные для обучения.

● Из-за общего снижения качества «скармливаемой» информации, нейросеть начинает тупить, все чаще повторяя свои же ошибки и неточности.

Вот недавно я решил поиграть в Kenshi, вспомнить лор и почитать информацию о фракциях. И первая же статья которую мне выдает поиск Яндекса выглядит так:

Как нейросети постепенно засрут интернет (а точнее уже засрали) Программирование, Разработка, Программист, Нейронные сети, Арты нейросетей, Яндекс, Google, IT, Чат-бот, Поисковые запросы, Поиск, ChatGPT, Длиннопост

▸ Я может быть какое то обновление пропустил, но про «Сеть» в Кенши не слыхал

Увидев этот странный текст, я из интереса перешел по ссылке, а там безумие в чистом виде!

Как нейросети постепенно засрут интернет (а точнее уже засрали) Программирование, Разработка, Программист, Нейронные сети, Арты нейросетей, Яндекс, Google, IT, Чат-бот, Поисковые запросы, Поиск, ChatGPT, Длиннопост

▸ Даже в Kenshi есть свой филиал «Без баб»

Как нейросети постепенно засрут интернет (а точнее уже засрали) Программирование, Разработка, Программист, Нейронные сети, Арты нейросетей, Яндекс, Google, IT, Чат-бот, Поисковые запросы, Поиск, ChatGPT, Длиннопост

▸ А как вам такое? Холодные осадки в Kenshi осознали себя и из погодных условий превратились во фракцию

Как нейросети постепенно засрут интернет (а точнее уже засрали) Программирование, Разработка, Программист, Нейронные сети, Арты нейросетей, Яндекс, Google, IT, Чат-бот, Поисковые запросы, Поиск, ChatGPT, Длиннопост

▸ А Шеки решили позабыть свой культ битвы и стать торговцами тех-охотниками

Для тех кто еще не понял — эта статья написана нейросетями!

Написана убого, коряво, без намека на логику, но с нужными SEO элементами — тот самый информационный мусор. А самое забавное, что мусор вынесен на первую позицию поисковой выдачи Яндекса. Да что там, 5 из 15 ссылок на первой странице поиска вели на такие же плоды нейросетей разной степени бредовости.

И в этом ключевая проблема нейросетей — слишком высокая скорость генерации контента. Она априори будет выше, чем создание уникального контента от живого автора. Ужасное качество итогового продукта меркнет на фоне человеческой жадности и лени.

Какая задача у информационного контента в 21 веке? Решить проблему пользователя? Нет — привлечь трафик и желательно здесь и сейчас, ведь трафик это деньги. Поэтому количество такого контента будет расти в геометрической прогрессии.

Масштаб проблемы и как она будет решаться в будущем?

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

● Для самих нейросетей встает вопрос обучения. Chat-GPT потребляет информацию из интернета и недавно с него сняли ограничения 2021 года (все что вышло позже этой даты нейросеть не учитывала). Если на системном уровне не будет фильтра, то в обозримом будущем качество ответов заметно упадет, ведь они будут составляться на основе ошибочных материалов созданных нейросетью до этого.

● Google, Яндекс и другие поисковики в какой то момент столкнутся с недоверием аудитории, ведь перестанут решать основную задачу пользователя — поиск полезной информации. Пока что их инструменты оценки качества контента слишком примитивны, что доказывает пример приведенный в начале статьи (1/3 выдачи поиска загажена мусором нейросетей). Единственный возможный критерий отбора доступный в данной ситуации — отдавать приоритет оригинальным статьям от живого автора.

А что в итоге?

Я пишу эту статью для того, чтобы люди более критично относились к информации в интернете и поддерживали живых авторов. Экспертного контента в сети все меньше и нельзя позволить ему утонуть под лавиной бреда нейросетей. В конце концов за ошибкой человека стоит мыслительный процесс, а за ошибкой нейросети — случайный алгоритм. И пока что к человеку доверия больше, чем к машине.

Ждем, когда техно-жрецы найдут решение этой проблемы и оно вскроет еще десяток других. А пока подписывайся на мой гоблинский блог — тут много интересного про разработку игр и нейросети.

P.S. По поводу моего месячного отсутствия. Несмотря на навалившийся ворох дел — я не забрасывал изучение инструментов для разработки игр. Просто написание статьей не вписывалось в мое плотное расписание. В ближайшие пару недель постараюсь выложить новую статью про Godot.

ВСЕМ WAAAGH!

Как нейросети постепенно засрут интернет (а точнее уже засрали) Программирование, Разработка, Программист, Нейронные сети, Арты нейросетей, Яндекс, Google, IT, Чат-бот, Поисковые запросы, Поиск, ChatGPT, Длиннопост

Показать полностью 5
3 месяца назад
Подписаться

Как нейронка за меня таблицы считала (живой пример)⁠ ⁠

Сегодня я расскажу как лично я в своей работе использую нейросеть для решения задач по обработке данных и экселевских таблиц.

Казалось бы обычный кликбейт в стиле «100 нейросетей для улучшения дикпиков» или «50 новых убийц чат-гпт”. Но нет.

Я работаю маркетологом, и помимо того что мне разрешают сидеть рядом с настоящими айтишниками и програмистами, мне иногда дают задачки по обработке данных. Но не тех данных, для которых нужно иметь 3 сертификата по ML и бигдате, а обычные задачки по экселю, которые встречаются у каждого из нас, практически вне зависимости от профессии. Если вы тот самый “опытный пользователь ПК”, скорее всего вы копаетесь в экселе по рабочим нуждам, и обычная задачка со сводной табличкой из-за отсутствия опыта может растянуться на 6 рабочих часов с перекурами. Большинство таких задач довольно однотипные, и более опытный коллега сделает их в 10 раз быстрее, просто потому что он уже на них собаку съел. Но задачка упала вам. Что бы не проваливаться в кроличью нору запросов в гугле про работу экселевских формул, откроем классический chatGPT 3.5.

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

Давайте более конкретно.

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

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Файл может и реальный, а может и нет. Да какая разница, мы тут не за этим.

Ваша задача довольно простая —

  • Прочекать все поисковые фразы с >20% отказностью;
  • Вычленить из них все наиболее повторяющиеся фразы, посчитать их повторы
  • Вычленить из них все наиболее повторяющиеся слова, посчитать их повторы
  • Выстроить в порядке убывания слова и фразы от большей отказности к меньшей

Часть первая — простая (кто хочет сразу про питон — го во вторую часть)

Первый вариант работы довольно очевидный — мы просим нейросеть (в данном случае обыкновенный чат-гпт) решить нашу задачу через формулы экселя. Для этого просто пишем в чат нашу таску.

Привет! У меня есть задачка. Есть таблица из 20000 строк. Столбцы этой таблицы — «Поисковая фраза (Директ), Визиты, Посетители, Отказы, Глубина просмотра, Время на сайте». Вторая строчка «Итого и среднее» содержит суммы с средние значения моих данных. Потом идет 19.998 строк с данными. Визиты и посетители — целые числа, отказы — в процентах, глубина просмотрах в десятичных числах с тремя знаками после запятой, время формата ЧЧ:ММ:СС.

Зачем я пишу так подробно? Потому что она буквально ничего не знает про мой файл. Может у меня визиты прописаны текстом, глубина просмотров в сантиметрах, а отказы написаны на хинди?

Далее когда нейросеть понимает что у нас за файл, можно ее просить помочь с формулами.

Напиши мне формулу, которая найдет все фразы с отказностью более 20% и добавит их на новый лист в отдельную колонку. Эксель у меня воспринимает англоязычные формулы. (про язык стоит добавлять, а лучше сразу версию указывать, что бы не было ошибок из-за разницы версий)

Нейросеть выдает нужную формулу, с описанием ее работы —

=IF(«Отчет’!D2 > 0.2, ‘Отчет’!A2 & » (» & TEXT(‘Отчет’!D2*100, «0.00%») & «)», »»)

«Эта формула проверяет, если значение отказов в ячейке D2 (на листе «Отчет»)

больше 20% (0.2 в десятичной форме), и если это условие выполняется,

она объединяет значение в столбце »Поисковая фраза (Директ)» с

отображением отказов в скобках с процентами.

В противном случае, она возвращает пустую строку.”

К сожалению в формуле есть косяк, который мы видим после пробного запуска — она не содержит разделителя для формулы (;). Спросим об этом нейросеть.

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Это я в скриншотах такой борзый, обычно я пишу приличнее.

Итогом этой формулы являются опять косячные данные —

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Видим что он зачем то умножает наши проценты на 100. Исправляем формулу руками до вида (убираем «*100» из формулы) —

и получаем приемлемый результат.

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Мне не нравится что у меня проценты и фраза в одной ячейке, спрошу нейросеть как это исправить, и убрать пустые строки.

Он предлагает сначала скопировать все фразы на новый лист, потом выполнить следующие действия.

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Подробное описание всех необходимых действий

По итогу мы получим новый лист с фразами где отказы более 20%.

Далее мы можем просить нейросеть написать более сложные формулы для подсчета оставшихся задачек.

Этот метод подходит тем кто не знает как подступиться к задаче, не очень хорошо разбирается в возможностях экселя (или вообще его первый раз видите), но можете примерно понять где именно ошибка. Очень полезно если вы в душе не чаете какую формулу лучше использовать, и как сделать то что вам нужно. И у вас нет желания использовать что то еще кроме браузера и экселя. И это все равно намного быстрее чем гуглить формулу.

Но я собрал вас тут не для этого.

Вот бы был способ, что бы не надо было писать, протягивать формулы, самому фильтровать, вставлять, копировать данные и т. д.

Можно попросить написать макрос для экселя, который сделает за нас все самостоятельно, включая создание листов и т. д.

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

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

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

Я же предлагаю еще более сложный способ, но который позволяет делать с данными из экселя практически что угодно, имеет очень понятный способ поиска ошибки, и может быть реализован практически кем угодно. Я говорю про работу с Python

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

Что нам позволяет делать нейросеть? Писать любой простой код на любом языке программирования, даже если мы в нем ничего не понимаем.

Начнем по порядку, что нам нужно сделать что бы затея сработала?

Для работы с питоном, его (а точнее его интерпретатор) необходимо поставить на свой пк (без этого к сожалению никак). Я использую PyCharm от компании Jetbrains (хотя пофигу что использовать, главное что бы он работал). Инструкция по установке находится в первой ссылке поискового ответа — https://pythonru.com/baza-znanij/poshagovaja-ustanovka-pycha. . Если хочется не отходить от нейросетей — можно спросить у нее, как пошагово установить PyCharm, он подробно расскажет.

Перенесемся сразу в момент когда у нас установлен PyCharm, и мы начали новый проект.

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

Как это выглядит.

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

Вот пример ответа на мой прошлый запрос для экселя, но я попросил его написать код на питоне:

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Чуть редактируем код, меняя 20 на 0.20, потому что данные о процентах у нас меньше единицы всегда.

Вставляем код в PyCharm, и получаем сразу новый готовый файл в папке с нашим проектом.

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Да, задача решалась просто и через эксель. Но так тоже работает.

На решение этой задачки ушло минуты 3. Из которых две — на открытие программы и написание запроса. Результат ок, идем дальше.

Далее просим нейросеть перейти ко второй задачке —

  • Вычленить из полученных запросов все наиболее повторяющиеся фразы, посчитать их повторы”. (более полный запрос будет чуть ниже)

Далее нам нейросеть пишет код посложнее, со всякими сторонними библиотеками и т. д. Я не стал постить сюда этот код, думаю он мало что скажет. (Можно попросить писать объяснение всех действий, она очень подробно пишет комментарии для каждой строчки.) Нам совершенно не нужно вникать какую именно библиотеку она использует, или какой метод. Следуем указаниям умной машины.

Если (точнее «когда») получаем ошибку — не стесняемся копировать ее всю в ответ в чат, она находит причину и говорит решение — вот пример (я обрезал часть ошибки, она была длинная)

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Я ему абракадабру, а он мне — четкий план действий.

Любую полученную ошибку закидываем в нейросеть и получаем решение. Далее запускаем код. Если есть снова ошибка — кидаем снова в нейросеть. Если нет — смотрим на данные и радуемся результату, или просим переделать в другом виде. Если видите что нейросеть пишет вам ахинею (будто совсем забыла в чем изначально задача) — формулируйте изначальную задачу заново. И так повторяйте до тех пор пока не получите удобоваримый результат.

Вот как выглядел мой итоговый запрос:

Давай создадим новый файл, основываясь на этой задаче — “Есть таблица из 20000 строк. Столбцы этой таблицы — «Поисковая фраза (Директ), Визиты, Посетители, Отказы, Глубина просмотра, Время на сайте». Вторая строчка «Итого и среднее» содержит суммы с средние значения моих данных. Потом идет 19.998 строк с данными. Визиты и посетители — целые числа, отказы — в процентах, глубина просмотрах в десятичных числах с тремя знаками после запятой, время формата ЧЧ:ММ:СС.” (тут я скопировал изначальные условия) Напиши мне формулу, которая найдет все фразы с отказностью более 0.2 (эту часть добавил что бы он не написал 20, как в первый раз) и добавит их на новый лист в две отдельные колонки (фраза и отказность). Мой файл называется context_data.xlsx (что бы он понимал как называется файл) Теперь у меня в полученном мне нужно вычленить из полученных данных все наиболее повторяющиеся фразы или словосочетания и посчитать их повторы (без учета союзов и местоимений) (эти уточнения сильно фильтруют итоговый результат. Потмоу что очевидно что самые частые слова будут союзами). Сделай отдельно лист с результатами повтора словосочетаний (где больше 1 слова), и отдельно лист с самыми часто повторяющимися словами. Важно что каждая строка в целом уникальна, но в ней могут содержаться одинаковые словосочетания или фразы (если это не описать, он просто будет искать одинаковые строки, а их у меня нет). Результаты добавь на новый файл. Код напиши на питоне.

В итоге я получил длинную портянку кода и инструкцию:

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

После запуска у меня была всего одна ошибка, которая была вылечена одной доп. строчкой. После чего я получил вот такой итоговый файл

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Как нейронка за меня таблицы считала (живой пример) Программирование, IT, Python, Удаленная работа, ChatGPT, Личный опыт, Работа, Таблица, Microsoft Excel, Длиннопост

Алгоритм всегда один и тот же — описали задание, если выполнилось с ошибкой — кидаем ошибку, он ее исправляет. Если без ошибок — усложняем задачку, и заново формируем ее в запросе.

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

По итогу получаем готовую таблицу с нужными нам данными, попутно осваивая питон.

Зачем я все это пишу и показываю?
Данный метод работы сократил мое время на обработку данных, позволяет мне кинуть в разговоре “да я тут на питоне прикинул”, что резко повышает ценность в глазах других маркетологов и начальства, и вполне обоснованно позволяет писать новый навык на линкедине.

А если более серьезно — нейросеть может сильно ускорить выполнение рутинных и нудных задач. Она как гугл — главное правильно составить запрос. Не “посчитай мне итог по Сыктывкару для прошлого квартала” а “У меня есть таблица А, в ней колонки АБС, содержат данные таких то форматов. В колонке Б у меня города рф, в колонце С у меня оборот, в колонке Е вид материала. Создай новую таблицу где будет сумма всех поставок пургена для областей которые содержат букву Ы в названии и состоят из 9 букв”. Такой запрос очень понятен, его можно разбить на подзадачи и написать алгоритм. А какой в итоге для этого будет использоваться язык программирования — не имеет значения (ну вообще имеет, если язык появился после 21 года, то есть шанс что чат-гпт 3.5 не знает об этом). Нейросеть можно попросить что то объяснить в коде, рассказать о методе или причинах выбора такого способа решения, и писать запросы человеческим языком.

Использование нейросети для работы не напрямую с формулами, а через сторонний язык программирования позволяет работать сразу с нужными нам файлами. Скоро, когда майкрософт внедрит окончательно нейросеть в стандартный пакет офиса — такие задачи можно будет попросить решать нейронку сразу напрямую в экселе. Но пока что это недоступно простым менеджерам.
Поставить IDE питона — элементарно. Запустить скопированный код из чата с нейронкой — дело 2 секунд. Если у вас есть ежедневные (еженедельные, повторяющиеся) задачки с какими то однотипными выгрузками — вы один вечер потратите на написание кода через нейросеть, потом сможете использовать его постоянно. Сэкономленное время можно потратить на срач в комментариях на DTF или пикабу, или поиск новой работы аналитиком.

Если хоть одному человеку это сэкономит больше времени чем я потратил на эту простыню — это будет означать что я писал все не зря.

Телеграм канала нет, паблика нет, контактов нет, никуда не подписывайтесь, я пишу очень редко.

Показать полностью 13
5 месяцев назад
Подписаться

Подборка из 82-х полезных нейросетей⁠ ⁠

Подборка из 82-х полезных нейросетей Искусственный интеллект, Программирование, Халява, Бесплатно, Подписки, Услуги, Лайфхак, Подборка, Сайт, Приложение, ChatGPT, Нейронные сети, Интернет, Полезное, Длиннопост

Чехов сказал: «Краткость — сестра таланта», поэтому держите подборку из 82-х полезных нейросетей, которые можно попробовать и чуточку ощутить будущее, которое уже наступило. Постарался разделить по категориям, чтобы вам было удобнее ориентироваться.
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
Необычные нейросети:
● The Dream Keeper — Оживи свой сон.
└ Визуализируйте свой сон по запросу
● AiOrNot — Полиция в сфере ИИ.
└ 95% распознает работу ИИ
● SkyBox Blockade Labs — Создай «мир».
└ Введи текст, ИИ сгенерирует «мир»
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
Работа с изображениями:
● 3DFY — Генератор 3D-объектов.
└ Напиши слово и получи 3D-объект
● Kandinsky 2.1 — Генератор картинок.
└ Генерируйте по текстовому запросу
● CleanUp — Удаляет водяные знаки.
└ Можно вырезать целые объекты
● Uncrop — Расширяет фон.
└ Напоминает Generative Fill
● Mokker — Генерирует фон.
└ Загрузи фото, ИИ заменит фон
● Anything AI — Меняет объекты/фон.
└ Пару кликов прямо в браузере
● FotoFix / Restore Photos / Face PR.
└ Улучшайте качество изображений
● VectoRizer — Векторизация фото.
└ Превращает в векторную графику
● PicWish / BigJpg — Повысить пиксели.
└ Сделайте фото в 4 раза лучше
● CountThings — Считает объекты.
└ ИИ считает объекты на фото
● Зрение Mail — Ч/Б в цветное.
└ Отреставрируйте старые фото
● Synthesys X — Копирует оригинал.
└ Создайте похожее изображение
● SwitchLight — Меняет свет.
└ Меняйте цвет, угол и интенсивность
● Runway — Генерирует фон для изображения.
└ По текстовым запросам
● Aalab — Фотошоп на максималках.
└ Имеется пробная версия на 3 дня
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
Работа со звуком:
● Audioread — Текст в аудио.
└ ИИ генерирует текст в аудио
● ElevenLabs / DupDub — Озвучка для видео.
└ Генератор качественной озвучки
● Whisper JAX — Аудио в текст.
└ Вставьте ссылку или видео = текст
● SonGR — Генератор музыки.
└ ИИ создаст текст, вокал и бит
● RiverSideFM — Аудио в текст.
└ Загрузите видео, получите текст
● VocalRemover — Удаление вокала.
└ Вырезать можно не только вокал
● Podcastle AI — Озвучка для видео.
└ Генератор качественной озвучки
● Ambient — Заметки после диалога.
└ Из речи собеседника (напр. в Zoom)
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
Работа с видео:
● Video Editing Tool — Создай ролик.
└ Загрузи картинки, получи ролик
● ZebraCat Al — Генератор роликов.
└ Генерируйте видео через текст
● Zeroscope — Генератор видео.
└ Генерируйте эпичные видео
● Kapwing AI — ИИ-видеоредактор.
└ Монтируйте с помощью ИИ
● VOT — Закадровый перевод.
└ Работает через Tampermonkey
● Eightify — Резюмирует видео.
└ Расширение для Google Chrome
● Descript — Редактор видео и аудио.
└ Редактируйте с ИИ, свои подкасты
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
Работа с документами:
● ChatGPT — Работа с документами.
└ Задавайте вопросы по документу
● Quizard Al — ИИ решит ваши тесты.
└ Загрузи фото вопроса, получи ответ
● ChatBCG — Генератор презентаций.
└ За 1 клик создавайте презентацию
● Explanepaper — Диплом вкратце.
└ Загрузи документ = Краткая статья
● OpenResume / KickResume — Резюме.
└ Генерируйте качественное резюме
● Roam Around — Генератор текста.
└ Задайте тему, ИИ пишет материал
● Tutorle.Al — ИИ по точным наукам.
└ 10 запросов/день на английском
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
Для программистов:
● 60SECsite — Генератор сайтов.
└ Напиши идею, ИИ сгенерирует сайт
● html.to.design — Генератор шаблонов.
└ Превратит любой сайт в Figma-шаблон (Figma на 2 года бесплатно)
● Piggy Magic — Генератор дизайна.
└ ИИ напишет дизайн сайта по запросу
● uKit AI — Генератор редизайна.
└ Проанализирует ЦА и напишет дизайн
● ChatGPT Prompts — Сборник промптов.
└ Настройте веб-дизайнера из ChatGPT
● Fronty — Конвертирует в HTML CSS.
└ Загрузите картинку или наброски
● Indigo.Design — Дизайн в код.
└ Конвертирует дизайн в код
● Website Builder — Конструктор сайтов.
└ Создайте сайт через ИИ-конструктор
● GhostWriter — Поиск ошибок в коде.
└ Ищет/комментирует ошибки в коде
● Adrenaline — Поиск ошибок в коде.
└ Работает в браузере и на устройстве
● Code GPT — Генерирует блоки кодов.
└ По вашим текстовым запросам
● Galileo Al — Генератор интерфейсов.
└ По вашим текстовым запросам
➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
✅ Если хотите поблагодарить автора — подпишитесь в Telegram.

Скрипты, когда и где они нужны? Как работают?

Я жуткий дилетант и любитель. Хочется двигаться дальше, получать больше знаний.
Если вас это не очень затруднит, хотел бы побеседовать на тему использования скриптов в играх.

Сейчас куда не посмотри, все юзают скрипты даже в казуальных играх.
Зачем это так уже необходимо?

1. Чтобы свести на минимум количество перекомпиляций проекта во время разработки? А если проект небольшой, компьютер мощный, а код толково разделять на отдельные файлы hpp/cpp? Всё равно преимущество скриптов на лицо?

2. Цитата из темы о скриптах: «у меня сейчас в проекте 15 мини-игр, кодить их все на плюсах — это жесть, а на скриптах накидаю без проблем».
А почему жесть на плюсах? Потому что человека уже тошнит от с++ после n-лет работы в индустрии?

3. Когда наступает тот момент, когда однозначно нужно использовать систему скриптов в игре вместо «хардкоженья» всего на С++? Когда проект большой, или когда в команде много программистов, или это уже стандарт в индустрии?

4. Встречаются ли сейчас более менее серьёзные проекты без скриптов? Когда отказ от скриптов и написания всего проекта на С++ оправдано?

5. А движки вроде Unity3d вообще стоят отдельным особняком и в них эти вопросы не возникают — по сути всё и так делают на скриптах. Или бывают и тут необходимость в более высокоуровневых скриптах возникает?

6. Связь между скриптом и монолитным нативным кодом игры для меня загадка. Вызываются ли скрипты каждый кадр, т.е. интерпретатор скриптов работает каждый кадр? И обмен переменными между скриптами и программой идёт постоянно во время работы игры?
или же скрипт выполняется только во время запуска сцены?
До недавнего я полагал, что на скриптах пишут, какие ресурсы грузить, какие объекты с какими параметрами для сцены создавать, условия победы/поражения и т.д.
А вот как можно писать логику на скриптах?
Насколько я понял, скрипты вызывают ф-ии нативного кода. Значит с++программисты пишут все необходимые действия (ф-ии), вроде перемещений объектов, физики и т.д., а скрипты дают команду вызывать те или иные ф-ии?

7. Если скрипты призваны облегчить процесс разработки, то есть ли возможность перед релизом скомпилировать скрипты во что-то более близкое к нативному коду дабы повысить производительность?

P.S. И на последок. Я тут потихоньку в свободное время пишу небольшой проект, как программист я один, есть и художник. Потихоньку двигаемся. Получается ничего так, может даже издаваться будем 🙂 Так вот, я написал все нужные инструменты и везде использую только С++, скрипты не использую. Всё получается и проблем с неудобством разработки не вижу. Вопрос — я чего-то упускаю или можно со спокойной душой продолжать все делать так, как делаю?

Спасибо, что дочитали сей выплеск)
Всех с Наступающим!)

#1
12:38, 30 дек 2013

Zackary
> А почему жесть на плюсах?
Сложней и дольше. Рабочее время C++ программиста стоит дорого.
Zackary
> Когда наступает тот момент, когда однозначно нужно использовать систему
> скриптов в игре вместо «хардкоженья» всего на С++?
Когда вы начинаете делать вещи типа «тут надо добавить на потолк верёвку чтобы когда игрок за неё дёрнул — ему на голову упал кирпич». Вы не захотите это хардкодить.
Zackary
> Встречаются ли сейчас более менее серьёзные проекты без скриптов?
Нет. Почти.
Zackary
> Если скрипты призваны облегчить процесс разработки, то есть ли возможность
> перед релизом скомпилировать скрипты во что-то более близкое к нативному коду
> дабы повысить производительность?
В принципе да. Но скорей всего проблемы не будет.
Zackary
> Так вот, я написал все нужные инструменты и везде использую только С++, скрипты
> не использую. Всё получается и проблем с неудобством разработки не вижу.
Ну это и хорошо. Не надо прикручивать фичи ради фич. Когда у вас появится отдельный геймдизайнер — то вам понадобятся и скрипты в каком нибудь виде.

#2
12:44, 30 дек 2013

Есть lua-jit например, не нативный код, конечно, но близко.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *