Лайф-бары в BlitzMax
Содержание :
1 Введение 2 Ближе к делу 3 Type TBar 4 Function Create() 5 Method Draw() 6 Method Update() 7 Выведение
Введение
Привет, сегодня я хочу вам рассказать про бар. Да не про тот бар, где мы вчера бухали с друзьями. Это нечто иное, что используется во многих играх, с самых древних ZX времен и даже по сей день. Интернет-переводчик translate.ru слово «bar» – перевел как «брусок». Я бы перевел его, как полоска или шкала. Вам знакомы такие слова - ProgressBar, StatusBar, ScrollBar, LifeBar…? это некие шкалы, заполнение которых, зависит от некоторых событий или переменных. То есть визуально и динамически отображается какой-то процесс, некая замена скучным цифрам. Типичные примеры: шкала загрузки(ProgressBar), перед началом программы на экране пишется что-то типа Loading и шкала(Bar) заполняется по мере выполнения загрузки; LifeBar стратегии, где над юнитами располагаются полоски символизирующие кол-во жизни юнита. ScrollBar - тоже полоска, которая меняет свои размеры, например, в зависимости от кол-ва текста в окне. EnergyBar – в Worms- сила броска/удара. SkillBar – шкала умений персонажа в RPG. Да что там говорить, на моем стареньком мобильнике, уровень заряда батарей изображается как раз EnergyBar-ом. А увеличивая громкость телевизора мы можем наблюдать VolumeBar. Можно перечислять очень долго, так как существует множество разновидностей Bar-ов. Хочу заметить, что не все они имеют только горизонтальное расположение, бывают так же вертикальные и произвольной формы.
Ближе к делу
Я же хочу вам рассказать, как сделать горизонтальную шкалу на примере шкалы жизни, но эта информация применима также и ко всем остальным видам Bar-ов. Я использую язык BlitzMax, но вы можете использовать любой другой ЯП, для воспроизведения данного алгоритма. Сначала немного теории. Для отображения шкалы я воспользуюсь обычными функциями BMax-а: DrawRect(x,y,width,height). Эта функция рисует прямоугольник длинною width, и высотой height, начиная с координат x и y. Синим цветом, я изображу прямоугольник, который будет отображать максимальное кол-во жизни героя, и он будет рисоваться первым.
А красным цветом мы будем рисовать прямоугольник, который показывает сколько на данный момент жизни у нашего героя (реально).
Второй прямоугольник будет рисоваться начиная с тех же координат x и y, что и синий прямоугольник, то есть красный будет накладываться на синий. Но длина его(CurWidth) будет напрямую зависеть от здоровья юнита(!). Так если количество жизней максимально, то виден будет только красный прямоугольник, потому что он будет полностью закрывать собою синий. Если половина жизни, то красный закроет синий на половину. А если кол-во жизней 0, то мы увидим только синий прямоугольник, красный рисоваться не будет. Ну думаю, принцип понятен. Для начала, давайте введем, какой ширины(далее слово длина обозначает то же самое) и высоты будет наша шкала жизни:
Const WIDTHBAR:Int = 200 ‘ ширина шкалы Const HEIGHTBAR:Int = 16 ‘ высота шкалы
Type TBar
Теперь сделаем класс(тип) TBar который будет:
- Создавать шкалу
- Изменять ее в зависимости от кол-ва жизни героя
- Отображать ее на экране
Названия функций, соответственно по пунктам:
- function Create()
- method Update()
- method Draw()
Но для начала опишем все свойства или поля(Field) нашего типа:
Field CurPts:Int
Field MaxPts:Int Field x:Int Field y:Int Field Width:Int = WIDTHBAR Field Height:Int = HEIGHTBAR Field Percent:Int Field CurWidth:Int
Пробежимся по всем переменным: CurPts – текущее количество жизни(здоровья) MaxPts – максимальное количество жизни(здоровья) x и y – координаты для рисования шкалы на экране Width и Height – габариты(размеры) нашей шкалы, мы определили их выше. Percent – текущее значение жизни(в процентах) CurWidth – текущее значение жизни(в пикселях) –длина красного прямоугольника
Function Create()
Вот функция создания нашей шкалы:
Function Create:TBar(sx:Int , sy:Int, pts:Int = 0, mxpts:Int = 100)
Local TB:TBar = New TBar TB.x = sx TB.y = sy TB.CurPts = pts TB.MaxPts = mxpts ListAddLast(BarList , TB) Return TB End Function
Она принимает 4 параметра. sx и sy - координаты на экране, pts - кол-во жизни(по умолчанию-0) и также максимальное кол-во жизни mxpts (по умолчанию-100). Параметры по умолчанию очень облегчают работу и являются не обязательными к указанию, но имейте ввиду, что при создании функции, они должны находиться СТРОГО ПОСЛЕ параметров, которые объявлять обязательно. Итак, входные параметры функции инициализируют поля созданного объекта TB и затем, вновь созданный объект добавляется в список BarList, где будут храниться все созданные lifebar-ы. Наконец, вернем созданный и заполненный объект командой Return, авось пригодится позже))).
Method Draw()
Теперь рассмотрим функцию Draw(), которая будет рисовать шкалу на экране. Method Draw() SetColor(0 , 0 , 255) DrawRect(x , y , Width , Height) SetColor(255 , 0 , 0) DrawRect(x , y , CurWidth , Height) SetColor(255 , 255 , 255) DrawText(Percent + "%" , x + (Width / 2) - 10 , y + 2 ) DrawText(CurPts + "/" + MaxPts + " pts", x + Width + 10 , y + 2) End Method
В общем-то и здесь нет ничего хитрого. Сначала устанавливается синий цвет и рисуется прямоугольник (первый) нашей полоски жизни, начиная с позиции x,y с шириной и высотой ранее нами установленными. Дальше устанавливается красный цвет, и начиная с тех же координат (x и y) рисуется уже другой(второй) прямоугольник, такой же высотой, что и первый. Но длина этого прямоугольника (CurWidth) будет зависеть от текущего количества жизни (CurPts). (Я это уже говорил, но как говорят «повторенье-мать ученья»). Как раз этот параметр нам и надо рассчитать. Но об этом чуть ниже. Затем устанавливается белый цвет, и приблизительно посередине шкалы, пишется сколько процентов здоровья, относительно максимального, сейчас имеет юнит (этот параметр мы тоже рассчитаем позже). Чуть правее Bar-а пишутся через дробь текущее здоровье и максимальное (CurPts/MaxPts), это как в РПГ. Всё, отрисовка завершена!
Method Update()
Теперь самая важная часть, необходимо вычислить какой длины должен быть красный прямоугольник, а это напрямую зависит от текущего состояния здоровья юнита (CurPts). То есть рассчитать CurWidth через CurPts. А затем еще рассчитать, сколько это будет в процентах (Percent) от максимального количества жизни. Давайте начнем с процентов.
Ух, как же я не любил проценты в школе! Мало того, что на математике их проходили, так еще и на химии. Но начав с ними разбираться уже после окончания учебы тогда, когда это было нужно мне, я понял что это не просто… а очень просто. Итак, чтобы узнать сколько это будет в процентах, всего лишь надо: текущее количество чего-либо поделить на максимальное его количество и домножить на сто. В нашем случае вот так:
Percent = (CurPts / MaxPts) * 100
Ок, рассчитали. Вставим эту формулу в наш метод Update().
Теперь надо рассчитать длину нашего красного прямоугольника (CurWidth) , который символизирует текущее количество жизни.
Кто сказал, что это сигарета? А в глаз! Нет, это не сигарета, и не “косяк” какой-нибудь межгалактический, это наш с вами lifebar. На рисунке я обозначил все ключевые точки.
Итак мы хотим, чтобы максимальная длина(Width) отображала макимальное кол-во очков(MaxPts), а (CurWidth) отображала текущее кол-во очков(CurPts). То есть математически: Width = MaxPts, а CurWidth = CurPts. Из этого очевидно, что CurWidth должна так относиться к Width, как CurPts относится к MaxPts. Напомню: отношение – это частное двух чисел выраженных в одной и той же единице измерения. А вот математическая запись этой пропорции:
Из 4 параметров, 3 нам известны (CurPts, MaxPts и Width) нам осталось найти один. Проделав нехитрые перестановки, мы видим, что CurWidth рассчитывается так:
CurWidth = (Width * CurPts) / MaxPts
Занесем и эту формулу в метод Update().
Отлично. Все необходимые функции и методы у нас есть. Конечно, не мешало бы добавить еще парочку методов, типа SetXY(x,y), SetPts(pts) и других, но тут я ,думаю вы справитесь и без меня. Поздравляю, теперь можно использовать TBar в вашем проекте! Но я бы хотел еще немного задержать ваше внимание. Я решил добавить парочку методов, а заодно и протестить созданные функции. Лишний тест никогда не повредит, уж поверьте. Предлагаю ввести два тестовых метода: первый будет увеличивать текущую жизнь(CurPts) на единицу, а второй будет на единицу её уменьшать. Method AddPts()
If(CurPts < MaxPts) CurPts :+ 1 EndIf End Method
Method SubPts() If(CurPts > 0) CurPts :- 1 EndIf End Method
Думаю здесь особого описания не надо, так как очевидно, что делает каждая из функций.
Добавим в Update() парочку строк:
If (KeyDown(KEY_RIGHT))
AddPts() End If If (KeyDown(KEY_LEFT)) SubPts() EndIf
Нетрудно догадаться, что делает и этот код. Если нажать кнопку «вправо», то CurPts (текущее кол-во здоровья) будет увеличиваться, а если кнопку «влево», то уменьшаться. Теперь наконец-таки создадим 3 lifebar-а:
TBar.Create(200 , 150 )
TBar.Create(200 , 200 , 25) TBar.Create(200 , 250 , 50 , 300)
Заметьте, что благодаря параметрам «по-умолчанию», функция создания стала очень гибкой. Можно использовать как все 4 параметра, так и 3, а то и всего лишь 2.
Теперь напишем главный цикл нашей тестовой программы.
Global ScrWidth : Int = 640
Global ScrHeight : Int = 480 Graphics(ScrWidth, ScrHeight) Repeat Cls For Local TB:TBar = EachIn BarList TB.Update() TB.Draw() Next DrawText("KEY LEFT - sub points, KEY RIGHT - add points" , 150 , 450) Flip Until (KeyDown(KEY_ESCAPE) Or AppTerminate()) End
Здесь все стандартно, для приложения BMax. Устанавливаем графический режим, крутим список Lifebar-ов, апдейтим и рисуем их. Напоминаем, какие кнопки надо жать, в этой «ну ооочень сложной» программе))). Повторять это всё, пока не нажат ESC или крестик окна.
У кого не получилось, вот весь исходник программы “tutor_bar.bmx”. Давайте эксперементируйте, а я пошел в бар, меня уже друзья заждались ;)
SuperStrict
Global ScrWidth : Int = 640 Global ScrHeight : Int = 480 Global BarList:TList = CreateList() Const WIDTHBAR:Int = 200 Const HEIGHTBAR:Int = 16 Type TBar Field CurPts:Int Field MaxPts:Int Field x:Int Field y:Int Field Width:Int = WIDTHBAR Field Height:Int = HEIGHTBAR Field Percent:Int Field CurWidth:Int Function Create:TBar(sx:Int , sy:Int, pts:Int = 0, mxpts:Int = 100) Local TB:TBar = New TBar TB.x = sx TB.y = sy TB.CurPts = pts TB.MaxPts = mxpts ListAddLast(BarList , TB) Return TB End Function Method Update() If (KeyDown(KEY_RIGHT)) AddPts() End If If (KeyDown(KEY_LEFT)) SubPts() EndIf CurWidth = (Width * CurPts) / MaxPts Percent = Float(CurPts) / MaxPts * 100 End Method Method AddPts() If(CurPts < MaxPts) CurPts :+ 1 EndIf End Method Method SubPts() If(CurPts > 0) CurPts :- 1 EndIf End Method Method Draw() SetColor(0 , 0 , 255) DrawRect(x , y , Width , Height) SetColor(255 , 0 , 0) DrawRect(x , y , CurWidth , Height) SetColor(255 , 255 , 255) DrawText(Percent + "%" , x + (Width / 2) - 10 , y + 2 ) DrawText(CurPts + "/" + MaxPts + " pts", x + Width + 10 , y + 2) End Method End Type TBar.Create(200 , 150 ) TBar.Create(200 , 200 , 25) TBar.Create(200 , 250 , 50 , 200) Graphics(ScrWidth, ScrHeight) Repeat Cls For Local TB:TBar = EachIn BarList TB.Update() TB.Draw() Next DrawText("KEY LEFT - sub points, KEY RIGHT - add points" , 150 , 450) Flip Until (KeyDown(KEY_ESCAPE) Or AppTerminate()) End
Выведение
Об опечатках, багах и других пишите в комменты. Спасибо, за внимание ;)
Источник: http://blitzetc.blitzmax.ru/index.php/Лайф-бары_в_BlitzMax |