7 дней лета

Объявление

PSA: Актуальная версия мода: 7дл v.037a: Славя-7дл, завершение истории.
В разработке: Одиночка, д.6
Контакты:
vk.com/7dl_kun
steamcommunity.com/id/7dl_kun
twitter.com/7dl_kun
Skype: simeon-loki
mail: bl7dl@ya.ru телега: https://t.me/bl7dl
Спасибо всем, кто прислал денежку! Вы действительно помогаете сделать 7дл лучше!
Реквизиты для желающих помочь проекту
Карточка: 4790 8723 0122 5783
Я. Деньги: money.yandex.ru/to/410015008177902
Paypal.me/7dneyleta
Webmoney: R696999046792
patreon.com/7dl
Ресурсы, музыку, элементы скриптов и прочие составляющие мода можно свободно брать - при условии указания, откуда что брали! Не жалко!

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » 7 дней лета » Общее обсуждение мода » СПИСОК КОНТЕНТА


СПИСОК КОНТЕНТА

Сообщений 181 страница 210 из 710

1

Дорогие россияне!
Любой завод начинается с чертежа, любой фильм начинается со сценария.
Многие здесь хотят помочь автору, понимаешь. Но вот чем — всегда встаёт вопрос. За каждым конкретным предложением в личку ходить если будем, то слишком много времени отнимем у себя и у автора.
На базе этого предложение: создать определённый пост или тему, где будет список нужного творчества. По мере выполнения позиции будут вычёркиваться. Это будет заглавный пост. В ответных постах можно постить сами работы, чтобы можно было сразу же предлагать доработать/переделать. В итоге, весь процесс сразу будет перед глазами. И никакой телепатии!

Итак, список требующегося контента.

TODO LIST:

Фоны aka BG

• Секретное убежище Лены. Место, расположенное в глухих зарослях - в центре небольшая поляна с костровищем в центре, огороженным с трёх сторон брёвнами. Яма костровища утоплена относительно окружения, в самом костровище горит костерок (Дневная и ночная версии)

• Здание администрации лагеря, вид изнутри (вид из окна здания администрации (в приложенной карте показан возможный ракурс - на Генду в профиль, медпункт и столовую) День, и дождь.

Ракурс

http://s1.uploads.ru/t/SlLvB.jpg

Пример из игры

http://s3.uploads.ru/t/0FSTE.jpg

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

Свернутый текст

http://s5.uploads.ru/t/qHlJw.jpg
http://s8.uploads.ru/t/0sPLm.jpg
http://s1.uploads.ru/t/KCcjU.jpg

• Госпиталь (голубое/зелёное (на выбор) здание с металлической крышей подобной крыше администрации, два-три этажа, широкое крыльцо с концентрическими ступенями-окружностями, справа вдоль стены - "рельсы" для каталок и кресел, сбоку - въезд для карет СП во двор с решётчатыми воротами)

Свернутый текст

http://s8.uploads.ru/t/4lAK6.jpg
http://s1.uploads.ru/t/7S5qT.jpg

• Вид на спальный район (зима, дорога с припаркованными машинами, ночь, рекламы, панельные "корабли)
• Остановка-автовокзал (зима, ночь, справа домик с вывеской "автовокзал" и люди с сумками на пятачке, по центру ларёк-становка, в левой трети проезжая часть с парочкой автобусов, мордой от наблюдателя)

Карта лагеря с поясняющими надписями

http://sd.uploads.ru/t/H1b8v.jpg

Вид с мансарды администрации на лагерь . К ней ведёт внешняя лестница с крылечком, калитка изнутри закрывается на крючок, располагается с торцевой стороны здания администрации. Нужны три версии: день, закат, ночь.

Примеры

http://sd.uploads.ru/t/Krcdi.jpg
http://sd.uploads.ru/t/fyGSd.jpg
http://sg.uploads.ru/t/5qob0.jpg

Теннисный корт - коробка с дверью, покрытие - газон, расположена на спортплощадке.

Пример

http://s6.uploads.ru/t/GlxOa.jpg

Потребуются в отдалённом будущем

Это потребуется в довольно отдалённом будущем, потом ТЗ по ним пока не оставляю)
Фон: вид из тонущего автобуса, здание загса(синее здание с портиком и огромными окнами), вид на вечерний зимний Питер с крыши,  подземный бетонный пенал с антивандальными фонарями в ряд вдоль длинных стен и тремя саркофагами у дальней короткой стены, ночной вид на океан с причала, выжженная пустошь(вариант постапок), провинциальный полустанок у путей (стандарнтная бетонная подушка, ступеньки, название нп "Радченко" в центре и т.п., вокруг лес), проходная на заводе.
ЦГ: вид на стёртого Семёна(пустые глаза, расслабленная поза, стекающая по губе ниточка слюны) closeup и в отдалении на Дороге (см. автобусную остановку), вид на простенок (кирпич) с врезающимися пулями, несущийся в кадр юзом джип(обычный и смятый в хлам), прыжок веры в туман (локация: подземная пещера), Мику в свадебном платье, Алиса в скафе a la HL, лаборатория(стол с техникой, истекающей серым туманом).

Сценки aka CG

СЮЖЕТ
• Вид на салон "Лиаза" чуть сбоку, за окнами чёрная холодная вода и угадывается опора моста, ночь, в салоне тоже уже есть примерно по колено.

Девочки

МИКУ

• ЦГ с Cемёном на диване, и огромным экраном с Мику на всю стену.

http://s7.uploads.ru/t/Dr9ov.jpg

Мику, лежащая на кровати с балдахином. Ночь, Лунный свет, Мику в ночнушке, в руках фотография. Справа огромное, на всю стену, окно, сейчас распахнутое. Комнатка небольшая, умещаетмя только кровать, тумбочка и шкаф. Да коврик у кровати, на котором в беспорядке набросаны бутылки, коробки и одежда.

• ЦГ с Мику, погружающейся в воду. Ванная, лазоревая плитка, пар над водой.

http://sg.uploads.ru/t/fbSpu.jpg

• Бэкстейдж, вид на эстраду и выступающую Мику из-за кулис.

• Плачущая Мику из эпилога - редрав

http://sh.uploads.ru/t/GqoSE.jpg

• Эччи Мику

http://s9.uploads.ru/t/MbfI6.jpg

ОЛЬГА
• d6_mt_dance - медленный танец Семёна и Ольги
• scene cg d6_mt_hugging - Ольга, обнимающая Семёна.

СЛАВЯ
• Славя с Семёном на скамейке, ночная версия. Семён держит Славю за руку и немного краснеет, Славя улыбается, смотрит в сторону. Оба одеты в форму, перспектива немного со стороны так, что Славя находится на переднем плане.
• Поцелуй - Славя в купальнике, Семён в форуме, вид сбоку, она чуть ниже и тянется на носочках.

АЛИСА
• Аналогичные посиделки - но с Алисой. Семён улыбается, Алиса красная и смотрит в сторону, сводобную руку сжала в кулак.
• Семён получает пощёчину от Алисы - фон некритичен, ночь, оба в форме, Алиса в своей фирменной, злая, оскалившаяся, Семён шокирован.

УЛЬЯНА
• Полёт Ульяны в пододеяльнике.
• Домик на дереве (можно БГ).

РАЗНОЕ
• Щенок собаки породы "Саамская лайка" в картонной коробке, смотрит снизу вверх, перспектива чуть-чуть сверху, версия ночная, фон некритичен.

Спрайт: вожатая Катюшка (2 отряд)
Чуть ниже Ольги Дмитриевны, крайне фигуристая девица с завитыми волосами (не мелкие кудряшки, а крупные локоны) - то есть, тонкая талия, широкие бёдра, правильные пропорции, которые одежда не сможет скрыть.
Ощутимо светлее, рыженькая, с веснушками и болотно-зелёными глазами (темнее, чем у Лены, да и мельче - взрослая, всё-таки).
При желании, можно завить ей "рогульки" как у Миши из Катавы, будет отсылкой.
Одежда: форма вожатой (со значком УМЛ вместо Ильича), купальный костюм, вечернее платье.
Поз, желательно, три: потирающая подбородок, скрестившая руки на груди и упирающая руки в бока.
Перечень эмоций: Злость, нейтрал, смущение, грусть, возмущение, насмешка (grin), вина, serious, улыбка, смех, сюрприз.

Мишины рогульки

http://s7.uploads.ru/t/NKeEg.jpg
http://s9.uploads.ru/t/uyAQc.jpg

181

Amaurea написал(а):

Dantiras, пока концовки перечисляются сверху вниз, экран светлеет, затем темнеет. Так задумано?

Не-то чтобы задумано. Такова стандартная функция RenPy imagemap. Ей очень, видете ли, нужно наложить на фон ground, который хоть и обозначен как transparent (т.е. прозрачный), но на деле Вы наблюдаете это затемнение.

Т.е. сначала происходит вызов самих изображений, из которых формируется картина, и в течение этого процесса ground "intro_transparent" не накладывается (поэтому они светлые). Но по окончании анимированного вывода, происходит наложение, что и даёт затемнение областей.

Убрать аргумент ground нельзя. Иначе при старте БЛ происходит краш до запуска не только модов, но и даже главного меню.

P.S. От Вашего сообщения появилась идея проверить 100% прозрачный фон, вместо нашего 7ДЛ-ного intro_transparent, но все кнопки прекратили работать. Придётся жить с таким вопроизведением этой функции.

Отредактировано Dantiras (2017-01-16 10:14:18)

182

Dantiras написал(а):

Пойдёт, на Ваш взгляд, товарищи, такой вариант?

А мне светленький фон больше понравился...

Вообще, думал взять 7дл автобус(типа видео  где девушки появляются) и сделать его менюшкой - кликаешь по девушке - дальше её экран.

183

Вообще, думал взять 7дл автобус(типа видео  где девушки появляются) и сделать его менюшкой - кликаешь по девушке - дальше её экран.

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

184

Dantiras написал(а):

Придётся жить с таким вопроизведением этой функции.

Отлично живётся. Был полный функционал, сейчас ещё и приятное оформление.

HideoGodzilla написал(а):

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

1. Добавить пионера за окном. Тыкать в него.
2. Тыкать в пустое кресло подальше ото всех.
3. Тыкать в двери автобуса =)

