RU

Помощь в начинании

Mr.Crazzyr #623 22.07.2012 21:27 27 comments 14433 views

Всем доброго времени суток.

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

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

Так же у меня накопилась несметная масса вопросов:

1.

’ У вас <<Деньги>> монет.’

’ Вам нужно перенести <<3-Ящик>> ящика.’

ACT ‘Перенести ящик’:

‘Вы перенесли 1 ящик’

Ящик = Ящик + 1

IF Ящик = 3:

Деньги = Деньги + 5

Ящик = 0

END

GOTO ‘Работа’

END

Почему фраза

‘Вы перенесли 1 ящик’

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

2. RAND я вообще не понял. Или он просто не работает :D

horse = Rand (1, 3)

IF horse > 2:

msg ’ Выиграли’

ACT ‘Забрать приз’:

GT ‘Wictory’

END

END

IF horse = 1:

msg’ Не повезло вам.’

End

Почему этот код просто напросто не срабатывает когда я попадаю в локацию? Даже программа никаких ошибок не выдает.

Edited at 22.07.2012 21:27 (13 years ago)

А вот тебе мои не слишком профессиональные ответы:

Mr.Crazzyr:

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

Все переменные глобальные.

Mr.Crazzyr:

Почему фраза

‘Вы перенесли 1 ящик’

не пишется в основном окне?

Как насчёт *NL ‘Вы перенесли 1 ящик’?

Mr.Crazzyr:

Почему этот код просто напросто не срабатывает когда я попадаю в локацию

Если ты вставил этот текст из кода, то обрати внимание, что критически важен хороший стиль программирования, в актах, условия и прочее, что имеет тело, тело должно быть с табуляцией, то бишь:
if asdasd=1:
f=f+1
end
А RAND ты используешь правильно

Почему фраза ‘Вы перенесли 1 ящик’ не пишется в основном окне?

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

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

QSP “находит” переменные как только встретит их первое упоминание, изначально числовым переменным присваивается значение “0”. Это называется “значение по умолчанию”.

Почему этот код просто напросто не срабатывает когда я попадаю в локацию?

У тебя описаны условия для случаев, когда horse равняется 1 или 3, а если в результате RAND “выпало” значение 2, то ничего и не должно произойти.

существует ли полноценный обучающий материал или нужно самому догадываться пользуясь невнятной справкой программы?

Учебников, описывающих в подробностях все возможности и приемы программирования на QSP, нет. Существующий учебник рассматривает только основы, тем не менее, этого вполне достаточно для написания полноценной текстовой игры. Справка неудобна, и мы это знаем, но переделать ее сейчас некому. Помимо учебника и справки, у нас есть примеры кода на странице Разработчикам, а также FAQ. За более оперативной помощью можешь обращаться на IRC-канал #qsp.

Antipod,

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

Такс… я не совсем разобрался в переменных. Если у меня в отдельной локации Scor будет переменная One = 1, и мне необходимо, что бы ее число изменилось в одной локации и применялось в другой. Я пишу

Spoiler

One = Rand (1, 3)
IF One = 2:
msg ’ Выиграли’
AСT ‘Забрать приз’:
One = 2
GT ‘Next_Level’
END
END
IF One = 1 or 3:
msg’ Не повезло вам.’
AСT ‘Далее’:
One = 3
GT ‘Next_Level’
END
End
Gs ‘Scor’

Далее я перехожу в локацию Next_Level и буду оператором If задавать им действия, в зависимости от того 2 это или 3, ссылаясь Gs на Scor. А поскольку в локации Scor принудительно указано, что это 1 то будет ли эта 1 игнорироваться? Ведь мы ей уже присвоили 2 или 3 рандомом.

По поводу сообщений. Что *NL, что просто NL в данном случает вообще роли не сыграли. А вот XGOTO сработал но меня смутило, что

’ У вас <<Деньги>> монет.’
’ Вам нужно перенести <<3-Ящик>> ящика.’

лепится по новой ниже. Немного по мудрил, придумал выход.

Spoiler

’<center><b>Порт</b></center>

