Воскресенье, 05.05.2024, 23:47
Personal dimanche13 site
Главная | Регистрация | Вход Приветствую Вас Гость | RSS
Категории каталога
Мои статьи [22]
BlitzMax [17]
раздел содержит статьи относящиеся к языку программирования BlitzMax
SDL [9]
раздел содержит статьи на тему SDL
Code::Blocks [3]
в этом разделе рассказывается как прикрутить движок к интегрированной среде разработки(IDE) Code::Blocks
Форма входа
Поиск
Друзья сайта
Главная » Статьи » BlitzMax

Тайловая игра на BlitzMax, часть 1(2)

Бонусы

Ладно, худо-бедно, уровень нарисован , но какой-то он однообразный, давайте что-ли добавим сюда еще парочку элементов. Ну какая игра, скажите мне, будет без бонусов? Всевозможных монеток, кристаллов, и т. д. Предлагаю поместить их и на нашем уровне. Для этого напишем еще один тип TBonus

Type TBonus
    Field x:Int
    Field y:Int
    Field width:Int
    Field height:Int

    Field points:Int
    Field miny:Int
    Field maxy:Int
    Field diry:Int
    Field speed:Int
    Field AnimDelay:Int
  End type

Вообще-то (у меня) и бонус тоже будет прямоугольником, только желтого цвета (при хорошем воображении можно представить, что это слиток золота). Он меньше, чем тайл, естественно. Его размеры будут: 16х6. И помните - бонус должен находиться только в проходимом тайле, а иначе как его возьмет игрок? Посмотрите повнимательнее на свойства (переменные) нашего нового типа. Первые 4 понятны и так. А про остальные надо рассказать отдельно:

  • points - это очки, которые получит игрок при подборе(?) этого бонуса,
  • miny и maxy - наш бонус не просто будет висеть в воздухе, а будет раскачиваться вверх-вниз, т.е . двигаться по оси Y, как это часто бывает в играх. Так вот эти переменные указывают амплитуду раскачивания, смотрите рисунок:

  • Diry - это направление движения при раскачивании бонуса <-1> означает, что бонус движется вверх, а <+1> - соответственно, вниз. (При Diry = 0 бонус двигаться не будет.)
  • Speed - скорость, с которой двигается бонус, то есть на сколько пикселей вверх/вниз он переместится.
  • AnimDelay - это задержка, с которой раскачивается бонус. Регулируя эту переменную, можно регулировать скорость раскачивания.

Да, кстати , не забудем создать список для хранения наших бонусов:

Global BonusList:TList = CreateList()       ' вот так

Теперь перейдем непосредственно к функции Create для типа TBonus. Эта функция будет создавать бонус на указанном тайле, и заполнит все поля типа(которые я тока что описал) нужной информацией, надо только указать координаты на тайловой карте и очки за этот бонус:

Function Create(sx:Int,sy:Int,pts:Int)
  Local TB : TBonus = New TBonus
    TB.Width = 6
    TB.Height = 16
    TB.x = sx * TILESIZE + ((TILESIZE - TB.width) / 2)
    TB.y = sy * TILESIZE + ((TILESIZE - TB.height) / 2)
    TB.points = pts
    TB.miny = TB.y - 4
    TB.maxy = TB.y + TB.Height + 4
    TB.speed = 1
    TB.diry = -1
    TB.AnimDelay = 5
  ListAddLast(BonusList ,TB)
End Function
 
Вот картинка, которая поможет вам в понимании вышеизложенной функции:
Из кода и приведенной картинки все становится очевидным и доходчивым, переводим тайловые координаты в экранные, помещаем бонус в центре тайла и раскачиваем его на 4 пикселя вверх и 4 пикселя вниз, скорость (speed) = 1, начальное направление вверх (diry = -1). Да, чуть не забыл, при достижении бонусом miny или maxy, мы должны поменять направление раскачивания, учтем это при написании нашего кода. А вот и он:
 
Method Update()
    If(Animdelay < 0)

      If ( miny > (y) Or maxy < (y + height - 1) )
        diry = -diry
      End If

      y = y + speed * diry

      AnimDelay = 5
    End If

    AnimDelay :- 1

  End Method

  Method Draw()
    SetColor(255 , 255 , 0)
    DrawRect(x,y,Width,Height)
  End Method

В методе ничего примечательного нет. Там устанавливается желтый цвет и рисуется прямоугольник, то есть наш воображаемый бонус. А метод рассмотрим поподробнее. Здесь как раз и будет происходить раскачивание бонуса , а точнее в строке

y = y + speed * diry