185

Юра Кучугура написал(а):

А мне светленький фон больше понравился...

Там была идея выполнить всё в светлых пастельных тонах с индивидуальными нюансами бэков по каждую героиню.

Мне тоже он по ряду причин нравился больше. То ли здесь (на форуме), то ли в Стиме, а может и ещё где-то видел вопрос: "А почему же я сразу не сделал этот ачивлист на "авторских рельсах"?".

Это было сделано по целому ряду причин:
1. Сама идея моего ачивлиста родилась немного раньше, чем появились первые наработки тов.Автора по этому вопросу;
2. Я в тот момент являлся членом Кошкорут-команды и считал необходимым наличие блока "Юля", тем более что количество концовок и ачивок предварительно было известно;
3. Я считал, что ачивки необходимо показывать в увеличенном 150-200%, а не 100% как сейчас, размере. Для удобства пользователей на мобильных платформах и для слабовидящих;
4. Я не был доволен представленным тов.Автором скудным функционалом ачивлиста (про мою нелюбовь к отдельной "прыгалке" в текущем варианте известно читателям ещё старого форума). Спасибо пользователям Steam за идеи по внедрённому функционалу;
5. Предложенный тов.Автором вариант с условно трапециевидными кнопками крайне тяжёл для ввода в код, т.к. RenPy понимает самостоятельно исключительно прямоугольные области. Пришлось бы вносить изменения в Python код RenPy. Сейчас это реализовано "костылями" из прямоугольников;
6. Отсутствуют важные по сюжету обозначения символов Ольги и Ульяны (песочные часы + волшебная палочка)$
7. Боковые кнопки ("Ольга", "Лена" и т.д.) довольно громоздки и съедают большие пространства, которые можно было бы использовать под более эргономичный функционал.

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

Отредактировано Dantiras (2017-01-16 15:01:08)

186

Ещё мне понравилась идея сделать что-то типа движка меню: в массивах задавать позицию, размер, image(s), label. И настраивать будет удобно, и переключить в альтернативный вид можно(уже молчу, что в игре можно использовать)

187

Dantiras написал(а):

5. Предложенный тов.Автором вариант с условно трапециевидными кнопками крайне тяжёл для ввода в код, т.к. RenPy понимает самостоятельно исключительно прямоугольные области. Пришлось бы вносить изменения в Python код RenPy. Сейчас это реализовано "костылями" из прямоугольников;

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

188

Не найдено изображение acm_logo_sl_good1 +-полчаса (РФ), кажется.
Предложение касательно кошочки: разделить Одиночку с ней, потому что ну рут же будет. Когда-нибудь.

189

shers написал(а):

Не найдено изображение acm_logo_sl_good1 +-полчаса (РФ), кажется.
Предложение касательно кошочки: разделить Одиночку с ней, потому что ну рут же будет. Когда-нибудь.

Так и знал, что забуду её раздублить. Пошёл править.
Кошочку к Кошочке (пусть делают, что хотят, сами). В Одиночке и так мест уже нет.

7dl-kun написал(а):

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

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

Отредактировано Dantiras (2017-01-16 20:31:26)

190

Ну и у меня пройдены все концовки Мику, но самые верхние (гуд и тру) не показываются как полученные. Хотя тут подозреваю проблемы с моей стороны. С замечанием: у меня было почему-то заблокировано ещё несколько (эксклюзив Локи и "Не надоест"). Пробежался прыгалкой, они получились, а эти две - нет.

191

shers написал(а):

Ну и у меня пройдены все концовки Мику, но самые верхние (гуд и тру) не показываются как полученные. Хотя тут подозреваю проблемы с моей стороны. С замечанием: у меня было почему-то заблокировано ещё несколько (эксклюзив Локи и "Не надоест"). Пробежался прыгалкой, они получились, а эти две - нет.

Код:
persistent.mi_7dl_true
...
persistent.mi_7dl_good_human

Вроде бы всё там на месте. Ачивки в концовках воспроизвелись? Персистенты точно перед ними стоят.

192

Dantiras написал(а):

persistent.mi_7dl_true
...
persistent.mi_7dl_good_human

Вроде бы всё там на месте. Ачивки в концовках воспроизвелись? Персистенты точно перед ними стоят.


Да, я даже в код заглядывал. Всё нормально. Буду посмотреть, авось завтра пофиксится. Если что - маякну.

193

shers написал(а):

Да, я даже в код заглядывал. Всё нормально. Буду посмотреть, авось завтра пофиксится. Если что - маякну.

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

Перезалил архив.

194

Полистал - норм.
Но сразу критика-предложения:

Свернутый текст