ACT ‘Идти домой’:
Ящик = 0
GOTO ‘Дом’
END
ACT ‘Идти в магазин’:
Ящик = 0
GOTO ‘Магазин’
END
IF Ящик = 0:
‘Порт находится на самой южной окраине города. Здесь постоянно загружаются и разгружаются различные суда. Рабочих рук не хватает и складской бригадир всегда рад заплатить <i>деньги</i> за помощь.’
‘У вас <<Деньги>> монет.’
‘Вам нужно перенести 3 ящика.’
ACT ‘Перенести ящик’:
‘Вы перенесли 1 ящик’
Ящик = Ящик + 1
xGOTO ‘Работа’
END
END
IF Ящик = 1:
‘Порт находится на самой южной окраине города. Здесь постоянно загружаются и разгружаются различные суда. Рабочих рук не хватает и складской бригадир всегда рад заплатить <i>деньги</i> за помощь.’
‘У вас <<Деньги>> монет.’
‘Вам нужно перенести 2 ящика.’
ACT ‘Перенести ящик’:
‘Вы перенесли 1 ящик’
Ящик = Ящик + 1
xGOTO ‘Работа’
END
END
IF Ящик = 2:
‘Порт находится на самой южной окраине города. Здесь постоянно загружаются и разгружаются различные суда. Рабочих рук не хватает и складской бригадир всегда рад заплатить <i>деньги</i> за помощь.’
‘У вас <<Деньги>> монет.’
‘Вам нужно перенести 1 ящика.’
ACT ‘Перенести ящик’:
‘Вы перенесли 1 ящик’
Деньги = Деньги + 5
Ящик = 0
xGOTO ‘Работа’
END
END

И вот тут я поломал моск. Мне нужно, что б надпись:

‘Порт находится на самой южной окраине города. Здесь постоянно загружаются и разгружаются различные суда. Рабочих рук не хватает и складской бригадир всегда рад заплатить <i>деньги</i> за помощь.’
‘У вас <<Деньги>> монет.’

всегда была на экране и не исчезала и не дублировалась ниже после действия, но фраза

‘Вы перенесли 1 ящик’

всегда появлялась ниже при выполнении действия.

Так же я возникся вопросом: возможно ли игру сделать исполняющим файлом .EXE? Что б не запускать постоянно плеер и выбирать там файл, а просто запустить исполняющий файл и сразу же запустилась игра.

IF One = 1 or 3:

Так писать нельзя. Нужно написать так:

IF One = 1 or One = 3:

Еще лучше, взять выражения в скобки, для наглядности:

IF (One = 1) or (One = 3):

Поехали дальше.

буду оператором If задавать им действия, в зависимости от того 2 это или 3, ссылаясь Gs на Scor. А поскольку в локации Scor принудительно указано, что это 1 то будет ли эта 1 игнорироваться? Ведь мы ей уже присвоили 2 или 3 рандомом.

Разумеется, ничего игнорироваться не будет. Если в локации “Scor” есть присваивание, оно выполнится, как только мы вызовем локацию по GS. Если не хочешь, чтобы присваивание выполнялось, убери его из “Scor”.

Далее. По ящикам. Немного сокращаю для наглядности. Красным выделил изменения. Вычеркнул то, что нужно убрать.

IF Ящик = 0:
‘Порт находится … за помощь.’
‘У вас <<Деньги>> монет.’
‘Вам нужно перенести 3 ящика.’
ACT ‘Перенести ящик’:
‘Вы перенесли 1 ящик’
Ящик = Ящик + 1
ящик_перенесен = 1
GOTO ‘Работа’
END
END
IF Ящик = 1:
‘Порт находится … за помощь.’
‘У вас <<Деньги>> монет.’
‘Вам нужно перенести 2 ящика.’
ACT ‘Перенести ящик’:
‘Вы перенесли 1 ящик’
Ящик = Ящик + 1
ящик_перенесен = 1
GOTO ‘Работа’
END
END
IF Ящик = 2:
‘Порт находится … за помощь.’
‘У вас <<Деньги>> монет.’
‘Вам нужно перенести 1 ящика.’
ACT ‘Перенести ящик’:
‘Вы перенесли 1 ящик’
Деньги = Деньги + 5
Ящик = 0
ящик_перенесен = 1
GOTO ‘Работа’
END
END
IF ящик_перенесен = 1:
ящик_перенесен = 0
‘Вы перенесли 1 ящик’
END

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

