Создаём свой Crimsonland на BlitzMaxМатериал из Blitz Et Cetera
Инициализация мираВначале давайте подумаем, о чем будет наша игра. Сделаем давайте мы безумную экшн-мясо-кровища-шутер. По экрану будет бегать чел. Чел этот будет из автомата или из дробовика крошить монстров. Будут декалитры крови. Круто? ;) Ну, начнем писать код. Создадим новый файл - file => new. Создали? сохраним его в папку Crimsonland2 (предварительно создав ее ;) ). Для начала нужно задать разрешение экрана. Хранить значения мы будет в константах height, width. Для теста возьмем 1024х768. Пишем: 'ЧАСТЬ 1. Инициализация мира.
Все. Теперь игра уже представляет собой что-то. Круто? думаю ,пока нет. ;) Загрузка медиаТак. для начала сохраните у себя на компе эти картинки: Под названием 1.jpg и переместим в папку игры : CrimsonLand2/media/1.jpg . Это у нас будет текстура земли в игре. Под названием 1.png и переместим в папку игры : CrimsonLand2/media/1.png . Главный герой. Под названием blood.png и переместим в папку игры : CrimsonLand2/media/blood.png . Кровища для игры. Под названием bulletPistol.png и переместим в папку игры : CrimsonLand2/media/bulletPistol.png. Пуля. Под названием button.png и переместим в папку игры : CrimsonLand2/media/Button/button.png. Кнопка. Под названием buttondown.png и переместим в папку игры : CrimsonLand2/media/Button/buttondown.png. Когда наводим указатель на кнопку. Под названием buttonexit.png и переместим в папку игры : CrimsonLand2/media/Button/buttonexit.png. Под названием buttonexitdown.png и переместим в папку игры : CrimsonLand2/media/Button/buttonexitdown.png. Когда наводим указатель на кнопку. Под названием monster.png и переместим в папку игры : CrimsonLand2/media/monster/monster.png . Так, все медиа мы вроде загрузили. Сейчас напишем код ,который бы все это загружал... Global Fonimage = LoadImage ("Media/1.jpg") 'Загружаем текстуру для игры.
Загрузили в нашу игру мы медиа. Что дальше? Создания типов, переменных, функций, необходимых для работы игрыА дальше у нас идет создание необходимого. Global TipGame 'Для того, чтобы можно было понять, что сейчас происходит. 0- меню. 1- игра.
Global Level = 1000 'Уровень Объявляем переменные. '======== ДЛЯ УПРАВЛЕНИЯ СПИСКАМИ
Function UpdateEntities( list:TList ) Можно сказать, функция для обновления объектов в списке, а тип для работы функции... вроде... Function Dn_DrawImage (image, x#, y#, rotat#,level# ) 'Рисуем картинку через функцию.
SetBlend Alphablend Две функции для отрисовки изображений.
'======== ОПРЕДЕЛИТЬ УГОЛ МЕЖДУ ТОЧКАМИ
Function Angle!(x0!,y0!,x1!,y1!) Функция для определения угла между двумя точками. Создания типов для игрыВ этой части мы сделаем все необходимые типы для игры:
Так. Приступим сразу к коду: Type TPlayer Extends TEntity 'Объявляем тип.
Field X#,Y# 'Положение игрока. Type - объявляет тип. Extends - "привязка". В нашем случае к типу TEntity. Помните, мы такой создали? Field - знаения для типа. Function CreatePlayer:TPlayer( ) - Функция для создания объекта - игрока. TPlayer означает, к какому типу относится функция. Так же у нас для монстра, пули и крови. Только у поля значения другие и названия. ) Для того, чтобы создать игрока, достаточно ввести TPlayer.CreatePlayer (), но мы это напишем потом. Type TMonster Extends TEntity 'Объявляем тип.
Field X#,Y# 'Положение объекта. Чтобы создать монстра, надо написать: TMonster.CreateMonster(х, у)
Х, У - положение монстра. Если мы хотим, чтобы у монстров разные жизни были, или еще что-нибудь, то нужно заместо: Function CreateMonster:Tmonster(x#,y#)
Monster.life = 100 писать Function CreateMonster:Tmonster(x#,y#, life)
Monster.life = life То есть при создании нового монстра мы будем указывать еще и его количество жизней, но в моем туториале мы не будем делать этого. ))) Type TBullet Extends TEntity 'Объявляем тип.
Field X#,Y# 'Положение пули. Создаем пулю. Чтобы создать, нужно написать: TBullet.CreateBullet (x,y,поворот пули, скорость в px)
Правда, делать мы это будем в методе обновлении игрока. Type TBlood Extends TEntity 'Объявляем тип.
Field X#,Y# 'Положение пули. Типы все похожи ,не правда ли? То же самое и с кровью. Только мы добавили несколько новых значений. Значение alpham, alpha. Ang у нас будет каждый раз разное. Чтобы кровь была не похоже друг на друга, каждый раз рисуем ее в случайном повороте. Alpha - при зарисовке будет указываться, на сколько прозрачной будет кровь. Так же будет как "счетчик". Постепенно это значение будет уменьшатся на alpham, и когда alpha будет меньше или равна 0 ,то удаляем кровь. Хе. Вы почти создали основу , "каркас" вашей игры. Осталось не так уж и много... Правда посмотреть пока не на что... Создание обновления для объектовБез обновления объектов у нас игра просто не будет работать. Так давай те же напишем его! ;) Главный герой'Движение игрока.
If KeyDown(Key_W) Then Y = Y - 3 ; If animnext < MilliSecs () Then animnext=MilliSecs()+50 ; frame:+1 Так. найдите в коде обновление игрока / type TPlayer => Method Update () Там мы оставляли метку. Убираем ее и пишем вышенаписанное .))) If KeyDown(Key_W) Then Y = Y - 3 ; If animnext < MilliSecs () Then animnext=MilliSecs()+50 ; frame:+1
If KeyDown(Key_S) Then Y = Y + 3 ; If animnext < MilliSecs () Then animnext=MilliSecs()+50 ; frame:+1 Перемещение главного игрока. То есть при нажатие на клавишу (W,A,S,D) , у нас изменяются координаты. И так же при нажатии на клавигу у нас происходит смена кадров. X=X+3, где 3 - скорость. Изменить, если надо) If animnext < MilliSecs () Then animnext=MilliSecs()+50 ; frame:+1 Если animnext < с.времени , то animnext = с.время+50мс , кадр = +1 Каждые 50 мс увеличиваем кадр на 1. А всего у нас кадров 8. => если покажется 9 кадр, несуществующий, будет ошибка. Ставим ограничение: If frame=8 Then frame=0
(если кадр = 8 , то кадр = 0) Примечание: отсчет кадров начинается с нуля => 8 кадр - несуществующий. Dn_DrawAnimImage (playerImage, x, y, ang,1,frame )
Рисуем анимационную картинку - playerImage . В положении х игрока, у игрока, с поворотом ang. С прозрачностью 1 (непрозрачный) и кадром frame. Ang = Angle(x,y,MouseX(),MouseY())'Определяем поворот игрока.
Определяем через нашу функцию поворот между точкой один (главный герой) и точкой два (курсор) If shot < MilliSecs () And MouseDown (1) Then
Если shot меньше с.времени и нажата левая кнопка мыши, то:
11 потому-что начинается счет с 0 и идет до 10 - 11. Счетчикнаша переменная содержит число. (системное время) если системное время больше начего числа, то выполняем действие какое-нибудь, и увеличиваем число на с.время+мс. If KeyHit (key_f1) Then weapon=0
If KeyHit (key_f2) Then weapon=1 Если нажимаем клавишу F1, то достаем автомат, или переменная weapon = 0 Если нажимаем клавишу F2, то достаем дробовик, или переменная weapon = 1 SetRotation 0
DrawText life ,0 , 0 Рисуем жизни. ) Так. Главного героя сделали. Все. перерыв. Идите выпейте чего-нибудь, отдохните))) Отдохнули? приступаем к монстрам. МонстрыMethod Update() 'Цикл, где будут проходить все действия для монстра.
If life < 0 Then remove ; Return; If Level>300 Then Level:-5 Весь код на монстров. If life < 0 Then If Level>300 Then Level:-5; remove ; Return
Если жизни меньше 0 ,то если у нас скорость появления монстров (Level) больше 300, о уменьшаем ее. (на деле же чем меньше скорость, тем чаще они появляются.) Удалям объект (через TEntity, по этому не подствечивается). Возвращаем все. For Player:TPlayer = EachIn SPlayer
If x > player.x - 30 And x < player.x + 30 And y > player.y - 30 And y < player.y + 30 Then Смотрим на всех героев главных (а их он у нас один, но можно сделать и больше, только как быть с управлением?) Если наш монстр близко к герою : If x > player.x - 30 And x < player.x + 30 And y > player.y - 30 And y < player.y + 30 Then
То : player.life:-1
TBlood.CreateBlood (player.x,player.y,0.01) Уменьшаем жизни героя и создаем кровь в позиции героя. сейчас немного объясню, почему так пишем... Смотрите, мы в методе игрока писали просто x , а здесь player.x, так? а х у нас это координата монстра. Дело в том, что если если мы используем значения объекта прямо в его типе, то писать player. и тому подобное не надо. А если мы вызываем значения объекта из другого типа (из монстра вызываем героя), то надо писать player. и тому подобное... x=x+(3.5*Cos(ang))
y=y+(3.5*Sin(ang)) Перемещаем монстра относительно его поворота. 3.5 - скорость его. Если надо, можно увеличить или уменьшить... If animnext < MilliSecs () Then animnext=MilliSecs()+50 ; frame:+1
If frame=20 Then frame=0 Для анимации... думаю, уже не надо расписывать) ПулиMethod Update() 'Цикл, где будут проходить все действия для пули.
'Если пуля вылетает за пределы карты - удаляем.
If x<-100 Or x>=width+100 Or y>=height Or y<=-100 Then
remove Если пуля вылетает за пределы экрана - удаляем. For Monster:TMonster = EachIn SMonster
If x > monster.x - 25 And x < monster.x + 25 And y > monster.y - 25 And y < monster.y + 25 Then Обновляем монстров. Если пуля близко к монстру ,то удаляем пулю, добавляем крови. x=x+(speed*Cos(ang))
y=y+(speed*Sin(ang)) Перемещаем пулю. Dn_DrawImage bulletImage, x, y, ang,1
Рисуем. КровьMethod Update() 'Цикл, где будут проходить все действия для крови.
If alpha < 0 Then REmove ; Return Постепенно делаем кровь прозрачней. (уменьшаем alpha на alpham) Если прозрачность = 0 (т.е. совсем невидим), то удаляем Так. можете себя поздравить. Вы полностью сделали каркас вашей игры. Создание менюНи одна игра не обходится без меню. Так давайте же создадим меню и в нашей игре. While TipGame <> 1 'Цикл для меню. Пока переменная не равна 1, будет меню.
Cls Тут все просто. Рисуем две кнопки. Если курсор находится в зоне кнопки, то рисуем поверх нее другую. Если нажимаем на курсор и курсор находится над кнопкой, то делаем то-то. В нашем случае изменяем переменную TipGame 1. А цикл меню заверщается, если переменная становится не равна 0. то есть если мы нажимаем на "новая игра", то цикл меню завершается и продолжается выполнение кода... Кстати, cls - очищает экран, flip - все рисует. Цикл для игрыТак. Подошли мы к концу. TPlayer.CreatePlayer ()
UpdateEntities Sblood
UpdateEntities Sbullet Обновляем все объекты. UpdateEntities - наша функция, она была в самом начале. If time < MilliSecs () Then
time = MilliSecs () + level Так. Если time меньше системного времени, то присваиваем переменной a случайное значение от 1 до 4.
Все! нажимаем F5! Работает? если нет - код в студию ,будем выяснять. А так, все готово! Вы можете поздравить себя с созданием игры основы Crimsonland. Конечно, все аспекты типа уровней, спецэффетов и тому подобного описывать я не буду, но вы уже сделали основу. Уже легче. Автор: DanFi (ICQ: 468-909-567) |