1. Я чёрный фон на макете оставлял как элемент прозрачности, вообще в голову приходило использовать целевые цг/бг в зависимости от вызываемой ачивки/концовки, как, например, вокзал в бэде Алисы. То есть, я могу выгрузить и макет полностью прозрачным, только расположение кнопок... Или даже расположение сейчас некритично, можно каждую кнопку рассовать по экрану вручную?
2. Из п. 1 - предлагаю делать реакцию героинь, если это не слишком трудно в плане кода. На бэд - плачущие, на гуд - улыбающиеся и т.д. То есть, делать фигурки героинь вызываемыми спрайтами, а не наклеенными на фон, как сейчас.
3. Звук - ну, тут всё понятно. Можно сделать звуки онховер и онклик, хотя и необязательно, но на фон крайне желательно пустить какой-нибудь саунд. Булки за нас всё решили, я их поддерживаю - какой-нибудь амбиенс будет там крайне уместен.

На правах возможного (но совершенно необязательного) развития проекта.

195

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

Antwort
7dl-kun написал(а):

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

Звук нужен - это факт. Но амбиенс как-то не лезет в такие чёрные тона, на мой вкус. Как-то флёр ностальгии по пройденному хочется и 7DL-related тоже хочется. Хоть Юримоподобное что-то включай, но опять out of style - светловатый он какой-то. Тут нужно очень хорошо подумать как сделать правильно.
Онховер, онклик я хотел сделать уже сейчас, но поленился (хочется уникальный онклик под каждый рут сделать). =)

7dl-kun написал(а):

вообще в голову приходило использовать целевые цг/бг в зависимости от вызываемой ачивки/концовки, как, например, вокзал в бэде Алисы.

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

7dl-kun написал(а):

можно каждую кнопку рассовать по экрану вручную?


Сейчас нельзя (вернее можно, но не хочется). Пробовал полгода назад делать такой же гибрид ачивлиста с перетасовкой кнопок в зависимости от выбранного рута (т.е. одна кнопка становилась ещё больше, а остальные уменьшались и смещались). Не понравилось - как говорит мсье Ленивый Бегун, "нарушало чувство прекрасного".
Не стал впускать в код ещё и инактивные кнопки сейчас, чтобы минимизировать возможные ошибки. При action у кнопок и сейчас немало действий, а было бы ещё больше. Главная задача была - создать удобоваримый внешне, полностью рабочий прототип.

Меня более-менее устраивает текущий внешний вид инактивного фона, чтобы его не изменять. Не представляю только какую бг/цг/картинку стоило бы использовать для украшательства страницы Одиночки + первичного меню. Нужны идеи.

7dl-kun написал(а):

То есть, делать фигурки героинь вызываемыми спрайтами


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

196

Dantiras написал(а):

слабый контраст с фоном в таких вариантах.

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

Dantiras написал(а):

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

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

Dantiras написал(а):

Звук нужен - это факт. Но амбиенс как-то не лезет в такие чёрные тона, на мой вкус. Как-то флёр ностальгии по пройденному хочется и 7DL-related тоже хочется. Хоть Юримоподобное что-то включай, но опять out of style - светловатый он какой-то. Тут нужно очень хорошо подумать как сделать правильно.

Есть же бессмертная классика, первый кастомный трек в сценарии, Prolog_1, он же Coma_white, раз так музыки хочется.

197

7dl-kun написал(а):

Есть же бессмертная классика, первый кастомный трек в сценарии, Prolog_1, он же Coma_white, раз так музыки хочется.

Можно хоть шопеновский Marche Funebre. Но Coma White это что-то близкое к желаемому. Подержу её в голове, как рабочий вариант.

7dl-kun написал(а):

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

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

7dl-kun написал(а):

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

Я думал выводить контур-обводку в момент вывода ачивки для таких случаев.

198

Только что наткнулся на такие originals, вполне пойдут Японией 90-ых. Вдруг пригодится для Мику-эндингов (после перекраски волос).
http://s1.uploads.ru/t/q6xGh.jpg
http://sg.uploads.ru/t/Q5H3S.jpg

199

Денежка на ЯД

200

Всё пришло, спасибо огромное (=

201

Господа, доброго времени суток.
Я хотел бы оказаться полезным проекту и попробовать накодить dungeon-crawler. В связи с этим у меня следующие вопросы касательно Т/З:
1. Вопрос первый и главный – насколько это ещё актуально? В какой стадии находится? Кто занимается?
2. Платформа/движок. Я лично с РенРу / Питоном сталкивался только со стороны конечного потребителя конечного продукта. А так, я как-то больше по Юнити со всеми вытекающими… (Устроит ли отдельно приложение (*.exe, *.apk, и т.п.), которое будет подгружаться ренРу?) Если нет, ну что же… нет такого движка / языка который было бы нельзя освоить… :-) Хотя я конечно подозреваю что возможности/удобство Unity и ренРу находятся в разных весовых категориях.
3. Dungeon-crawler понятие ну очень растяжимое. Соответственно можно подробнее о том, чего бы Вам хотелось? Насколько большой скоуп? Примеры?

202