Да, можно. Можно, например, собрать самораспаковывающийся RAR-архив. Но это имеет смысл, только если ты собираешься самостоятельно распространять игру.

На нашем сайте игры публикуются в виде zip-архива. На твоем компьютере, если ты устанавливал “Набор игрока”, расширение “.qsp” “привязано” к плееру, поэтому достаточно щелкнуть мышкой qsp-файл игры, чтобы игра открылась в плеере. Во время редактирования игры в QGen, ее можно запустить по нажатию кнопки в виде синего треугольника, либо клавиши F5.

Nex,
Спасибо конечно, но с ящиками я не это имел ввиду. Приведу другой вариант того, что я хотел. Предположим идет пошаговый бой. На экране написано:

Арена открыта. Бой начался! Ваш соперник: Игрок 2!

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

Игрок 1 нанес ‘столько то’ урон Игроку 2.

Эта фраза должна писаться под первой фразой написаной выше и оставатся на экране до конца. Далее второй ход:

Игрок 2 ответил Игроку 1 и нанес ‘столько то’ урона.

Эта фраза должна писаться еще ниже

Арена открыта. Бой начался! Ваш соперник: Игрок 2!
Игрок 1 нанес ‘столько то’ урон Игроку 2.
Игрок 2 ответил Игроку 1 и нанес ‘столько то’ урона.

И т.д. до завершения боя. А с ящиками выходит, что ‘Вы перенесли 1 ящик’ стоит на одном месте и при действии просто исчезает и заменяется такой же самой.

Mr.Crazzyr,
описанное тобой поведение нарушает логику повествования. Будет написано так:

Порт бла-бла-бла.
Вам нужно перенести 2 ящика.
Вы перенесли ящик.
Вы перенесли ящик.
Вы перенесли ящик.
Вы перенесли ящик.
Вы перенесли ящик.
Вы перенесли ящик.

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

Mr.Crazzyr,
можно сделать так. Суть твоих изменений - добавить сообщение о том, что игрок взял ящик. Тогда берем изначальный вариант кода из уроков и дописываем его так:

‘<center><b>Порт</b></center>

’ Порт находится на самой южной окраине города. Здесь постоянно загружаются и разгружаются различные суда. Рабочих рук не хватает и складской бригадир всегда рад заплатить <i>деньги</i> за помощь.’
’ У вас <<Деньги>> монет.’
’ Вам нужно перенести <<3-Ящик>> ящика.’
ACT ‘Идти домой’:GOTO ‘Дом’
ACT ‘Идти в магазин’:GOTO ‘Магазин’
ACT ‘Перенести ящик’:
Ящик = Ящик + 1
‘Вы перенесли ящик.’
IF Ящик = 3:
Деньги = Деньги + 5
‘Вам заплатили 5 монет за разгрузку. Теперь у вас <<Деньги>> монет. Бригадир обещает заплатить еще за три ящика, если справитесь.’
Ящик = 0
END
GOTO ‘Работа’
END

Nex,
Спасибо, разобрался с не пропадающим сообщением. Логики повествования тут нет, это был просто пример с ящиками без сюжета в целях обучения. У меня возник следующий вопрос по поводу объектов. Предположим: ведётся беседа с персонажем, в выше описанном стиле где текст не пропадает, и мне необходимо использовать предмет из инвентаря, при этом предмет должен исчезнуть из инвентаря, но текст не очистится в окне, а остаться. $Curlock просто чистит окно, при переходе GOTO текст пропадает. DelObj удаляет предмет, но если не обновить окно будет казаться, что предмет всё еще у меня есть. Как поступить в таком случае?

Mr.Crazzyr,

ACT 'Съесть яблоко':
    DELOBJ 'яблоко'
    DELACT $SELACT
END

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

Просто для уточнения, правильно ли я понимаю:
$SELACT служит для обозначения текущего ACT в котором оно присутсвует. Т.е. вместо DELACT ‘Съесть яблоко’ можно просто написать DELACT $SELACT.
Так же я заметил, что ACT выполняет действия последовательно и сразу, а не по одному за раз

