#1
Привет. Помогите, плиз, гуманитарию - в программировании почти не разбираюсь, и при создании новеллы столкнулся с трудностями. Суть проблемы такая - нужно создать экран, как на приложенной картинке используя свойства drag and drop - т.е. чтобы объекты можно перетаскивать.
Описание экрана: 1) Есть несколько условных объектов (1,2, 3...), которые можно перетаскивать по экрану. 2) Есть две неподвижных зоны, зона №1 и зона №2, куда эти объекты можно сбрасывать, после чего объекты должны пропадать, вернув некоторые переменные (ну, допустим. если сбросить объект 1 в зону 1, то переменная answer станет равной 42) не прерывая работу с экраном 3) Зона №3 - информационная - там выводятся сообщения о всех манипуляциях с объектами (допустим "объект 1 сброшен в зону №1") Также там должны выводиться сообщения, если просто кликнуть по объекту, но никуда его не тащить (пример "это объект 5 - переместите его в зону 1 или зону 2") 4) В правом нижнем углу отображается значение переменной, которая увеличивается или уменьшается в зависимости от того, какой объект куда сброшен. Условно говоря - это мана, она расходуется на операции с объектами, но может и возрастать, если нужный объект попадет в нужную зону. 5) в левом нижнем углу - кнопка возврата/выхода.
Собственно, в мануале по renpy есть код, позволяющий реализовать нечто подобное (пример с детективами):
Код init python:
def detective_dragged(drags, drop):
if not drop: return
store.detective = drags[0].drag_name store.city = drop.drag_name
return True
screen send_detective_screen:
# A map as background. add "europe.jpg"
# A drag group ensures that the detectives and the cities can be # dragged to each other. draggroup:
# Our detectives. drag: drag_name "Ivy" child "ivy.png" droppable False dragged detective_dragged xpos 10 ypos 10 if game: drag: drag_name "Zack" child "zack.png" droppable False dragged detective_dragged xpos 10 ypos 300
# The cities they can go to. drag: drag_name "London" child "london.png" draggable False xpos 450 ypos 100 if game: drag: drag_name "Paris" draggable False child "paris.png" xpos 450 ypos 300
Этот код худо бедно позволяет мне создать зоны №1 и №2 плюс перемещаемые drag-объекты, но с остальным полный провал. Когда читаю мануалы на английском, просто башка трещать начинает от всех этих функций. Подскажите хотя бы примерно как должен выглядеть код, реализующий все пять пунктов. Если лень писать весь код (я Вас понимаю...) подскажите хотя бы как сделать зону №3 и как сделать, чтобы переменным присваивались разные значения в зависимости от того, какой объект куда сброшен. Помогите, плиз.
|
#2
1. Первое, что нужно - это экран, который, во избежание ненужных кликов вне его, будем вызывать командой call. В этот экран мы запихнем все нужные зоны и кнопки.
Объекты - это draggable drag-объекты. Их можно таскать и бросать, но нельзя бросать на них. Неподвижные зоны 1 и 2 - это droppable drag-объекты. На них можно бросать, но их нельзя таскать. За это отвечают свойства draggable и droppable, которые мы установим в False для соответствующих зон.
2. Инфо-зона (№3) будет фреймом с текстом внутри. Нам от нее требуемтся только чтобы она выводила на экран содержимое переменной. Назовем эту переменную current_message, и зададим ей дефолтное значение оператором default.
3. Функции. Для объектов нам нужно два вида функций: срабатывание по клику и срабатывание по перетаскиванию и сбросу. Первая функция устанавливается в свойстве clicked drag-объекта. Вторая - в свойстве dropped.
От функции по клику нам пока требуется исключительно смена сообщения. Т.е. изменение значения переменной current_message в зависимости от кликнутого объекта. Т.е. внутри функции должно быть что-то вроде:
если кликнутый объект == объекту 1: запихнуть в переменную current_message такой-то текст иначе если кликнутый объект == объекту 2: запихнуть в переменную current_message сякой-то текст
И так далее. Current_message нам доступна внутри функции (надо только объявить, что мы обращаемся именно к ней, с помощью оператора global). А что насчет "кликнутый объект"? А текущий кликнутый объект мы, по идее, должны были бы передать в виде параметра в функцию-обработчик клика, но! В свойство clicked мы должны положить такую функцию, которая не принимает параметров (так уж оно устроено). Так как сказать функции о том, на какой именно объект клацнули? Тут два способа. Один - с помощью curried-функций, это долго объяснять, можете сами почитать вот тут: https://lemmasoft.renai.us/forums/viewtopic.php?p=319388#p319388 (это тема!). Второй чуть проще для понимания: мы заводим глобальную переменнию currently_clicked, в которую будем класть идентификатор текущего объекта.
Итак, код (пока в ошметках, потом в конце будет целиком код проекта): для curried-функции:
Код def object_clicked(objId): global current_message
if objId == 1: current_message = "Вы кликнули на объект %s" % objId if objId == 2: current_message = "Вы жмякнули на объект %s" % objId return None
curriedObjClicked = renpy.curry(object_clicked)
drag: drag_name "Айви" droppable False clicked curriedObjClicked(1)
Для комбо с SetVariable:
Код def object_clicked(): global current_message, objId
if objId == 1: current_message = "Вы кликнули на объект %s" % objId if objId == 2: current_message = "Вы жмякнули на объект %s" % objId return None
drag: drag_name "Зак" droppable False clicked [ SetVariable("objId", 2), object_clicked ] Во втором случае список функций/экшенов в свойстве clicked берется в квадратные скобки, а функция object_clicked там же вызывается без круглых скобок (это важно).
4. С кликом разобрались. Что с перетаскиванием и сбросом? Тут все проще, потому что функция внутри свойства dragged получает два параметра: объект, который бросили, и объект, в который бросили. То есть просто пишем функцию (код ниже).
Комментарии по коду: drags[0].drag_name переводится как "возьми значение атрибута drag_name первого объекта в списке перетаскиваемых объектов" (он у нас единственный, мы таскаем объекты по одному). drags - это массив объектов, drags[0] берет из него первый элемент (нумерация списков/массивов идет с нуля) drop.drag_name перевдится как "возьми значение атрибута drag_name объекта, на который уронили тягаемый объект". поскольку наша дроп-зона по сути своей - тоже draggable-объект, только с иными свойствами, его имя хранится в том же атрибуте.
Внутри if'ов можно задавать значения переменным по своему усмотрению и в зависимости от нужд: вычитать очки из общего числа очков маны, менять сообщения и менять значения других переменных, которые будут управлять отображением объектов на экране. Обратите внимание на условие вывода на экран объекта "Камень".
5. Кнопка возврата/выхода будет прятать наш экран экшеном Return.
Код тестового проекта:
Код default current_message = "" default mana_points = 42 default stones_left = 3
init python: def object_dragged(drags, drop): global current_message, mana_points, stones_left
if not drop: return
if drags[0].drag_name == "Атака" and drop.drag_name == "Враг": mana_points -= 10 current_message = "Отличным ударом вы прожгли во враге дыру!"
if drags[0].drag_name == "Атака" and drop.drag_name == "Герой": mana_points -= 10 current_message = "Какое нелепое самоубийство!" # return True # этой командой мы можем закрыть окно и прыгнуть на метку конца игры, например!
if drags[0].drag_name == "Камень": current_message = "Герой бросается камнями." stones_left -= 1
if drags[0].drag_name == "Шутка": current_message = "Ого! Какой смешной, оказывается, %s!" % drop.drag_name.lower()
renpy.restart_interaction() return None
def object_clicked(objId): global current_message
if objId == 1: current_message = "Вы кликнули на объект %s" % objId
else: current_message = "Вы жмякнули на объект %s" % objId
renpy.restart_interaction() return None
curriedObjClicked = renpy.curry(object_clicked)
screen objects_screen: draggroup: xysize(1.0, 1.0)
# Объект drag: drag_name "Атака" droppable False clicked curriedObjClicked(1) dragged object_dragged xalign .5 yalign .4
label "Файербол" background "#000"
# Объект if stones_left > 0: drag: drag_name "Камень" droppable False clicked curriedObjClicked(3) dragged object_dragged xalign .5 yalign .5
label "Камень" background "#000"
# Объект drag: drag_name "Шутка" droppable False clicked curriedObjClicked(2) dragged object_dragged xalign .5 yalign .3
label "Шутеечка за триста" background "#000"
# Зона слева drag: drag_name "Враг" draggable False
frame: xysize(.3, .7) background "#000" text "Кинуть во врага"
# Зона справа drag: drag_name "Герой" draggable False xalign 1.0 frame: xysize(.3, .7) background "#000" text "Наложить на себя"
# Третья зона, контейнер для сообщений frame: xysize(.7, .3) xalign .5 yalign 1.0 background "#000"
text current_message xalign .5
# кнопка выхода textbutton "Выход" action Return xalign .1 yalign .9
# Индикаторы vbox: xalign .9 yalign .9 label "Очки маны: %s" % mana_points label "Камней в карманах: %s" % stones_left
label start: call screen objects_screen
"Конец!"
|
#4
Помогите пожалуйста куда вставить этот кусочек кода screen main_menu: imagemap: ground "mmo.png" hover "mmh.png" alpha True
hotspot (165, 206, 360, 85) action Start() hotspot (762, 219, 360, 77) action ShowMenu("load") hotspot (157, 314, 395, 94) action ShowMenu("preferences") hotspot (156, 428, 346, 86) action Help() hotspot (914, 517, 253, 97) action Quit(confirm=False) а то не пойму. мой вк https://vk.com/sergey0804 Заранее спасибо)
Разработчик.
|
#5
Закомментированные строки можно просто удалитьКод ## Экран главного меню ######################################################### ## ## Используется, чтобы показать главное меню после запуска игры. ## ## https://www.renpy.org/doc/html/screen_special.html#main-menu screen main_menu(): ## Этот тег гарантирует, что любой другой экран с тем же тегом будет ## заменять этот. tag menu style_prefix "main_menu" imagemap: ground "mmo.png" hover "mmh.png" alpha True hotspot (165, 206, 360, 85) action Start() hotspot (762, 219, 360, 77) action ShowMenu("load") hotspot (157, 314, 395, 94) action ShowMenu("preferences") hotspot (156, 428, 346, 86) action Help() hotspot (914, 517, 253, 97) action Quit(confirm=False) # add gui.main_menu_background ## Эта пустая рамка затеняет главное меню. # frame: # pass ## Оператор use включает отображение другого экрана в данном. Актуальное ## содержание главного меню находится на экране навигации. # use navigation # if gui.show_name: # vbox: # text "[config.name!t]": # style "main_menu_title" # text "[config.version]": # style "main_menu_version"
Сообщение отредактировал dmit - Воскресенье, 11/Мар/2018, 00:54
планета FOREVER!!! Unkenbro team
|
#6
Цитата dmit ( ) Закомментированные строки можно просто удалить Код ## Экран главного меню ######################################################### ## ## Используется, чтобы показать главное меню после запуска игры. ## ## https://www.renpy.org/doc/html/screen_special.html#main-menu
screen main_menu():
## Этот тег гарантирует, что любой другой экран с тем же тегом будет ## заменять этот. tag menu
style_prefix "main_menu" imagemap: ground "mmo.png" hover "mmh.png" alpha True hotspot (165, 206, 360, 85) action Start() hotspot (762, 219, 360, 77) action ShowMenu("load") hotspot (157, 314, 395, 94) action ShowMenu("preferences") hotspot (156, 428, 346, 86) action Help() hotspot (914, 517, 253, 97) action Quit(confirm=False) # add gui.main_menu_background
## Эта пустая рамка затеняет главное меню. # frame: # pass
## Оператор use включает отображение другого экрана в данном. Актуальное ## содержание главного меню находится на экране навигации. # use navigation
# if gui.show_name:
# vbox: # text "[config.name!t]": # style "main_menu_title"
# text "[config.version]": # style "main_menu_version"
выбило такую ошибку Код [code] I'm sorry, but an uncaught exception occurred.
While loading <'Image' u'mmh.png'>: IOError: Couldn't find file 'mmh.png'.
-- Full Traceback ------------------------------------------------------------
Full traceback: File "renpy/common/_layout/screen_main_menu.rpym", line 28, in script python hide: File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\ast.py", line 848, in execute renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store) File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\python.py", line 1812, in py_exec_bytecode exec bytecode in globals, locals File "renpy/common/_layout/screen_main_menu.rpym", line 35, in <module> ui.interact() File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\ui.py", line 287, in interact rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs) File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\core.py", line 2624, in interact repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs) File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\core.py", line 3098, in interact_core self.draw_screen(root_widget, fullscreen_video, (not fullscreen_video) or video_frame_drawn) File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\core.py", line 2038, in draw_screen renpy.config.screen_height, File "render.pyx", line 485, in renpy.display.render.render_screen File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\layout.py", line 711, in render surf = render(child, width, height, cst, cat) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\layout.py", line 711, in render surf = render(child, width, height, cst, cat) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\layout.py", line 711, in render surf = render(child, width, height, cst, cat) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\screen.py", line 639, in render child = renpy.display.render.render(self.child, w, h, st, at) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\layout.py", line 711, in render surf = render(child, width, height, cst, cat) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\layout.py", line 711, in render surf = render(child, width, height, cst, cat) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\layout.py", line 711, in render surf = render(child, width, height, cst, cat) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\behavior.py", line 715, in render rv = super(Button, self).render(width, height, st, at) File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\layout.py", line 1138, in render back = render(style.background, bw, bh, st, at) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\imagemap.py", line 50, in render cr = render(self.child, width, height, st, at) File "render.pyx", line 145, in renpy.display.render.render File "render.pyx", line 233, in renpy.display.render.render File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\im.py", line 580, in render return cache.get(self, render=True) File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\im.py", line 266, in get surf = image.load() File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\display\im.py", line 625, in load surf = renpy.display.pgrender.load_image(renpy.loader.load(self.filename), self.filename) File "C:\Users\Людмила\Desktop\Проект\renpy-6.99.14.1-sdk\renpy\loader.py", line 555, in load raise IOError("Couldn't find file '%s'." % name) IOError: Couldn't find file 'mmh.png'.
Windows-8-6.2.9200 Ren'Py 6.99.14.1.3218 school 1.0 Sun Mar 11 11:50:50 2018
Разработчик.
|