Привет.
1. Актуально до сих пор.
2. Ренпай/питон. С юнити больше проблем будет.
3. Подробнее: сетка 8х8, статичный графон, реакция персонажей на обстановку, никаких излишеств, возможность пробежаться по коридору через несколько клеток в ряд либо ходить по клеточке за ход/разворачиваться. Примеры... Wizardry же (=

203

В одном из файлов кода был примерный порядок.

204

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

Собственно сам код (Питон 2.7.10):
Код:
# encoding: utf-8
# ИНИЦИАЛИЗАЦИЯ ЧРЕВА ПИТОНА
# Грузим библиотеки / модули

import os
import types
import pygame

from pygame.locals import *

# Проверяем обстановку/окружение, если что-то не так, то коммент в консоль, и на выход...
if not pygame.font:
    print(u"Ахтунг, печаталка не работает!")
    raise SystemExit
if not pygame.mixer:
    print(u"Ахтунг, будет глухо, как в танке!")
    raise SystemExit

# ДЕФАЙНИМ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ / КОНСТАНТЫ (Вне циклов и вне функций)
# Весь первичный набор данных (входящие переменные и т.п.) будут на старте помещаться сюда.
# Все классы при своей инициализации будут опираться на данные отсюда
# Питон... он такой питон...

# Статы Cемёна и его пассии (Позже они все уйдут в соответствующие классы)
carma = 100  # TODO Подлежит импорту из ренпи в момент инициализации - Карма у нас будет как удача
charge = 30  # Зарядка фонарика - сдох фонарик, двигаемся на ощупь... # TODO Наличие фонарика подтягиваем из...
passion = "SL"  # TODO Надобно пассию подтягивать из ренпи но пока пусть будет Славя
healthpoints = 100  # TODO Как по мне так, очень примитивно...

# TODO Вообще было бы хорошо вместо HP сделать нормальный класс Семёна с руками, ногами, головой и пусть дамаг
# прилетает туда... И как следствие определяется набор доступных действий
# Типа повредил руку - не можешь драться/ тащить предмет, повредил ногу, больше тратится кармы на передвижение...
# Такую же фигню будет прикольно сделать с пассией... поломала ноги -> У Сёмы опция "тащим на себе..." а если у Сёмы
# поломаны руки, то выбор -> бросить пассию в подземелье / ждать подмогу / обнять её ногами и сдохнуть...
# Вот уж где будет угар и содомия!
# Короче в этом плане DwarfFortress с проработкой персонажей/айтемов - эталон для подражания:
# надел перс тапки из шкуры огненного троля...
# ...получил: танец джига нон-стоп, 2% шанс поджечь таргет при ударе ногой, ожоги 3-й степени и
# флаги отношения окружающих - "идиот" и "шут гороховый"

# Переменные описывающие карту
tileSize = 32
mapOffsetX = 32
mapOffsetY = 32
walls = [17, 23, 24, 25, 27, 28, 35, 38, 42, 44, 45, 46, 52, 58, 59, 64, 66, 68, 73, 74, 76, 77, 78, 83]
levent = 85  # Координаты входа
levexit = 18  # Координаты выхода. Не знаю почему, но тут мне фильм "Куб" вспомнился :->
cell_descr_dictionary = {
    # Здесь, в словаре, можно дать произвольное описание месту (клеточке) по схеме
    # ИНДЕКС: "ОПИСАНИЕ МЕСТА",
    # TODO Описание интерактивных айтемов, снорков и прочих объектов будет в самих объектах
    levent: u"вход в шахту",
    levexit: u"кажется выход!",
    67: u"в углу забоя шахты лежит куча мусора. Покопаемся?",
    19: u"на одной из опор, поддерживающей свод шахты, нацарапано великое и могучее... x_й"
}

partySpriteSize = 30

# ДЕФАЙНИМ КАСТОМНЫЕ КЛАССЫ
# Можно сказать, что это реестр всех данных для игры (Как реестр в винде) в классах так же описываются
# методы / функции управления данными


class Settings:   # Класс хранит тупо внутри-игровые настройки
    debug_mode = True  # TODO - Пока врубим дебаг мод и да будет он оберегать нас
    scr_width = 800
    scr_height = 600

    def __init__(self):
        pass


class Party:  # Класс описывающий наших Чип и Дейлов. Наш девиз: "Слабоумие и отвага!"
    def __init__(self, spawn_position):
        self.x, self.y = Map.get_coor(spawn_position)  # Текущие координаты на карте как X и Y
        self.index = spawn_position  # Текущие координаты на карте как индекс
        self.width = partySpriteSize
        self.height = partySpriteSize
        self.xpos = self.x * tileSize + mapOffsetX + (tileSize - self.width)//2
        self.ypos = self.y * tileSize + mapOffsetY + (tileSize - self.height)//2

        # Плейсхолдер под Сёмкин спрайт
        self.image = pygame.Surface((self.width, self.height))
        pygame.Surface.convert(self.image)
        self.bg_color = (0, 100, 0)  # TODO - поменять на нормальную текстуру (набор-текстур)
        self.image.fill(self.bg_color)

        # Плейсхолдер под спрайт Пассии
        self.passimage = pygame.Surface((self.width, self.height))
        pygame.Surface.convert(self.passimage)
        if passion != "None":
            self.passimage.fill((0, 100, 0,))  # TODO - поменять на нормальную текстуру (набор-текстур)
            self.passion = passion
        else:
            self.passimage.fill((0, 0, 0,))    # Если Семён один, чтобы не усложнять жизнь тупо делаем спрайт
            self.passimage.set_colorkey((0, 0, 0))  # пассии целиком прозрачным и используем его как обычно.
            self.passion = ""

        self.last_frame_render = pygame.Surface((partySpriteSize, partySpriteSize))

        self.inventory = []  # Очевидно...
        # TODO инвентарь должен быть в руках, карманах... а не в сферическом вакууме:
        # Типа: болит рука -> не можешь нести айтем.

    def move(self, direction):
        if direction == "up":
            self.y -= 1
        elif direction == "down":
            self.y += 1
        elif direction == "right":
            self.x += 1
        elif direction == "left":
            self.x -= 1

    def update(self):
        self.index = Map.get_index(self.x, self.y)
        self.xpos = self.x * tileSize + mapOffsetX + (tileSize - partySpriteSize) // 2
        self.ypos = self.y * tileSize + mapOffsetY + (tileSize - partySpriteSize) // 2

    def render(self):
        self.update()
        rparty = pygame.Surface((partySpriteSize, partySpriteSize))
        pygame.Surface.convert(rparty)
        rparty.blit(self.passimage, (0, 0))  # Вначале рендерим спрайт пассии
        rparty.blit(self.image, (0, 0))     # Сверху накладываем Сёмкин Спрайт
        self.last_frame_render = rparty
        return rparty


class Cell:  # Класс описывающий содержимое клеточки карты, её координаты и внешний вид
    def __init__(self, x, y):
        self.descr = ""  # Тут будет хранится конкретное текстовое описание конкретной ячейки
        self.x = x  # Координаты ячейки-клеточки (от 0 до 9)
        self.y = y
        self.index = Map.get_index(x, y)  # Индекс ячейки (от 1 до 100)
        if y == 0 or y == 9 or x == 0 or x == 9:
            self.type = 0  # Если клеточки расположены на периметре карты - это стены с 0-ой проходимостью.
            self.descr = u"непроходимая стена. Кажется за ней нет ничего, кроме грунта, камней и горной породы."
        else:
            self.type = 1
            self.descr = u"есть проход."
        self.width = tileSize
        self.height = tileSize
        self.bg_color = (0, 0, 0)
        self.image = pygame.Surface((self.width, self.height))
        pygame.Surface.convert(self.image)
        self.image.fill(self.bg_color)
        self.cont = ""  # TODO Разбросать по лабиринту бафы/дебафы: "говно снорка", "Батарейка к фонарику", "Кирка"...
        self.xpos = x * self.width + mapOffsetX  # Координаты ячейки на экране в Пикселях
        self.ypos = y * self.height + mapOffsetY


class Map:  # это собственно карта-индекс с координатами стен (непроходимых участков) и иных объектов
        # и при желании наплодить таких карт можно сколько угодно, и в рантайме рандомно или в зависимости от
        # пассии Сёмки (от сценария) подгружать соответствующую карту

    def __init__(self):
        # Создаём АДъ в виде двухмерного массива из объектов класса Cell
        self.level = [[Cell(i, j) for j in range(10)] for i in range(10)]  # На синтаксис этой строки ушло 2.5 часа...
        # ПИТОН... СУКА... я тебя ненавижу... можете считать меня быдлокодером...
        # Но вот тот кто скажет что это интуитивно понятный синтаксис..., пусть бросит в меня тапком

        # Расставляем на карте вход, выход и стены
        self.entrance = levent
        self.exit = levexit
        # TODO возможно стоит запилить случайную генерацию карты,
        # или выбор из нескольких заранее прописанных карт
        # самое простое, кстати, можно у одной предопределённой карты менять случайно точки входа и выхода:
        # дёшево и сердито

        # Определяем длинну массива walls (а она в зависимости от карты может меняться)
        c = len(walls)
        # Для каждого элемента массива находим соответствующий "Тайл" и ставим там стену
        for i in range(c):
            x, y = self.get_coor(walls[i])
            self.level[x][y].type = 0
            self.level[x][y].descr = u"невыработанная порода. Скорее всего, при должном старании её можно разрушить."
        x, y = self.get_coor(self.entrance)
        self.level[x][y].type = 2
        x, y = self.get_coor(self.exit)
        self.level[x][y].type = 3

        # Для каждой клеточки, для которой в словаре прописано описание, переносим его в соответствующую клеточку
        for key in cell_descr_dictionary:
            x, y = self.get_coor(key)
            self.level[x][y].descr = cell_descr_dictionary[key]

        self.width = tileSize * 10 + mapOffsetX
        self.height = tileSize * 10 + mapOffsetY
        self.bg_color = (0, 0, 0)
        self.xpos = 0
        self.ypos = 0
        # Эта переменная хранит отрендеренную карту с последнего вызова функции map.render() (c прошлого хода короче)
        self.last_frame_render = pygame.Surface((self.width, self.height))

    def update(self):
        # Перед рендером карты было бы неплохо вызывать эту функцию, для обновления всех переменных Тайлов,
        # и назначения им соответствующих спрайтов, эвентов, и триггеров.
        # Теоретически - это можно сделать всего один раз, после инициализации левла, но вдруг у нас руки дойдут до
        # динамически изменяемой карты ("снос куска стены динамитом" / "Долгая и упорная работа киркой" / "Обвал")
        for i in range(100):
            x, y = self.get_coor(i)
            if self.level[x][y].type == 0:
                self.level[x][y].image.fill((255, 0, 0,))  # TODO Сделать рандомный тайл подходящий по типу
            elif self.level[x][y].type == 2:
                self.level[x][y].image.fill((0, 0, 255,))
            elif self.level[x][y].type == 3:
                self.level[x][y].image.fill((0, 255, 0,))
            else:
                self.level[x][y].image.fill((255, 100, 100,))

    def render(self):
        self.update()
        rmap = pygame.Surface((self.width, self.height))
        pygame.Surface.convert(rmap)
        rmap.fill(self.bg_color)
        for i in range(100):
            x, y = self.get_coor(i)
            rmap.blit(self.level[x][y].image, (self.level[x][y].xpos, self.level[x][y].ypos))
        self.last_frame_render = rmap
        if not Settings.debug_mode:
            rmap.fill((0, 0, 0))
        return rmap

    @staticmethod
    def get_coor(i):  # Служебная функция для конверсии индекса клетки в координаты X, Y
        y = i // 10
        x = i - y * 10 - 1
        return x, y

    @staticmethod
    def get_index(x, y):  # Служебная функция для конверсии координаты клетки X, Y в её индекс
        index = x * 10 + y + 1
        return index


class Stats:  # Этот класс отвечает за отображение и хранение всех статов.
    def __init__(self):
        self.carma = carma
        self.charge = charge  # Зарядка фонарика - сдох фонарик, двигаемся на ощупь...
        # TODO Само наличие фонарика... подтягиваем из...
        self.health = healthpoints

        self.font = pygame.font.Font(None, 22)
        self.statscolor = (200, 200, 200)
        self.bg_color = (30, 30, 30)
        self.width = pygame.display.get_surface().get_size()[0] - tileSize * 10 - mapOffsetX * 3
        self.height = 100  # TODO - подогнать потом для красоты
        self.xpos = mapOffsetX * 2 + tileSize * 10
        self.ypos = mapOffsetY
        self.last_frame_render = pygame.Surface((self.width, self.height))

        self.carmatext = u"Карма: "
        self.chargetext = u"Фонарик: "
        self.healthtext = u"Здоровье: "

    def update(self):
        # TODO - Возможно стоит все статы сделать в одну строчку вверху экрана.
        # "Я подумаю над этим завтра(с)", когда будут готовы все остальные элементы интерфейса.
        pass

    def render(self):
        self.update()
        # TODO - Переделать всю нижеприведённую срань на стройный рендер через render_text() и текстовый массив
        rcarma = self.font.render(self.carmatext + str(self.carma), 1, self.statscolor, self.bg_color)
        rcharge = self.font.render(self.chargetext + str(self.charge), 1, self.statscolor, self.bg_color)
        rhealth = self.font.render(self.healthtext + str(self.health), 1, self.statscolor, self.bg_color)

        rstats = pygame.Surface((self.width, self.height))
        pygame.Surface.convert(rstats)
        rstats.fill(self.bg_color)
        rstats.blit(rhealth, (0, 0))
        rstats.blit(rcharge, (0, rhealth.get_rect().height))
        rstats.blit(rcarma, (0, rhealth.get_rect().height + rcharge.get_rect().height))
        self.last_frame_render = rstats
        return rstats


class Textline:  # Класс нужен для удобного вывода на экран текстовых массивов.
    def __init__(self):
        self.text = ""
        self.color = (100, 100, 100)
        self.bgcolor = (30, 30, 30)
        self.size = 22
        self.AA = 1  # Anti-aliasing включён по умолчанию
        self.face = None  # Шрифт, вдруг кого-то торкнет разные фразы, разными шрифтами писАть.


class Description:  # Этот класс отвечает за отображение и текстового описания текущей обстановки
    def __init__(self):
        self.width = pygame.display.get_surface().get_size()[0] - mapOffsetX * 2
        self.height = pygame.display.get_surface().get_size()[1] - mapOffsetY * 3 - tileSize * 10
        self.bg_color = (30, 30, 30)
        self.xpos = mapOffsetX
        self.ypos = mapOffsetY * 2 + tileSize * 10
        self.line = [Textline() for _ in range(10)]  # Гы-гы, чудный символ "_", питон... такой питон.
        self.last_frame_render = pygame.Surface((self.width, self.height))

    def build(self, party_instance, map_instance, stat_instance):
        # Это по сути самая главная функция класса. Вызывается один раз за ход... но при желании можно и чаще...
        # У нас 10 фиксированных строчек. Никакого автопереноса по словам :-(
        # Так что есть смысл
        self.line[0].text = u"Текущее описание обстановки (это плейсхолдеры >> всё будет переписано)"
        self.line[1].text = u"Под ногами: " + map_instance.level[party_instance.x][party_instance.y].descr
        self.line[2].text = u"Впереди: " + map_instance.level[party_instance.x][party_instance.y - 1].descr
        self.line[3].text = u"Сзади: " + map_instance.level[party_instance.x][party_instance.y + 1].descr
        self.line[4].text = u"Справа: " + map_instance.level[party_instance.x + 1][party_instance.y].descr
        self.line[5].text = u"Слева: " + map_instance.level[party_instance.x - 1][party_instance.y].descr
        self.line[8].text = u"Временное управление игрой - стрелочками. ESC - выход."
        if Settings.debug_mode:
            self.line[9].text = u"Debug-mode-on: Карта видна. 1 - 'Вкл/выкл'"
            self.line[9].color = (250, 0, 0)
        else:
            self.line[9].text = u"Debug-mode-off. 1 - 'Вкл/выкл'"
            self.line[9].color = (0, 0, 0)

    def update(self):
        pass

    def render(self):
        self.update()
        rdescription = pygame.Surface((self.width, self.height))
        pygame.Surface.convert(rdescription)
        rdescription.fill(self.bg_color)
        rendered_text = render_text(self.line, self.width, self.height, self.bg_color)
        rdescription.blit(rendered_text, (0, 0))
        self.last_frame_render = rdescription
        return rdescription


class Action:   # Класс для описания всех возможных действий, которые может предпринять Сёма
                # На каждое действие должен приходится один инстанс этого класса
    def __init__(self, action_name, action_type):
        self.enabled = False
        self.caption = action_name
        self.type = action_type
        self.color = (100, 255, 100)
        self.bg_color = (60, 60, 60)
        self.face = None
        self.size = 22
        self.AA = 1
        pass

    def arm(self):
        # Эта функция в каждом конкретном инстансе класса будет проверять соответствие внешних условий для
        # "активации" соответствующей игровой опций. Если все условия соблюдены -> "снимаем предохранитель"
        pass

    def fire(self):
        # Эта функция непосредственно совершает действие - меняя статы / координаты и т.п.
        # Функция будет вызываться в момент клика по соответствующей кнопке
        # Для доступа к данным / методам других классов при вызове функции передаём референс на них
        # Пока это просто заглушка. Функция будет переопределена в момент создания инстанса, конкретного действия
        # ибо для каждого Action-инстанса эффект строго индивидуален.
        pass

    def render(self):
        # Эта функция рендерит тупо одну кнопку с возможным вариантом действия,
        font = pygame.font.Font(self.face, self.size)
        text_surface = font.render(self.caption, self.AA, self.color, self.bg_color)

        # TODO А также добавляет в словарь вида {Индекс кнопки : Индекс Action} новую запись
        return text_surface


class Options:  # Этот класс отвечает за генерацию и отображение доступных игровых опций
    def __init__(self, map_obj, party_obj, stats_obj, desc_obj):
        self.width = pygame.display.get_surface().get_size()[0] - tileSize*10 - mapOffsetX * 3
        self.height = pygame.display.get_surface().get_size()[1] - stats_obj.last_frame_render.get_size()[1] -\
            desc_obj.last_frame_render.get_size()[1] - mapOffsetY * 4
        self.bg_color = (30, 30, 30)
        self.xpos = tileSize * 10 + mapOffsetX * 2
        self.ypos = stats_obj.last_frame_render.get_size()[1] + mapOffsetX * 2
        self.action = []
        self.last_frame_render = pygame.Surface((self.width, self.height))

        # -------------НИЖЕ ИДЁТ СОЗДАНИЕ ИГРОВЫХ ОПЦИЙ Всё в рамках Options.__init__()-----------------
        # к каждому инстансу action динамически присабачивается две функции arm() и fire()
        # их описание и назначение смотри в самом классе Action

        # Ход на клетку вверх
        move_up = Action(u"Идём вверх", "move")

        def move_up_inst_func(self):
            party_obj.move("up")
            stats_obj.charge -= 1
            stats_obj.carma -= 1

        def check_move_up_inst_func(self):
            if party_obj.y >= 1:
                if map_obj.level[party_obj.x][party_obj.y - 1].type != 0:
                    move_up.enabled = True

        move_up.fire = types.MethodType(move_up_inst_func, move_up)
        move_up.arm = types.MethodType(check_move_up_inst_func, move_up)
        self.action.append(move_up)

        # Ход на клетку вниз
        move_down = Action(u"Идём вниз", "move")

        def move_down_inst_func(self):
            party_obj.move("down")
            stats_obj.charge -= 1
            stats_obj.carma -= 1

        def check_move_down_inst_func(self):
            if party_obj.y <= 8:
                if map_obj.level[party_obj.x][party_obj.y + 1].type != 0:
                    move_down.enabled = True

        move_down.fire = types.MethodType(move_down_inst_func, move_down)
        move_down.arm = types.MethodType(check_move_down_inst_func, move_down)
        self.action.append(move_down)

        # Ход на клетку вправо
        move_right = Action(u"Идём вправо", "move")

        def move_right_inst_func(self):
            party_obj.move("right")
            stats_obj.charge -= 1
            stats_obj.carma -= 1

        def check_move_right_inst_func(self):
            if party_obj.x <= 8:
                if map_obj.level[party_obj.x + 1][party_obj.y].type != 0:
                    move_right.enabled = True

        move_right.fire = types.MethodType(move_right_inst_func, move_right)
        move_right.arm = types.MethodType(check_move_right_inst_func, move_right)
        self.action.append(move_right)

        # Ход на клетку влево
        move_left = Action(u"Идём влево", "move")

        def move_left_inst_func(self):
            party_obj.move("left")
            stats_obj.charge -= 1
            stats_obj.carma -= 1

        def check_move_left_inst_func(self):
            if party_obj.x >= 1:
                if map_obj.level[party_obj.x - 1][party_obj.y].type != 0:
                    move_left.enabled = True

        move_left.fire = types.MethodType(move_left_inst_func, move_left)
        move_left.arm = types.MethodType(check_move_left_inst_func, move_left)
        self.action.append(move_left)

    # --------------------- КОНЕЦ ИНИЦИАЛИЗАЦИИ ИГРОВЫХ ОПЦИЙ -----------------------------------------------

    def disable_all(self):  # В начале каждого хода сбрасываем флаг активности на всех опциях
        for ind in range(len(self.action)):
            self.action[ind].enabled = False

    def arm(self):
        self.disable_all()
        for ind in range(len(self.action)):
            self.action[ind].arm()

    def update(self):
        pass

    def render(self):
        # Формируем (перезаписываем) Surface под кнопки - размер поверхности всегда определяется интерфейсом
        roptions = pygame.Surface((self.width, self.height))
        pygame.Surface.convert(roptions)
        roptions.fill(self.bg_color)
        # Шурстим весь массив, состоящий из Actions-инстансов и для тех, которые помечены Enabled, делаем Render
        y_but_pos = 0
        y_but_offset = 1  # Оставляем чуть-чуть места между кнопками.
        for ind in range(len(self.action)):
            if self.action[ind].enabled:
                ar = self.action[ind].render()
                # Отрендеренную кнопку добавляем на Surface ниже уже отрендеренных кнопок
                roptions.blit(ar, (0, y_but_pos))
                y_but_pos += ar.get_size()[1] + y_but_offset

        # TODO Для контроля за нажатием мыши по соответствующей опции и VFX формируем словарь {Квадрат : индекс кнопки}

        # После завершения цикла - Возвращаем Surface c кнопками из функции
        self.last_frame_render = roptions
        return roptions


class Talks:  # TODO - Здесь было бы здорово управлять реплками / диалогами персонажей но это когда-нибудь потом...
    def __init__(self):
        pass

    def update(self):
        pass

    def render(self):
        pass


# ДЕФАЙНИМ КАСТОМНЫЕ СЛУЖЕБНЫЕ ФУНКЦИИ - они нам пригодятся...

# ФУНКЦИИ ЗАГРУЗКИ АСЕТОВ
# Если что-то пойдёт не так во время подгрузки ассетов, то мы узнаем об этом первыми
# Ну и в случае с пикчами, можно сразу указать код прозрачности спрайтов


def load_image(name, colorkey=None):
    fullname = os.path.join('sprites', name)
    try:
        image = pygame.image.load(fullname)  # Странно IDE в этом месте материться, но всё работает как надо.
        # Он почему-то не может залезть внутрь класса Image... ну... не было печали...

    except pygame.error as message:
        print(u'Не грузится пикча:', name)
        raise SystemExit(message)
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:  # Если кодом прозрачности стоит -1, цвет верхнего-левого пикселя считать прозрачным.
            colorkey = image.get_at((0, 0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image


def load_sound(name):
    class NoneSound:
        def __init__(self):
            pass

        def play(self): pass  # "Заглушка" для симуляция тишины ;-)
    if not pygame.mixer:      # на случай если саундсистема не инициализировалась.
        return NoneSound()
    fullname = os.path.join('sounds', name)
    try:
        sound = pygame.mixer.Sound(fullname)
    except pygame.error as message:
        print(u'Не грузится саунд:', name)
        raise SystemExit(message)
    return sound


# ФУНКЦИЯ ПОСТРОЧНОГО РЕНДЕРА ЗАРАНЕЕ ПОДГОТОВЛЕННЫХ (ПОСТРОЕННЫХ) ТЕКСТОВЫХ МАССИВОВ


def render_text(text_array, width, height, bgcolor):
    rendered_text = pygame.Surface((width, height))
    pygame.Surface.convert(rendered_text)
    rendered_text.fill(bgcolor)
    xpos = 10
    ypos = 10
    for i in range(len(text_array)):
        font = pygame.font.Font(text_array[i].face, text_array[i].size)
        text_surface = font.render(text_array[i].text, text_array[i].AA, text_array[i].color, text_array[i].bgcolor)
        rendered_text.blit(text_surface, (xpos, ypos))
        ypos += text_surface.get_rect().height
    return rendered_text

# ГЛАВНАЯ ФУНКЦИЯ: В начале было слово... main()


def main():
    # ИНИЦИАЛИЗИРУЕМ "СЦЕНУ", не знаю как это называется в питоне, во всех нормальных движках это называется сцена
    pygame.init()  # И да начнётся драма...
    sceene = pygame.display.set_mode((Settings.scr_width, Settings.scr_height))  # И да будет сцена...
    # TODO Хрен его знает, как сделать размер динамичным/адаптивным... надо погуглить
    pygame.display.set_caption('7DL-Dungeon-Crawler')  # И да будет ей имя...
    pygame.mouse.set_visible(1)  # И да будет курсор мыши как святой дух носиться над ней...

    # ИНИЦИАЛИЗИРУЕМ ЗАДНИК НА КОТОРОМ БУДЕМ ПРИЧИНЯТЬ ДОБРО И НАНОСИТЬ НЕПОПРАВИМЫЙ УЮТ
    background = pygame.Surface(sceene.get_size())
    pygame.Surface.convert(background)
    background.fill((0, 0, 0))  # И да будет мгла кромешная покрывать всё видимое и невидимое и лежать под ними...

    # ИНИЦИАЛИЗИРУЕМ ИГРОВЫЕ ЭЛЕМЕНТЫ и UI
    dungeon = Map()                     # Инициализируем карту
    party = Party(dungeon.entrance)     # Инициализируем (Cпавним) команду Чип и Дейлов на входе
    stats = Stats()                     # Инициализируем область статов и вводим входящие данные
    desc = Description()                # Инициализируем область с описанием обстановки
    options = Options(dungeon, party, stats, desc)      # Инициализируем область с игровыми опциями ходов Сёмы
    # ВАЖНО! В класс Options, передаются ссылки на инстансы всех основных внутриигровых классов,
    # иначе инстанс options не получит над ними контроль

    # ИНИЦИАЛИЗИРУЕМ БЕСКОНЕЧНЫЙ ЦИКЛ ХОДА ИГРОКА
    while 1:        # TODO - Тут (вместо 1) по хорошему должно быть win/lose condition
        # АПДЕЙТ ВСЕХ ОБЪЕКТОВ И СТАТОВ

        # ФОРМИРУЕМ ТЕКСТОВОЕ ОПИСАНИЕ НА ОСНОВЕ ИНФЫ О КОМАНДЕ, ОБСТАНОВКЕ И СТАТОВ
        desc.build(party, dungeon, stats)
        # ОЦЕНИВАЕМ ОБСТАНОВКУ И ФОРМИРУЕМ ВАРИАНТЫ ДЕЙСТВИЙ ПО ОБСТАНОВКЕ
        options.arm()

        # РЕНДЕРИМ
        background.blit(dungeon.render(), (0, 0))                       # Рендерим карту
        background.blit(party.render(), (party.xpos, party.ypos))   # Рендерим поверх карты Сёму и Ко
        # Рендерим иные объекты на карте
        background.blit(stats.render(), (stats.xpos, stats.ypos))  # Рендерим статы и инвентарь
        background.blit(desc.render(), (desc.xpos, desc.ypos))  # Рендерим текстовую область c описанием обстановки
        background.blit(options.render(), (options.xpos, options.ypos))  # Рендерим доступные варианты действий

        # КОНЕЧНОЕ ОБНОВЛЕНИЕ ЭКРАНА
        sceene.blit(background, (0, 0))
        pygame.display.flip()

        # ЗАПУСКАЕМ БЕСКОНЕЧНЫЙ ЦИКЛ ОЖИДАНИЯ ПОЛЬЗОВАТЕЛЬСКОГО ВВОДА / ВИЗУАЛЬНЫХ ЭФФЕКТОВ
        # К этому моменту вся логика, события эевенты должны быть отработаны, эффекты сиграны, сцена отрисована
        while 1:
            # Господи... ну кто придумал в процеурном скриптовом языке в 21 веке игры писать...
            decision_flag = False


            # TODO - В этом же бесконечном цикле сделать отслеживание VFX:MOUSE:hover эффекта у кнопок действий.
            for event in pygame.event.get():
                if event.type == QUIT:
                    return
                elif event.type == KEYDOWN and event.key == K_ESCAPE:
                    return
                elif event.type == KEYDOWN and event.key == K_1:
                    Settings.debug_mode ^= True
                    decision_flag = True
                # TODO - убрать нахрен клавиатурное управление (или перемесить его в дебаг-мод)
                # Вместо этого запилить событийное управление по клику мышки
                elif event.type == KEYDOWN and event.key == K_UP and options.action[0].enabled:
                    options.action[0].fire()
                    decision_flag = True
                elif event.type == KEYDOWN and event.key == K_DOWN and options.action[1].enabled:
                    options.action[1].fire()
                    decision_flag = True
                elif event.type == KEYDOWN and event.key == K_RIGHT and options.action[2].enabled:
                    options.action[2].fire()
                    decision_flag = True
                elif event.type == KEYDOWN and event.key == K_LEFT and options.action[3].enabled:
                    options.action[3].fire()
                    decision_flag = True

            if decision_flag:  # Если игрок раздуплился и принял решение, прерываем цикл -> и "Делаем ход конём"
                break


# Если до сюда Питон доканал, и не словили эксепшн / трейсбэк / ран-тайм эрор, то, Сёма, держись!
if __name__ == '__main__':  # Запускаем главный цикл
    main()  # Добро пожаловать в адЪ!
Как на это посмотреть (для тех, у кого стоит питон):

1). Копируем выше представленный быдлокод в пустой текстовый файл, называем его скажем game.py, сохраняем.
2). В консоли пишем: “python game.py”  и жмём ввод
Оговорка). Если вдруг у Вас нет библиотеки pygame, перед п.2 пишем в консоли pip install pygame и ввод. Питон сам всё загрузит и установит.