новое положение по оси <у> вычисляется как прибавление к старому значению и скорости (speed) домноженной на направление (diry), как я говорил раньше, diry может принимать только 2 значения - <-1> и <+1>, а потому произведение дает разные ПО ЗНАКУ значения speed, что в свою очередь влияет на то, будет ли скорость вычитаться или прибавляться к текущей координате. Например: текущая позиция по y = 5, направление - вверх , то есть diry = -1 и скорость (speed) =1, тогда новое значение у:

y = 5 + 1 * (-1) = 5 - 1 = 4

если diry = +1 ,то есть направление вниз:

y = 5 + 1 * 1 = 5 + 1 = 6

вот так diry влияет на вычисление новой позиции нашего бонуса. Нет, мы ,конечно, могли бы сделать и так: если двигаемся вверх, то вычитать скорость, а если вниз ,то прибавлять.

If diry = 1
  y = y + speed
else if diry = -1
  y = y - speed
end if

Но этот способ мне кажется более громоздким, по сравнению с изяществом первого. Впрочем, вы можете использовать любой. Теперь надо ограничить наши движения maxy и miny. Первое что приходит в голову это сделать так:

  If (y =< miny)           ' если достигли верха
    diry = 1            ' направить вниз
  end if

  if (y + height >= maxy)     ' если достигли низа
    diry = -1                   ' направить вверх
  end if

Но я сделаю чуть иначе:

  If ( miny >= (y) Or maxy =< (y + height) )
    diry = -diry
  End If

Строка diry = -diry означает изменить знак diry, то есть если diry был -1, то -(-1) = +1, а если diry = +1 ,то -(+1) = -1. Говоря по-другому ,что важно для нас - эта строка, меняет направление движения на противоположное.

Я привел оба эти варианта для того ,чтобы показать, что одну задачу можно решить двумя разными способами, тремя и даже больше. Так что не бывает правильного и не правильного кода, хорошего или плохого. Бывает код ,который работает, то есть выполняет свою прямую задачу, и код ,который не работает! Главное ,чтобы вы сами понимали, то что пишете. А уж потом, когда заматереете в программинге, можно модернизировать и оптимизировать свой код.

Вот в общем-то и всё. А нет, не всё! У нас ведь еще введена задержка анимации (AnimDelay). Не каждый вызов метода Update() приводит к перемещению нашего бонуса, а лишь тот, когда AnimDelay < 0 . Ну а если больше нуля, то от задержки отнимается единица, через пять циклов условие соблюдается и движение бонуса происходит. Нехитрый способ задержки, думаю вы его переделаете со временем. Итак, у нас есть функция создания бонусов (Create), метод качания (Update) и метод рисования (Draw). Так чего же мы ждем? Давайте разместим наши бонусы на карте и нарисуем их!

Для инициализации их на карте я создал отдельную функцию:

Function Init_All_Bonuses()

  TBonus.Create(15 , 1 , 100)
  Tbonus.Create(7 , 4 , 100)
  Tbonus.Create(1 , 1 , 25)
  Tbonus.Create(3 , 8 , 25)
  Tbonus.Create(4 , 8 , 25)
  Tbonus.Create(5 , 8 , 25)
  Tbonus.Create(9 , 7 , 10)
  Tbonus.Create(4 , 6 , 10)
  Tbonus.Create(9 , 2 , 10)
  Tbonus.Create(14 , 7 , 10)
  Tbonus.Create(17 , 6 , 10)
  Tbonus.Create(17 , 4 , 10)
  Tbonus.Create(18 , 4 , 10)
  Tbonus.Create(3 , 3 , 10)

End Function

Здесь 14 бонусов, 2 по 100 очков, 4 по 25 и остальные по 10 очков. Ну теперь осталось отобразить их все на экране. Вы тоже можете создать для этого отдельную функцию, ну а я решил впихнуть всё это в Tlevel.Render(), сразу после рисования тайлов:

For Local CurBonus:Tbonus= EachIn BonusList
  CurBonus.Update()
  CurBonus.Draw()
Next

Запускаем и любуемся. Если не получилось, смотрите исходник:

SuperStrict
 
Global ScrWidth : Int  = 640
Global ScrHeight : Int = 480

Global TileList:TList = CreateList()
Global BonusList:TList = CreateList()

Const TILESIZE:Int   = 32

Type TTile
  Field x:Int
  Field y:Int

  Field xTBle:Int
  Field yTBle:Int
 
  Field Width:Byte
  Field Height:Byte

  Field Walkable:Byte
 
  Function Create(sx:Int, sy:Int, WB:Byte)
    Local TT:TTile = New TTile
      TT.width  = TiLESIZE    
      TT.height = TiLESIZE    
      TT.xTBle = sx      
      TT.yTBle = sy            
      TT.x = TT.xTBle * TT.width    
      TT.y = TT.yTBle * TT.height  
      TT.Walkable = WB        

    ListAddLast(TileList , TT)  
  End Function  

  Method update()
    If    walkable       'walkable
      SetColor(255 , 0 , 0)  'red
    Else             'NOT walkable
      SetColor(0 , 255 , 0)   'green
    End If  
  End Method      

  Method Draw()
        DrawRect(x,y,Width,Height)  
  End Method

