mafon2, сейчас пригляделся. В общем, проблем чуть меньше, чем дофига Во-первых, несмотря на то, что у тебя:
Код
// В комнате LEVEL_1 объект LEVEL_1_SYS, в нем // Событие Create GEMS = 0;
- ссылаться в событии Create на переменную другого объекта НЕЛЬЗЯ:
Код
// Событие Create объекта SYSTEM_INI global.A1L1_GEMS = LEVEL_1_SYS.GEMS; // Так делать НЕ правильно
Дело в том, что объекты создаются последовательно, друг за другом, в зависимости от того, какой объект был раньше размещён в комнате, а какой позже. И когда, например, создаётся экземпляр объекта SYSTEM_INI, так как он был размещён в комнате раньше, поэтому получил более меньшее ID, поэтому и создаётся раньше - он ещё не знает о переменной объекта LEVEL_1_SYS, потому как его очередь события Create не подошла. Вариант решения проблемы: для объектов, которые создаются одновременно, лучше объявлять все переменные в теле одного события одного объекта. Например:
Код
// Есть событие Create у объекта SYSTEM_INI // Здесь мы будем объявлять все переменные // И глобальные, и встроенные в экземпляры LEVEL_1_SYS.GEMS = 135; // Вот, мы объявили переменную экземпляра LEVEL_1_SYS, теперь можем использовать её в данном теле события Create global.TOTAL_A1_GEMS = 0; global.A1L1_GEMS = LEVEL_1_SYS.GEMS;
Это что касается ОДНОВРЕМЕННОГО создания экземпляров и перекрёстного присваивания значений. Если же нам каким-то образом необходима конструкция:
Код
global.A1L1_GEMS = LEVEL_1_SYS.GEMS
без явного обозначения переменной GEMS у объекта LEVEL_1_SYS, тогда придется прибегнуть к динамическому созданию экземпляра. Например:
Код
// Событие Create объекта LEVEL_1_SYS GEMS = 0; // Объявили все необходимые переменные, теперь создаём другие объекты instance_create(0, 0, SYSTEM_INI); ... ... ... // Событие Create объекта SYSTEM_INI SomeVariableName = LEVEL_1_SYS.GEMS // Profit!
Во-вторых, так лучше не делать:
Код
globalvar GEMS; // Глобальная переменная с именем GEMS (P.S. от globalvar лучше совсем избавиться) global.A1L1_GEMS = LEVEL_1_SYS.GEMS; // Встроенная переменная с именем GEMS
Лучше не использовать одинаковые названия переменных. Если прям необходимо назвать переменные как-то похоже, потому как они выполняют похожую роль, то лучше использовать префиксы, к примеру:
Код
global.GEMS = 0; LEVEL_1_SYS.inst_GEMS = 0; // добавили префикс inst_, чтобы легко отличить, что это переменная экземпляра (instance)
Ну а лучше вообще пересмотреть и переработать иерархию и структуру переменных. Уменьшить их количество, сделать их более понятными и увеличить зону их применения. (но опять же, в меру). К примеру:
Код
// Хотим определить направление движения игрока: сервер, запада, юг или восток // Как в большинстве случаев НЕ надо делать isNorth = false; isWest = false; isSouth = true; isEast = false; // Легко запутаться, нагородить ошибок, да к тому же выделяем лишнюю память. // Лучше поступить так: объявляем числовую переменную dir, которая может принять 4 различных значения // 0 - Север, 1 - Запад, 2 - Юг, 3 - Восток. // и получаем: dir = 2; // Игрок смотрит на Юг. // А если хотим сделать ещё нагляднее, можно использовать перечислители, enum: enum Direction { North = 0; West = 1; South = 2; East = 3; } dir = Direction.South; // Запись, конечно, увеличилась, зато ни у кого не вызовет никаких сомнений, что она означает.
В-третьих, если этот код
Код
//Step
//Код A1L1_GEMS = GEMS;
выполняется в теле события Step объекта LEVEL_1_SYS, то здесь, как я уже сказал выше, возникает конфликт внутренней и глобальной переменных GEMS. Про разные названия переменных я уже сказал, скажу ещё, что одной из причин создания префикса "global." является подобный случай использования.
Вроде, пока всё. Действительно, вещь простая, и особых проблем вызывать не должна, но камнем преткновения здесь является чрезмерно загроможденный код и обилие второстепенных переменных. Я, конечно, не знаю всех тонкостей игры, какие данные где и зачем должны храниться, но что-то мне подсказывает, что всё можно упростить как минимум в два раза. Ах да, что касается переменных, которые должны хранить данные на протяжении всей игры и не обнуляться при смене комнаты: как вариант, создать объект, например obj_variables, задать ему свойство Persistent в менеджере объекта, и уже в теле события Create объявить все необходимые переменные. Такой объект достаточно разместить только в самой первой комнате, но "жить" он будет на протяжении всей игры, пока игра не закончится или пока объект не будет удалён вручную. Событие Create у такого объекта происходит только один раз, независимо от перехода из/в комнату.
Сообщение отредактировал Rean - Пятница, 18 Ноября 2016, 13:41
Один из вариантов перемещения между дверьми в платформере: Doors.gmz
Основной принцип реализации: Все двери являются экземплярами одного объекта, но с уникальными значениями двух переменных: doorId (идентификатор двери) и goToDoor - номер двери, в которой должен появиться персонаж после перехода. Переход выполняется при нажатии игроком стрелки вверх, при пересечении двери персонажем. Персонаж плавно исчезает возле одной двери и появляется возле другой.
Весь необходимый код, в принципе, комментирован, необходимо, думаю, только пояснить пару моментов: - у дверных спрайтов коллизионная маска выставлена точкой (или очень коротким отрезком). Сделано это для того, чтобы игрок мог пересечься с дверью, только когда он полностью находится на спрайте двери (то есть, он не торчит за пределом двери ни слева, ни справа).
- также, у каждой двери, размещённой в комнате, изменено событие Create. Это сделано, чтобы можно было легко и просто настроить "какая дверь куда ведёт". Достаточно определить всего лишь значения двух переменных: doorId и goToDoor. Если параметр goToDoor будет равен "-1", то дверь никуда не будет вести (имеется ввиду, без вываливания ошибки).
mafon2,
Цитатаmafon2 ()
Я в этом и не сомневаюсь, но это и отличает программиста от энтузиаста. У меня, как говорится, – сплошные спагетти.
Понимаю. Всё отлично. Главное, что есть желание разбираться, а это уже половина успеха
Сообщение отредактировал Rean - Суббота, 19 Ноября 2016, 02:16
vadim74a, в одном платном из них в End User Licence Agreement (EULA).
лицензионное соглашение с конечным пользователем ("ЛСКП")
3. ДОСТУПА К АКТИВАМ И УСЛУГ
3.5. Активы-это лицензии, а не продается. Когда вы покупаете активы, происходит то, что Издательство не предоставляет Вам неисключительную, всемирную силу и неограниченный срок право (юридически известный как “лицензия”) на активы с целью их использования и их интеграции в интерактивные развлекательные продукты (которые можно распространять бесплатно или за деньги – решать вам). Вы можете копировать, использовать и изменять активов только для этих целей, и Вы не можете распространять, сублицензировать, сдавать в аренду или во временное пользование активов. Поэтому Вы приобретаете лицензию на активы, а не покупать сами активы (Издатель до сих пор владеют). Вашу лицензию на активы является предметом настоящего Соглашения.
Подскажите, пожалуйста такой момент: Есть объект (космический корабль) со спрайтом из нескольких картинок (движение вперед, назад, остановка). Хочу чтобы независимо от этого спрайта дорисовывались еще два при повороте (один справа, другой слева). Пытался сделать через draw_sprite, но ничего не рисуется, хотя сам поворот происходит. По какой то причине у меня вообще draw_sprite никогда ничего не рисует. Что я делаю не так?
aedginvael, не лучшая идея менять значение переменных в Draw Events. Точка с запятой после D не нужна. Объект имеет экземпляры в комнате и активный параметр Visible? Данный код говорит, что отрисовывать объект (сам объект и дополнительный спрайт) необходимо ТОЛЬКО при нажатии D. Всё остальное время ничего отрисовываться не будет. Добавлено: а, ну и самое главное - ты рисуешь второй спрайт поверх первого по тем же координатам.
Сообщение отредактировал Rean - Вторник, 29 Ноября 2016, 22:47
1) Там нет точки с запятой. Просто когда я выложил сюда код, в этом месте появился смайл. Сколько я не пытался удалить их от туда, все равно они дописываются и рисуется смайл. Но это отступление от темы. 2)объект в комнате всего 1 и он visible 3)Да, отрисовывать все это нужно ТОЛЬКО при нажатии кнопки D 4) Да, я рисую один спрайт поверх другого с координатами в одной точке, потому что сами спрайты смещены так, что изображение не накладывается. Я сделал так, чтобы не путаться с координатами.
1) Для кода лучше использовать специальные теги code. 2, 3, 4 - вот с этого и надо начинать. Чем больше информации, тем больше шансов, что кто-то сможет помочь. А иначе приходится угадывать, что там у кого случилось.
Такой момент: в каком событии код? Всё рисование должно происходить в Draw Event (Draw Begin, Draw End, etc) И правильно я понимаю, что больше в комнате нет никаких других объектов, фона и прочего? Views не задействованы?
Сообщение отредактировал Rean - Среда, 30 Ноября 2016, 01:01
Да, в комнате есть фон и Views. Все, спасибо, я понял в чем был не прав. Появился еще вопрос: как сделать, чтобы direction рисуемого спрайта, совпадал с direction объекта?
Да, спасибо! Теперь то, что нужно! Подскажите, пожалуйста, где почитать о создании кнопок, меню, всплывающих окон и т.д.?
Добавлено (01 декабря 2016, 13:01) --------------------------------------------- Снова вопрос: Есть объект - космическая станция. Хочу сделать запрос "Свой/Чужой" по всем объектам в радиусе действия. Переменная friend имеет значения 0,1,2,3 что соответствует: "Неитрал", "Свой", "Чужой", "Агр чужой" id_obj получает id экземпляра Затем проверяется его статус. В зависимости от результата проверки: или запускаются шлюзы, или запускается система обороны станции (sos); Пока объект был один, проблем, вроде бы не было. Но как только появились другие (пушки на станции, friend = 1), то все перестало работать. Вернее сказать работать стало все: и шлюзы, и пушки. Причем пушки просто моргали анимацией, не запускаясь полностью. Подскажите, что я делаю не так?
Код
id_obj=collision_circle(x,y,500,all,0,1); if id_obj >0 { if id_obj.friend = 3 { sos = true; } if id_obj.friend = 1 sos = false; }
На орудия step:
Код
image_index = 0;
if obj_mir.sos { target = obj_mir.id_obj; if distance_to_object (target) <distan and image_index <4 and done { image_index +=1; done = false; alarm[0] = done_speed; }
if distance_to_object(target) <distan-100 and image_index = 4 and canshot { image_angle = direction; instance_create (x,y,obj_lazer); alarm[1] = speed_shot; canshot = false; }
if distance_to_object (target) > distan and done { image_index -=1; done = false; alarm[0] = done_speed; } }
Сообщение отредактировал aedginvael - Среда, 30 Ноября 2016, 23:31
id_obj=collision_circle(x,y,500,all,0,1); if id_obj >0 { if id_obj.friend = 3 { sos = true; } if id_obj.friend = 1 sos = false; }
Во-первых, collision_circle всегда будет возвращать только один instance. И вполне возможно, что это будет один и тот же instance. Если, к примеру, пушка в одно время может иметь только одну цель - то, в принципе, это может сработать. А если надо проверить всех, кто находится в круге - здесь ждёт неудача. К тому же стоит иметь ввиду, что collision_circle не всегда возвращает ближайший объект, а лишь объект который попадает в зону коллизии. Во-вторых, более читаемый код выглядит с использованием конструкции switch:
Код
... if (id_obj != noone) switch (id_obj.friend) { case 0: тра-та-та; break; case 1: sos = false; break; case 3: sos = true; break; }
Можно, конечно, ещё компактней, но это для тривиальных случаев:
Код
sos = (id_obj != noone) and (id_obj.friend == 3)
В-третьих, в событии Step орудия, ты в начале каждый раз обнуляешь индекс, а потом пытаешься сделать следующий (или предыдущий кадр), но в следующем степе у тебя всё будет заново (нулевой кадр +- 1). Таким образом анимация никогда не проиграется и всегда будет показывать кадры 0, 1. Думаю, перечисленные выше причины - краеугольный камень проблемы. Решив их, ситуация должна более-менее проясниться.
P.S. Все три конструкции (if distance_to_object (target)...), наверное, лучше расположить в конструкции if-else, чтобы лишний раз не дёргать проверки. Хотя, я не знаю задумку, поэтому здесь тяжело что-то советовать. P.P.S Вместо image_index += 1, я бы всё же предпочёл устанавливать image_speed. Иначе получается жесткая привязка к room_speed. Ну и при потере кадров, будут пролёты анимации.
Сообщение отредактировал Rean - Пятница, 02 Декабря 2016, 00:50
Да, обнуление image_index уже увидел. Проблема с проверкой объектов осталась: Есть инструмент более подходящий для этой задачи, чем collision_circle? Или может есть способ его более грамотного использования? Цель по сути простая: при верном коде проверки - отношение к объекту "Друг". Если код у объекта (одного или нескольких) не верен, то отношение к объекту "Враг" т.е. атаковать объект. Имеет смысл каждому орудию писать аналогичный поиск объектов "Враг" для стрельбы, или это не эффективно? И как рисовать что то относительно рамки экрана, а не относительно комнаты?
Сообщение отредактировал aedginvael - Четверг, 01 Декабря 2016, 19:35
aedginvael, вариантов много. Один из: 1. Создать функцию, которая будет перебирать все экземпляры определённого объекта и проверять их на коллизию с необходимой областью. Формирует из них массив и уже с этим массивом мы делаем всё что нам хочется. Ещё один вариант: Создать объект с прозрачным спрайтом (или спрайтом отображающим нашу область), сделать у него маску (круглую, квадратную, в общем, какую нужно) - простой объект, который будет отвечать за нашу зону видимости. Отключим его отображение (Visible = false) и будем проверять его на коллизию со всеми необходимыми нам объектами. В событии коллизии мы может напрямую обращаться к тому или иному экземпляру, проверяя его свойства и т.д. Главное, чтобы объект-зона всегда совпадал с центром станции/корабля и имел на него ссылку (чтобы выполнять необходимые изменения). Возможно, не самый быстрый, но вполне наглядный и удобный при использовании. 2. Если орудия будут стрелять в одно время только по одному противнику, то лучше сделать функцию поиска-определения только для станции (а она уже будет напрямую связана с орудиями) 3. Если рисовать в методе Draw, то надо взаимодействовать с x и y координатами вида (view_xview, view_yview). Для GUI же лучше использовать события DrawGUI - там будут использованы координаты окна.
Добавлено: вот, набросал пример по первому пункту. CheckCollision.gmz Добавлено 2: поправил ссылку
Сообщение отредактировал Rean - Пятница, 02 Декабря 2016, 00:55
Извини, я не очень понял как открывать твой файл. Можешь объяснить?
Добавлено (03 декабря 2016, 00:12) --------------------------------------------- И еще: за view_xview view_yview - спасибо большое, но появился новый вопрос. У меня используются два вида. view[0] - это вид в окне, view[1] - это вид в маленьком окошке миникарты. На view[0] виде я через draw нарисовал небольшой интерфейс. Однако теперь он виден на миникарте view[1]... Как его скрыть от view[1]
Добавлено (03 декабря 2016, 00:56) --------------------------------------------- Можно описать колижн с группой объектов у которых общий объект родитель? Чтобы не прописывать колижн с каждым объектом отдельно.