Как на это посмотреть (для тех, у кого нет питона):

Пока никак. Скомпилировать сей код в *.exe для тех, у кого питон не стоит у меня не получилось (не хватает у меня библиотек 2008 года выпуска… а лазить по задворкам интернета в поисках старых библиотека как-то нет времени/желания). Возможно, что кто-то из вас, кто уже через это проходил и мне с этим поможет.

Теперь о проблемах технического плана:

Проблема 1. Скрещивание ежа и ужа (Ренпай и кода на питоне выше)
Это чистый питон версии 2.7.10, если я правильно понял, именно эта версия идёт с БЛ.
Из сторонних (не стандартных питоновских) библиотек у меня используется только pygame для питона 2.7. И тут есть проблема… в комплекте с БЛ идёт pygame_SDL2. Сторонняя библиотека, которая по идее в точности повторяет API pygame, но ей понятно не является... Поставить себе pygame_SDL2 у меня не получилось – опять же нет библиотек от VS 2008 и т.п. – возможно я быстро сдался – но тем не менее…

Вопрос 1: кто-нибудь из присутствующих уже что-нибудь с ренпай и БЛ самопальное Питоновское скрещивал (альт_сценарий написаный на «ренпай скрипте» не считается)? Возможно кто-то знает, что за зверь renpygame – подозреваю, что это именно то, что мне нужно? Ваша помощь поможет мне избежать долгих чтений мануалов, топтания по граблям и набиванием шишек. Отпишите, плиз, в личку - пообщаемся.

