Vicente Опубликовано 15 августа, 2011 Жалоба Опубликовано 15 августа, 2011 Подскажите как правится поле для текста? Например прозрачность или добавление рамки как здесь: http://s2.ipicture.ru/uploads/20110815/T0Lj72n1.jpg Цитата
Алекс__ Опубликовано 15 августа, 2011 Жалоба Опубликовано 15 августа, 2011 (изменено) http://lemmasoft.ren...3&hilit=textboxhttp://lemmasoft.ren...t=9812&p=127872Здесь превосходные руководства по настройке внешнего вида игры, они конечно на английском, но с примерами кода и картинками (все очень доступно и в большом количестве)...)) Изменено 15 августа, 2011 пользователем Алекс__ (смотреть историю редактирования) 1 Цитата
Vicente Опубликовано 17 августа, 2011 Жалоба Опубликовано 17 августа, 2011 Хочу сделать так, чтобы время на ввод кода ограничивалось. init: python: def countdown(st, at, length=0.0): remaining = length - st if remaining > 5.0: return Text("%.1f" % remaining, color="#fff", size=72), .1 elif remaining > 0.0: return Text("%.1f" % remaining, color="#f00", size=72), .1 else: return anim.Blink(Text("0.0", color="#f00", size=72)), None image countdown = DynamicDisplayable(countdown, length=20.0) label start: show countdown at Position(xalign=.1, yalign=.1) Меняю так:if remaining > 5.0: return Text("%.1f" % remaining, color="#fff", size=72), .1 elif remaining > 0.0: return Text("%.1f" % remaining, color="#f00", size=72), .1 else: jump endОшибка в синтаксисе. Может неправильно использовать команду джамп? Цитата
Алекс__ Опубликовано 17 августа, 2011 Жалоба Опубликовано 17 августа, 2011 (изменено) Ошибка в синтаксисе. Может неправильно использовать команду джамп?Угу, вся функция "countdown" написана в блоке <python>, т.е. все команды должны быть на питоне. Эквивалентом команды <jump> будет <renpy.jump ("end")> Ах, да - самое главное! Не забудьте в самом начале блока "end" скрыть с экрана этот самый "countdown" <hide countdown> - иначе условие о том, что время истекло будет всегда выполнено, и программа "бесконечно" будет совершать переход к блоку "end". Изменено 17 августа, 2011 пользователем Алекс__ (смотреть историю редактирования) 1 Цитата
Vicente Опубликовано 17 августа, 2011 Жалоба Опубликовано 17 августа, 2011 А с чем связана эта ошибка?unsupported operand type(s) for +=: 'function' and 'int'Вроде все так же делаю так же, но когда выбираешь пункт в меню с заданной переменной игра вылетает. Цитата
Алекс__ Опубликовано 17 августа, 2011 Жалоба Опубликовано 17 августа, 2011 Что за переменная (как называется, какое значение по умолчанию присвоено)? В тексте ошибки говориться (если я правильно понял), что вы пытаетесь прибавить числовое значение к функции (а не к другому числовому значению). Цитата
Vicente Опубликовано 17 августа, 2011 Жалоба Опубликовано 17 августа, 2011 (изменено) label start: $ say = 0 menu: "Первый пункт": $ say += 1 "Второй пункт": pass jump result2 label result2: if say >0: jump dal5 else: "Плохая концовка." Изменено 17 августа, 2011 пользователем Vicente (смотреть историю редактирования) Цитата
Алекс__ Опубликовано 17 августа, 2011 Жалоба Опубликовано 17 августа, 2011 Понятно, <say> - это функция Рен'пи $ renpy.say ( e, "Hey, it is me talking!") e "Hey, it is me talking!" Если в качестве имен переменных использовать слова, зарезервированные Рен'пи для своего использования (названия функций и т.п.), то это приведет к ошибкам (не стоит называть переменные "jump", "int", "str", "show" и т.д.) Здесь, как в том анекдоте, лучше всего использовать "длинные_и_понятные_имена_переменных". 1 Цитата
Айон XIV Опубликовано 31 августа, 2011 Жалоба Опубликовано 31 августа, 2011 Вот собственно и код "ошибки" - http://i071.radikal.ru/1108/a0/ed042686f9a8.jpgВозможно я и не правильно подумал, но у меня пока что тестовый вариант кода и в нём 8 моментов, когда принудительно выкидывает на другой код в игре, когда изменял количество принудительных перекидываний число в сообщении тоже менялось. Цитата
Алекс__ Опубликовано 31 августа, 2011 Жалоба Опубликовано 31 августа, 2011 Вот собственно и код "ошибки" - http://i071.radikal....d042686f9a8.jpgВозможно я и не правильно подумал, но у меня пока что тестовый вариант кода и в нём 8 моментов, когда принудительно выкидывает на другой код в игре, когда изменял количество принудительных перекидываний число в сообщении тоже менялось.Похоже на использование нескольких countdown'ов...Можно попробовать скрывать их все после того, как осуществляется перекидка... Либо вообще не использовать countdown если нет необходимости отображать таймер, а воспользоваться функцией <timer> (нужна версия 6.12). Вот несколько ссылок - может пригодятсяhttp://lemmasoft.ren...ug+in+Ren%27Py.http://lemmasoft.ren...ug+in+Ren%27Py. http://www.renpy.org...ght=timer#timer Цитата
Айон XIV Опубликовано 3 сентября, 2011 Жалоба Опубликовано 3 сентября, 2011 Отображать таймер надо обязательно, что бы игрок видел, сколько у него времени на раздумье (выбор вариантов). Вот про скрывание - что именно имеете в виду? Например какой командой скрывать, обычной countdown=false или что-то ещё? Цитата
Алекс__ Опубликовано 3 сентября, 2011 Жалоба Опубликовано 3 сентября, 2011 Если countdown сделан так: def countdown(st, at, length=0.0): remaining = length - st if remaining > 5.0: return Text("%.1f" % remaining, color="#fff", size=72), .1 elif remaining > 0.0: return Text("%.1f" % remaining, color="#f00", size=72), .1 else: return anim.Blink(Text("0.0", color="#f00", size=72)), None image countdown = DynamicDisplayable(countdown, length=20.0)то <show countdown> и <hide countdown>.Только все равно с такими таймерами полно проблем - при переходе в игровое меню таймер не останавливается, сохранить его значение в какой-то момент не возможно. Может у вас получится придумать функцию, которая будет отсчитывать время и показывать его на экране (без использования DynamicDisplayable), тогда все может сработать. Цитата
Айон XIV Опубликовано 4 сентября, 2011 Жалоба Опубликовано 4 сентября, 2011 Ну сохраняться во время выбора варианта как-то бредово, так что пофиг :) А вот с "hide countdown" проблемы. Подобное скрывание стоит в самом начале кода какого-либо выбора, и так же стоит в самом начале кода куда кидает принудительно. Если выбирать какой-либо вариант, то всё в порядке. Когда перекидывает принудительно, то в самой игре тоже всё ок, таймер скрывается как и полагается, с "критом" не вышибает. Просто при завершении самой игры (т.е. при обычном выключении) выдаётся сообщение, что была утеряна память (высвечивается только когда были принудительные перекидывания, в остальном без сообщения) Цитата
Айон XIV Опубликовано 4 сентября, 2011 Жалоба Опубликовано 4 сентября, 2011 Забавно получается - скачал 6.12.2 версию, запустил через неё - сообщение перестало вылезать... но теперь после первого принудительного перекидывания начинает постоянно кидать сразу же без выбора вариантов в следующих действиях. Пойду рыться и смотреть, как можно это дело пофиксить. Цитата
Элионт Опубликовано 28 октября, 2011 Жалоба Опубликовано 28 октября, 2011 Приветствую.Алекс, таймер можно сделать на потоках, например так. А вообще на этом шикарнейшем фреймворке можно писать далеко не только игры и как пример - "Программа-таггер для раздела "Арт" сайта 4otaku.ru. Также в качестве моего вклада в развитие предлагаю к ознакомлению и использованию свою библиотеку безотносительных к конкретной игре, но весьма полезных функций и не только (практически чистый питон): # Здесь основные предустановки и функции безотносительные к игре. # Он у меня кочует из проекта в проект и может быть свободно распространён. init python: ##################### Системные установки ##################### import os,pygame,math,sys,random import xml.etree.ElementTree as xmldb # установка окна игры по центру # полезно если запускается не в полный экран os.environ['SDL_VIDEO_CENTERESD'] = '1' sys.setdefaultencoding('utf-8') # лень писать заглавные true = True false = False none = None result = True # иногда может глючить при сохранении, тогда убрать коммент # config.use_cpickle = False ######################## Расположения ######################## top = Position(xalign = 0.5,yalign=0) bottom = Position(xalign = 0.5,yalign=1.0) left = Position(xalign = 0.0,yalign=0.5) right = Position(xalign = 1.0,yalign=0.5) center = Position(xalign = 0.5,yalign=0.5) almost_top = Position(xalign = 0.5,yalign=0.1) almost_bottom = Position(xalign = 0.5,yalign=0.9) almost_left = Position(xalign = 0.1,yalign=0.5) almost_right = Position(xalign = 0.9,yalign=0.5) upright = Position(xalign = 1.0,yalign=0.0) upleft = Position(xalign = 0.0,yalign=0.0) downright = Position(xalign = 1.0,yalign=1.0) downleft = Position(xalign = 0.0,yalign=1.0) up_quarter_left = Position(xalign = 0.25,yalign=0.0) up_quarter_right = Position(xalign = 0.75,yalign=0.0) down_quarter_left = Position(xalign = 0.25,yalign=1.0) down_quarter_right = Position(xalign = 0.75,yalign=1.0) center_up = Position(xalign = 0.5,yalign = 0.25) ########################## Изображения ########################## renpy.image('bg black',Solid((0,0,0,255))) renpy.image('bg blood',Solid((150,6,7,255))) # цвета определены в colors.rpy ##################### Автоассоциирование ##################### # фоны с автоподгонкой размера изображения под размеры экрана # вызов производится "show bg <filename>" # имя файла без расширения for fname in os.listdir(config.gamedir + '/gfx/bg'): if fname.endswith(('.jpg')): tag = 'bg ' + fname[:-4] image = 'gfx/bg/' + fname renpy.image(tag,im.Scale(image,config.screen_width,config.screen_height)) ##################### Остальное ##################### def trans_fadein(t, st, at): t.zoom = min(1.0, 0.01 + st / 1.0) t.alpha = min(1.0, 0.01 + st / 1.0) return 0 def trans_fadeout(d, st, at): d.alpha = max(0.0, 1.0 - st / 2.0) return 0 def particle_burst(img, xs, ys, xrad=0.05, yrad=0.05, wave=13, cnt=10): for ii in range (wave): renpy.pause(0.1) for i in range(cnt): xd = renpy.random.random() if xd > xs + xrad: xd = xs + xrad if xd < xs - xrad: xd = xs - xrad yd = renpy.random.random() if yd > ys + yrad: yd = ys + yrad if yd < ys - yrad: yd = ys - yrad speed = renpy.random.random() renpy.show(img,at_list=[Transform(function=trans_fadeout),Move((xs,ys,0.5,0.5),(xd,yd,0.5,0.5),speed)],tag='%d%d'%(i,ii)) for ii in range (wave): for i in range(cnt): renpy.transition(slow_dissolve) renpy.hide('%d%d'%(i,ii)) # возвращает последовательнось например 1-2-3-2-1 def arcrange(start,end,step=1): list = [] for i in range(start,end+1): list.append(i) pos = len(list) for i in range(start,end): list.insert(pos,i) return list # округление def math_round(number): integer,fraction = math.modf(number) if fraction >= 0.5: integer = math.ceil(number) else: integer = math.floor(number) return int(integer) # получить знак числа def sign(number): if number > 0: return 1 elif number < 0: return -1 else: return 0 # эта функция не делает ничего, совсем ничего... def do_nothing(): pass # боремся с целочисленным по умолчанию делением def divide(n1,n2): return float(n1)/float(n2) # бросок стогранной кости. value - шанс, max - грани # например if dice(60): означает вероятнось в 60% def dice(value,max=100): number = random.randrange(0,max+1) if number <= value: result = True else: result = False if config.developer: notify(u"Выпало %d из %d, предел - %d, итог - %s."%(number,max,value,str(result))) return result # выбрать случайный вариант из предложенных def select(variants): result = random.choice(variants) if config.developer: notify(u"Выбрано '%s'."%str(result)) return result # выяснить что за нафиг путём записи нужных сообщений в файл # хотя вообще-то wtf = Write To File, но пользоватьей приходится # когда думаешь WTF?! в другой расшифровке... def wtf(message,logfile="bughunt.txt"): file = open(renpy.loader.transfn(file),"a") file.write(str(message)+"\n") file.close() # обёртка над оповещалкой def notify(message,style=False): if config.developer: if style: msg = "{=%s}%s"%(style,str(message)) renpy.notify(u"%s"%msg) else: renpy.notify(u"{size=+10}%s"%str(message)) # безопасный джамп # если метки нет, игра не вылетит а просто сообщит об этом def jump(labelname): if renpy.has_label(labelname): notify("jump %s"%labelname) renpy.jump(labelname) else: notify(u"Метки '%s' не существует."%labelname) # анализ строк и превращение их целые, дробные, и логические значения def parse(string): try: value = int(string) except TypeError: value = string except AttributeError: value = string except ValueError: try: value = float(string) except ValueError: if string.lower() in ['true','yes','on']: value = True if string.lower() in ['false','no','off','none']: value = False else: value = string return value # Первая часть работы с базами данных - автокласс # Универсальная структура данных class Structure(object): def __init__(self,namespace=None): self.flags = [] if namespace: for key in namespace: self.set(key,namespace[key]) def get(self,par): return self.__dict__[par] def namespace(self): return self.__dict__ def has(self,par): return self.__dict__.has_key(par) def set(self,par,value): self.__dict__[par] = value def mod(self,par,value): self.__dict__[par] += value def flag(self,flag): return flag in self.flags def setflag(self,flag): if flag not in self.flags: self.flags.append(flag) def delflag(self,flag): if flag in self.flags: self.flags.remove(flag) # вторая часть движка для работы с базами # разбор файла и загрузка его в словарь # выловленный в инете скрипт разбора ини доработан # для работы ещё и с хмл def dict_from_config_file(file, raw=false, vars=None): result = dict() if file[-3:] == 'ini': """Convert an INI file to a dictionary""" #from cherrypy inifile = ConfigParser() inifile.read(renpy.loader.transfn(file)) # Parse config file # Load INI file into a dict for section in inifile.sections(): result[section] = dict() for option in inifile.options(section): v = inifile.get(section, option, raw, vars) result[section][option] = v elif file[-3:] == 'xml': tree = xmldb.parse(renpy.loader.transfn(file)).getroot() for node in tree: if not node.attrib.has_key('id'): node.attrib['id'] = node.tag result[node.attrib['id']] = node.attrib result[node.attrib['id']]['xml'] = node return result # Третья часть движка для работы с базами # превращаем словари в объекты и обрабатываем значения # 'true','yes','on','false','no','off' - станут логическими # числа без точки - станут целыми # числа с точкой - станут дробными # строки - строками и останутся )) # за это отвечает функция parse() определённая ранее # Параметры: # dic - можно вставить в существующий словарь, или использовать новый # entity - класс который создавать, имненно ссылка на тип существующего класса # perform_init - выполнить метод "init" ( не __init__ ) после загрузки def load_database(file,dic = None,entity = Structure,perform_init = False): db = dict_from_config_file(file) if not dic: dictionary = dict() else: dictionary = dic for entry in db: dictionary[entry] = entity() for key in db[entry]: dictionary[entry].__dict__[key] = parse(db[entry][key]) dictionary[entry].id = entry if perform_init: for entry in dictionary: dictionary[entry].init() return dictionary # покажет позицию курсора если вывести рисунок cursorPosition # show cursorPosition on bottom def cursorPositionFunction(st, at): x,y = pygame.mouse.get_pos() return Text("{size=+10}%d - %d"%(x,y)), .1 image cursorPosition = DynamicDisplayable(cursorPositionFunction) label _instant_exit: $renpy.quit() label _full_restart: $renpy.full_restart() # добавляет в нижний левый угол несколько полезных на стадии разаработки примочек screen debugTools: hbox: xalign 0 yalign 1.0 button: text "X" action ui.callsinnewcontext("_instant_exit") button: text "R" action ui.callsinnewcontext("_save_reload_game") add(DynamicDisplayable(cursorPositionFunction)) yalign 0.5 Полная версия прикреплена к сообщению. До недавнего времени ковырял свой проект, начатый в августе 2009, после завершения работы над модом "Конец одиночества" к игре "Проект воспитания Аянами Рей" но недавно присоединился к разработке Alkion (солянка из WhoreMaster, OtherWorld, RoyalHunt) и сейчас работаю с ними, перетащив туда большую часть кода (так как игры схожие по плану с технической стороны) с планами доработать его во время разработки Алькиона и перетащить назад усовершенствованные. Скриншоты текущей версии можно посмотреть здесь. Если кому интересно - контакты в профиле.library.zip 1 Цитата
Алекс__ Опубликовано 28 октября, 2011 Жалоба Опубликовано 28 октября, 2011 Алекс, таймер можно сделать на потоках, например так.Привет, наверное можно, но моих "знаниев" для этого недостаточно...;) Цитата
Элионт Опубликовано 29 октября, 2011 Жалоба Опубликовано 29 октября, 2011 Посидел вечерок и организовал таймер на версии Ренпи 6-12-2.Под спойлером полный код.Создай новый проект и замени содержимое script.rpy содержимым спойлера. define e = Character('Eileen', color="#c8ffc8") init python: import thread,time # функция, которая будет запущена в другом потоке def timer(): renpy.notify(u"Таймер запущен.") while True: # бесконечный цикл time.sleep(1) # ждём секунду persistent.timer_counter -= 1 # уменьшаем счётчик renpy.notify(u"%d"%persistent.timer_counter) # оповещаем пользователя if persistent.timer_counter == 0: # время почти вышло time.sleep(1) # последняя секунда persistent.timer_result = False # результат - не успели return # запуск таймера def start_timer(time): persistent.timer_counter = time # время в секундах persistent.timer_result = True # результат Истина пока время не истечёт thread.start_new_thread(timer,()) # запускаем поток. # переход по результатам таймера def timed_jump(success,failure): # если успели if persistent.timer_result: persistent.timer_counter = 1 # фактически, это отключает таймер renpy.jump(success) # если не успели else: renpy.jump(failure) # отключение таймера и переход, вне зависимости от результатов def no_timed_jump(destination): persistent.timer_counter = 1 renpy.jump(destination) # Поехали! label start: e "На следующий выбор вам будет дано ограниченное время." $start_timer(10) # запускаем таймер на 10 секунд menu timed_menu: "Выбирай мудро (и быстро)!" "Сесть на автобус": $timed_jump("MadeInTime","TooSlow") "Подождать другого": $no_timed_jump("WaitingAnotherBus") return label MadeInTime: e "Вы успели." return label TooSlow: e "Автобус ушёл." jump WaitingAnotherBus return label WaitingAnotherBus: e "Подожду другого, может хоть там свободные места будут." return Если что - обращайся. 1 Цитата
wec Опубликовано 11 ноября, 2011 Жалоба Опубликовано 11 ноября, 2011 Здравствуйте. Пытаюсь в Ren'Py реализовать такую идею: подводим курсор к определенному месту экрана, картинка начинает двигаться, убираем курсор, движение прекращается. Вопрос Элионту. Как переделать твою функцию: def cursorPositionFunction(st, at): x,y = pygame.mouse.get_pos() return Text("{size=+10}%d - %d"%(x,y)), .1 чтобы она возвращала x,y мыши в реальном времени? И как ее правильно вызывать в Ren'Py? Цитата
Алекс__ Опубликовано 16 ноября, 2011 Жалоба Опубликовано 16 ноября, 2011 Здравствуйте. Пытаюсь в Ren'Py реализовать такую идею: подводим курсор к определенному месту экрана, картинка начинает двигаться, убираем курсор, движение прекращается. Если используете версию Рен'пи 6.13.х то вам поможет <mousearea>. Здесь пример кода, который показывает экран с кнопками когда подводишь мышь к верхнему краю экрана и убирает его, когда мышь отводят вниз http://www.renpy.org/doc/html/screens.html#sl-mousearea (transition=dissolve - эффект с которым показывается/скрывается окно).Можете в качестве действия при наведении на активную область поставить показ экрана с анимированной картинкой, а в случае, когда курсор вне активной области - показывать экран с обычной картинкой. Вот, как-то так. Цитата
Элионт Опубликовано 17 ноября, 2011 Жалоба Опубликовано 17 ноября, 2011 Вопрос Элионту.Определяем скрин.# добавляет в нижний левый угол несколько полезных на стадии разаработки примочек # X - мгновенный выход, в обход диалога подтверждения # R - перекомпиляция игры # также отображает текущие координаты курсора screen debugTools: hbox: xalign 0 yalign 1.0 button: text "X" action ui.callsinnewcontext("_instant_exit") button: text "R" action ui.callsinnewcontext("_save_reload_game") add(DynamicDisplayable(cursorPositionFunction)) yalign 0.5Показываем его при запуске игры.Будет в реальном времени.# The game starts here. label start: show screen debugToolsCommon.rpy.new_version.zip Цитата
wec Опубликовано 17 ноября, 2011 Жалоба Опубликовано 17 ноября, 2011 Большое спасибо Алекс__у и Элионту за ответы. Буду разбираться. Потом отпишусь :-) Цитата
wec Опубликовано 17 ноября, 2011 Жалоба Опубликовано 17 ноября, 2011 Вот код:init: python: def cursorPositionFunction(st, at): x,y = pygame.mouse.get_pos() return x label start: python: x = cursorPositionFunction if x > 600: ui.image ("photo2.jpg") centered "" returnКоордината х определяется, но только один раз, при вызове функции.Как сделать, чтобы позиция курсора отслеживалась в реальном времени, т.е. функция вызывалась постоянно?(как при DynamicDisplayable)С <mousearea> пока не получается. Хотелось бы решить эту задачу на одном screen. Цитата
Элионт Опубликовано 18 ноября, 2011 Жалоба Опубликовано 18 ноября, 2011 (изменено) Как сделать, чтобы позиция курсора отслеживалась в реальном времени, т.е. функция вызывалась постоянно? Используй скрин а не функцию. С функцией в версии старше 6.12 работать не будет. А пример работы (и код) mousearea можно посмотреть в этой новелле-рецепте (подведя мышку к верхнему краю экрана) которую я делал для знакомого с 4otaku. Является переделанной версией "Набора для создания визуальной новеллы Хроники Валькирии". Изменено 18 ноября, 2011 пользователем Элионт (смотреть историю редактирования) Цитата
wec Опубликовано 19 ноября, 2011 Жалоба Опубликовано 19 ноября, 2011 Элионт и Алекс__ еще раз спасибо за помощь. Все получилось. Кстати очень понравилась новелла-рецепт.Выкладываю пример: "Прокрутка панорамы". Может кому пригодится :rolleyes:ps. (Как реализовать бесшовную прокрутку пока не придумал)panorama.zip Цитата
Алекс__ Опубликовано 19 ноября, 2011 Жалоба Опубликовано 19 ноября, 2011 (Как реализовать бесшовную прокрутку пока не придумал) ... попробуйте добавить справа и слева к картинке кусок с другой стороны размером в ширину экрана (или в пол-экрана), и когда он будет показан до конца - перепрыгните к началу картинки...хм, сам не понял, что написал...(Вобщем, начало картинки и конец картинки должны быть одинаковыми (панорама будет не 360 градусов а больше). Цитата
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.