Spoiler
Act 'Поговорить с сестрой':
	If Psi = 0:
		'-Слушай, принеси ка мне психофазатрон, я тебе дам 5 баксов'
		'-Что за вопросы, считай уже зделано'
	END
	If Psi = 1:
		'-Вот твой психофазатрон, где мои деньги?'
		'-Да всё путем вот твои деньги. Кстате, спасибо'
		Деньги = Деньги + 5
		DelObj 'Психофазатрон'
		Psi = 2
	End
	If Psi = 2:
		'-Не мешай мне, я занята'
	END
End

В такоем случае получаеться фразы произносится сразу вместе

-Вот твой психофазатрон, где мои деньги?
-Да всё путем вот твои деньги. Кстате, спасибо
-Не мешай мне, я занята

Вырезал кусок

Spoiler

If Psi = 2:
‘-Не мешай мне, я занята’
END

и влепил его в начало

Spoiler
Act 'Поговорить с сестрой':
	If Psi = 2:
		'-Не мешай мне, я занята'
	END
	If Psi = 0:
		'-Слушай, принеси ка мне психофазатрон, я тебе дам 5 баксов'
		'-Что за вопросы, считай уже зделано'
	END
	If Psi = 1:
		'-Вот твой психофазатрон, где мои деньги?'
		'-Да всё путем вот твои деньги. Кстате, спасибо'
		Деньги = Деньги + 5
		DelObj 'Психофазатрон'
		Psi = 2
	End
End

получилось так как и задумывалось. Как то это не правильно..

Да, выполняются все команды последовательно. Все логично. Если нужно выполнение только одного из условий, используйте ELSEIF вместо IF, а именно:

Spoiler
Act 'Поговорить с сестрой': 
    IF Psi = 0: 
        '-Слушай, принеси ка мне психофазатрон, я тебе дам 5 баксов' 
        '-Что за вопросы, считай уже зделано' 
    ELSEIF Psi = 1: 
        '-Вот твой психофазатрон, где мои деньги?' 
        '-Да всё путем вот твои деньги. Кстате, спасибо' 
        Деньги = Деньги + 5 
        DelObj 'Психофазатрон' 
        Psi = 2 
    ELSEIF Psi = 2: 
        '-Не мешай мне, я занята' 
    END 
End

Mr.Crazzyr,
все правильно. Если в чем-то сомневаешься, смотри в справку.

Всем привет еще раз. И снова я обращась к вам за советом. Всё работает верно и правильно. Вопрос такой: можнно ли как то упростить такое масовое количество IF / ELSEIF? Может есть какойто секрет оптимизации или еще, что то.
У меня есть код:

Spoiler
IF пельмени_в_воде = 1 or пельмени_в_воде = 2:
	CLS
	IF пельмени_в_воде = 1:
		IF вода_посолена = 1:
			'Вы сытно пообедали и голод как рукой сняло'
			голод = 0
			run = 0
			ACT 'Закончить приготовление':
				пельмени_в_воде = 0
				GT curloc
			END
		END
	ELSEIF пельмени_в_воде = 2:
		свареные = RAND(1,2)
		IF вода_посолена = 0 and свареные = 1:
			'Вы кое как запихнули в себя недовареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее'
			голод = 4
			run = 0
			Выйти = 1
			ACT 'Закончить приготовление':
				пельмени_в_воде = 0
				GT curloc
			END
		ELSEIF вода_посолена = 0 and свареные = 2:
			'Вы кое как запихнули в себя перевареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее'
			голод = 4
			run = 0
			Выйти = 1
			ACT 'Закончить приготовление':
				пельмени_в_воде = 0
				GT curloc
			END
		ELSEIF вода_посолена = 1 and свареные = 2:
			'Вы кое как запихнули в себя перевареные пельмени.'
			голод = 4
			run = 0
			Выйти = 1
			ACT 'Закончить приготовление':
				пельмени_в_воде = 0
				GT curloc
			END
		ELSEIF вода_посолена = 1 and свареные = 1:
			'Вы кое как запихнули в себя недовареные пельмени.'
			голод = 4
			run = 0
			Выйти = 1
			ACT 'Закончить приготовление':
				пельмени_в_воде = 0
				GT curloc
			END
		END
	END
END

loca = 5

IF кот = 5: 
	'На тумбочке вальяжно развалился кот <<$кот[кличка]>>'
	ACT 'Взять кота':
		кот = 0
		ADDOBJ 'Кот <<$кот[кличка]>>'
		DELACT 'Взять кота'
		GT curloc
	END