Вопрос 2: Можем ли мы? / есть ли в этом необходимость? поставить вместе с модом 7ДЛ свои библиотеки (тот же pygame). Или мы ограничены только теми техническими средствами (модулями и библиотеками), что уже идут в комплекте с БЛ. Ибо соблазн велик, но череват конфликтами версий и прочими неприятностями…

DISCLAMER О проделанной работе:

Важное замечание – Код представленный выше - это MVP (Minimum viable product, минимально жизнеспособный продукт). Т.е. по степени завершения, это даже не прототип и не пре-альфа… Поэтому прошу не утруждать себя писать комменты типа «графон отстой…, ЩИТО это..., и т.п» Степень готовности 5%... со всеми вытекающими. И выкладываю я это для того чтобы:

1). Понять в первую очередь для себя в том ли направлении копаю.
2). Конкретизировать СКОУП – ограничить/расширить функционал: фичи, геймплей, геймдизайн пожелания по UI и т.д. и т.п.
3). Получить конструктивную критику/диалог.

Итак, что мы имеем:
1). 2D вид сверху, рогалико-подобный dungeon crawler. Nuff said…
2). Экран (пока это фиксированные 800х600) разделён на области:
2.1). Карта – 10х10 тайлов (клетки по периметру по сути служебные, так что реальное игровое поле 8х8) в конечной версии будет видно только клетки в зоне освещения фонарика (клетка впереди и по пол клетки с боков). Текстуры (тайл-сет) для карты пока не завезли, но он едет… издалека… очень издалека… И да… ничего не мешает сделать поле 20х20 или 100х100…