End Type

Type TLevel
  Field Width : Byte
  Field Height : Byte

  Field Map:Int[,]
 
  Function Create:TLevel(MyMap:Int[],map_width:Int,map_height:Int)
      Local TM : TLevel = New TLevel  
    TM.Width  = map_width
    TM.Height = map_height

    TM.map = New Int [TM.Width, TM.Height]
    TM.load(myMap)
   
    Return TM              
  End Function  
 
  Method Load(arrMap:Int[])
    For Local i:Int = 0 Until Height
      For Local j:Int = 0 Until Width
        Map[j , i] = arrMap[j + (i * Width)]
        If Map[j , i]
             TTile.Create(j , i , True)
        Else
             TTile.Create(j , i , False)
        End If
      Next
    Next    
  End Method  

  Method Render()
   
    For Local CurTile:TTile = EachIn TileList
      CurTile.Update()
      CurTile.Draw()
    Next  
   
    For Local CurBonus:TBonus= EachIn BonusList
      CurBonus.Update()
      CurBonus.Draw()
    Next      
   
  End Method
 
End Type

Type TBonus
  Field x:Int
  Field y:Int
  Field width:Int
  Field height:Int
 
  Field points:Int
  Field miny:Int
  Field maxy:Int
  Field diry:Int
  Field speed:Int
  Field AnimDelay:Int
 
  Function Create(sx:Int,sy:Int,pts:Int)
    Local TB : TBonus = New TBonus
      TB.Width = 6
      TB.Height = 16
      TB.x = sx * TiLESIZE + ((TiLESIZE - TB.width) / 2)  'center it
      TB.y = sy * TiLESIZE + ((TiLESIZE - TB.height) / 2) 'center it
      TB.points = pts
      TB.miny = TB.y - 4
      TB.maxy = TB.y + TB.Height + 4
      TB.diry = -1
      TB.speed = 1
      TB.AnimDelay = 5
    ListAddLast(BonusList ,TB)
  End Function  
 
  Method Update()
    If(Animdelay < 0)

         If ( miny > (y) Or maxy < (y + height - 1) )
             diry = -diry
         End If
   
         y = y + speed * diry
   
         AnimDelay = 5

    End If  
   
    AnimDelay :- 1
   
  End Method
 
  Method Draw()
    SetColor(255 , 255 , 0)
    DrawRect(x,y,Width,Height)
  End Method  
 
End Type

Global LevMap:Int[]=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,..
                     1,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,1,..
                     1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,..
                     1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,..
                     1,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,..
                     1,0,0,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,..
                     1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,..
                     1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,..
                     1,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,..
                     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]


Global MyLevel : TLevel = New TLevel.Create(LevMap , 20 , 10)

Function Init_All_Bonuses()
  TBonus.Create(1 , 1 , 25)
  TBonus.Create(3 , 8 , 25)
  TBonus.Create(4 , 8 , 25)
  TBonus.Create(5 , 8 , 25)
  TBonus.Create(15 , 1 , 100)
  TBonus.Create(7 , 4 , 100)
  TBonus.Create(9 , 7 , 10)
  TBonus.Create(4 , 6 , 10)
  TBonus.Create(9 , 2 , 10)
  TBonus.Create(14 , 7 , 10)
  TBonus.Create(17 , 6 , 10)
  TBonus.Create(17 , 4 , 10)
  TBonus.Create(18 , 4 , 10)
  TBonus.Create(3 , 3 , 10)
End Function  

'----------------------------- main loop -----------------------------
Graphics(ScrWidth, ScrHeight)

Init_All_Bonuses()

Repeat
   Cls

    MyLevel.Render()
   
   Flip
Until KeyDown(KEY_ESCAPE) Or AppTerminate()

End
Категория: BlitzMax | Добавил: dimanche (24.05.2008) | Автор: Dmitriy
Просмотров: 907 | Комментарии: 2 | Рейтинг: 0.0/0 |
Всего комментариев: 1
1 Alex  
0
Т.е. в карте для этих бонусов нужно создавать отдельный раздел? Как и для других объектов? Хм... А я думал, что они считываются как значения массива карты, правда, при этом они получатся однообразными.. Т.е. фон и неподвижные тайлы можно грузить при помощи двумерного массива карты, а подвижные тайлы и всякого рода бонусы, а также врагов грузить из отдельных частей карты?

Имя *:
Email *:
Код *:
Copyright MyCorp © 2024