END

На всякий случай приложил всю игру
Скачать

Причина редактирования: забыл спросить. В самом начале кода идет проверка

IF пельмени_в_воде = 1 or пельмени_в_воде = 2:

и если условие верно то должен сработать оператор CLS, он срабатует верно но пропускает проверку кота. И если кот верен но всёравно лепит снизу

‘На тумбочке вальяжно развалился кот <<$кот[кличка]>>’

Почему так происходит? Ведь стоит же оператор CLS

Mr.Crazzyr,
для упрощения нужно вынести выполняющиеся во всех случаях операторы за условие. Раз они выполняются в любом случае, то должны стоять вне условия.

IF пельмени_в_воде = 1 or пельмени_в_воде = 2:
CLS
IF пельмени_в_воде = 1:
IF вода_посолена = 1:
‘Вы сытно пообедали и голод как рукой сняло’
голод = 0
run = 0
ACT ‘Закончить приготовление’:
пельмени_в_воде = 0
GT curloc
END
END
ELSEIF пельмени_в_воде = 2:
свареные = RAND(1,2)
IF вода_посолена = 0 and свареные = 1:
‘Вы кое как запихнули в себя недовареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее’

ELSEIF вода_посолена = 0 and свареные = 2:
‘Вы кое как запихнули в себя перевареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее’

ELSEIF вода_посолена = 1 and свареные = 2:
‘Вы кое как запихнули в себя перевареные пельмени.’

ELSEIF вода_посолена = 1 and свареные = 1:
‘Вы кое как запихнули в себя недовареные пельмени.’

END
голод = 4
run = 0
Выйти = 1
ACT ‘Закончить приготовление’:
пельмени_в_воде = 0
GT curloc
END
END
END

В итоге получаем:

IF пельмени_в_воде = 1 or пельмени_в_воде = 2:
    CLS
    IF пельмени_в_воде = 1:
        IF вода_посолена = 1:
            'Вы сытно пообедали и голод как рукой сняло'
            голод = 0
            run = 0
            ACT 'Закончить приготовление':
                пельмени_в_воде = 0
                GT curloc
            END
        END
    ELSEIF пельмени_в_воде = 2:
        свареные = RAND(1,2)
        IF вода_посолена = 0 and свареные = 1:
            'Вы кое как запихнули в себя недовареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее'
        ELSEIF вода_посолена = 0 and свареные = 2:
            'Вы кое как запихнули в себя перевареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее'
        ELSEIF вода_посолена = 1 and свареные = 2:
            'Вы кое как запихнули в себя перевареные пельмени.'
        ELSEIF вода_посолена = 1 and свареные = 1:
            'Вы кое как запихнули в себя недовареные пельмени.'
        END
        голод = 4
        run = 0
        Выйти = 1
        ACT 'Закончить приготовление':
            пельмени_в_воде = 0
            GT curloc
        END
    END
END
...

Количество ELSEIF не сократилось, но код стал короче, т.к. мы избавились от дублирования. Далее, можно разбить блок с большим количеством ELSEIF на два раздельных IF, согласно условиям:

IF вода_посолена = 0 and свареные = 1:
            'Вы кое как запихнули в себя недовареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее'
        ELSEIF вода_посолена = 0 and свареные = 2:
            'Вы кое как запихнули в себя перевареные пельмени. Возможно если бы вы посолили воду было хоть немного вкуснее'
        ELSEIF вода_посолена = 1 and свареные = 2:
            'Вы кое как запихнули в себя перевареные пельмени.'
        ELSEIF вода_посолена = 1 and свареные = 1:
            'Вы кое как запихнули в себя недовареные пельмени.'
        END

Получаем

IF свареные = 1:
            *P 'Вы кое как запихнули в себя недовареные пельмени. '
        ELSE
            *P 'Вы кое как запихнули в себя перевареные пельмени. '
        END
        IF вода_посолена = 0:
            *P 'Возможно если бы вы посолили воду было хоть немного вкуснее'
        END
        ''

Количество строк не сократилось, но стало вроде бы нагляднее.

Про проверку кота. Тебе нужно, чтобы если выполнился оператор CLS, то не осуществлялась проверка кота?

Log in or Register to post comments.