Текущая версия «движка» (если быдлокод выше можно назвать движком) поддерживает неограниченное кол-во «предопределённых» карт… так что стенки/проходы/игровые объекты можно расставлять как хочется и для разных подруг Семёна карта может быть разной, с советующими «сюжетными поворотами». Думал про рандомно «процедурно генерируемую» карту… но мне кажется это как-то не «по сценарию»… так что, если к концу проекта война с Питоном и софтом 10-и летней давности не заколебёт, то можно будет сделать.

Ах да, карта поддерживает динамические изменения – ну там обвал (аля новая стена), неожиданное затопление (непроходимый участок)… или взрыв /снос куска стены динамитом (который можно случайно найти или раздобыть где-нибудь в лагере)… или долгая и упорная работа киркой/фонариком/голыми руками в забое… Изменения могут быть как рандомными, так и по заранее прописанным триггерам/скриптам. Самих «динамических изменений» (сценарных событий) пока в коде нет – но с использованием текущих классов и их методов – их скоро завезут. Им намного ближе ехать чем текстурам.

Нажатие на 1 включает/выключает дебаг мод, а вместе с ним и карту.

2.2). Статистика или статы – ну тут всё просто… отображается стат информация о происходящем и планируется инвентарь… Класс статов будет переписан, точнее расширен, физической моделью Сёмы и его подруги… ну типа Голова, руки, ноги… и соответствующие предметы в/на них: ну типа побежал в темноте -> споткнулся -> повредил руку -> не могу нести фонарик/предмет… повредил ногу -> не могу бегать… сильно повредил -> дальше только ползком (и то - при наличии целых рук)…

Карма – хочу сей бесполезный стат использовать как удачу. Если игрок за первые 4-5 дней делал добрые дела в подземку он войдёт с хорошей кармой и удача будет на его стороне: поиск Шурика /ответов / приключений на отверстия будет не сложнее похода в магазин за хлебом. Но если карма будет низкая, то всё будет против Сёмы (спотыкания на ровном месте, галюны и глюки, агра снарков и т.п.) и ждёт его в конце кара анальная.

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

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

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

2.4) Окно с опциями. Это окно справа предназначено для отображения доступных в настоящий момент игроку игровых опций. Пока их 4 (идти вверх, вниз, вправо, влево...) но наплодить их можно тысячи. Каждая игровая опция «сама» определяет на основании информации об окружающих объектах может ли она быть сыграна в настоящий момент. Так, например, опция «бежать от снарка» сама включится и станет доступной игроку если в соседней клеточке есть снарк. Eсли в текущей клеточке есть выключатель, то появляется опция «вкл/выкл»… Если в партии Мику и в инвентаре динамит – то появляется опция «бахнуть стену без «последствий»» (Ибо папа Мику - инженер).

2.5) Объекты. Пока объект только один – партия (Сёма и его подргуа, или один Сёма). Но объектов может быть много, и они могут быть двух видов: динамичные (туман, снарк, или кого вы там хотите…) и статичные (кирка, батарейка к фанарику). Принципиальное отличие первых от вторых – это способность самостоятельно передвигаться по карте. Про объекты расписывать пока ничего не буду – это WIP.

3). Управление. Пока только клавиатурой (стрелочки). Конпка 1 – вкл/выкл дебаг-режим. ESC – выход. Планирую полностью отказаться от клавиатурного управления и завезти клик мышкой по игровой опции (их будет много, клавиш на клаве не хватит, ну и на тач скрин не портируешь). На клаве думаю оставить только ESC и пробел (читать дальше)… опять же – это вопрос для обсуждения.

4). Звуки/музон. Будут, но едут оттуда же откуда и текстуры…

5). Анимация…VFX… Цитата, от разраба Dwarf Fortress “ The interface is coming — it’s not coming in your lifetime but it’s coming.”

6). Вне игровые опции: Save/Load. Динамический ресайз экрана. Контраст / гамма. И прочие свистелки и перделки… пока нету это всего и не планируется. Ну может быть… когда-нибудь…

7). Когда же всё это будет? Ну как там у нас принято: «Ждать осталось недолго (с)»

Короче, господа, жду ваших предложений, замечаний, конструктивной критики.
Заранее прошу прощения за опечатки и орфографические ошибки – я не силён в русском языке.

205

Выкладываю хотфикс по ачивлисту: Ссылка.

Чейнджлог:
1. Фикс перехода на концовку "что-то правильное";
2. Дополнительный запуск всех переменных для прочтения концовок.

206

Dantiras написал(а):

Выкладываю хотфикс по ачивлисту: Ссылка.

Чейнджлог:
1. Фикс перехода на концовку "что-то правильное";
2. Дополнительный запуск всех переменных для прочтения концовок.

Подпись автора

    Слышу голос, голос спрашивает строго: "А сегодня что для завтра сделал я?".

Памёрла панночка!

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/scenario_alt/Config/sdl_achv_list_main.rpy", line 27, in script call
  File "game/scenario_alt/Config/sdl_achv_list_main.rpy", line 27, in script call
ScriptError: could not find label 'alt_day0_vars'.

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\bootstrap.py", line 265, in bootstrap
    renpy.main.main()
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\main.py", line 327, in main
    run(restart)
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\main.py", line 78, in run
    renpy.execution.run_context(True)
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\execution.py", line 509, in run_context
    context.run()
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\execution.py", line 288, in run
    node.execute()
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\ast.py", line 1157, in execute
    rv = renpy.game.context().call(label, return_site=self.next.name)
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\execution.py", line 365, in call
    return renpy.game.script.lookup(label)
  File "C:\Users\Ivan\Documents\Everlasting Summer\renpy\script.py", line 547, in lookup
    raise ScriptError("could not find label '%s'." % str(label))
ScriptError: could not find label 'alt_day0_vars'.

Windows-7-6.1.7601-SP1
Ren'Py 6.16.3.502
Everlasting Summer 1.0

207

Melirius написал(а):

Памёрла панночка!

Пшепрашам, пан Мелириус, маче остатну версу модификацйи?
Бо тен label надавален был в версе 0.31d и розмешчем тераз в файле conf_vars_cmm.rpy.

У меня из-за наличия этого участка кода никаких проблем не было. Проверьте собственную версию мода.

Отредактировано Dantiras (2017-02-20 19:35:36)

208

₽ на ЯД

209

Всё пришло, спасибо!

210

Dantiras написал(а):

Пшепрашам, пан Мелириус, маче остатну версу модификацйи?
Бо тен label надавален был в версе 0.31d и розмешчем тераз в файле conf_vars_cmm.rpy.

У меня из-за наличия этого участка кода никаких проблем не было. Проверьте собственную версию мода.


Я всё ещё 0.31с терзаю, чтобы номера строк, в кои я исправления предлагаю, не поплыли. Значит, останусь на предыдущем ачив-листе, пока не добью Лену и Алису.


Вы здесь » 7 дней лета » Общее обсуждение мода » СПИСОК КОНТЕНТА