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

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

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


Зумминг
Видели движок Матвея к игре про злобных колобков? Просто офигительный эффект приближения и удаления камеры, не правда ли? Признаюсь, меня он очень впечатлил, и я захотел сделать такой же. Сейчас мы с вами займемся его реализацией. Но для начала, уже по традиции, я вам расскажу какие функции в Бмаксе отвечают за увеличение/уменьшение масштаба. SetScale(Xscale,Yscale) – это установка коэффициента масштаба, и GetScale(Xscale, Yscale) - чтение текущего коэффициента масштаба. Как вы могли уже заметить, у этих функций 2 параметра. Первый отвечает за масштабирование по оси Х, а второй по оси У. Это значит, что мы можем масштабировать объект непропорционально, то есть без соблюдения пропорций, на каждую ось - свой коффициент. Эти коэффициенты имеют тип float, то есть - это вещественные числа. При коэффициенте 1.0 не будет ни увеличения, ни уменьшения масштаба, при 2.0 будет увеличение в 2 раза, при 0.5 уменьшение в 2 раза (0.5 = ½). Проведем еще один маленький тестик. Как говорится “лучше 1 раз увидеть, чем 100 раз услышать” : SuperStrict

SuperStrict
 
'========== Параметры графики ===========
Global ScrWidth:Int  = 640
Global ScrHeight:Int = 480
'===================================

AppTitle = "Test 004"

'       инициализация графики
        Graphics(ScrWidth, ScrHeight)  

                Cls() 
      
                        SetScale(1.0 , 1.0)'один к одному
                        SetColor(0,0,255)
                        DrawRect(50,140,100,100)

                        SetScale(0.5 , 0.5)' в два раза меньше
                        SetColor(255,0,0)
                        DrawRect(250,140,100,100)

                        SetScale(2.0 , 2.0)' в два раза больше
                        SetColor(0,255,0)
                        DrawRect(400,140,100,100)

                Flip()
              
        WaitKey()

End

Как видите (по коду программы), все три квадрата имеют одинаковые размеры - 100 на 100. Но в связи с тем, что перед их отрисовкой стоят функции масштабирования(SetScale), они выводятся разного размера. Один (красный) в 2 раза меньше – 0.5, а другой (зеленый) в 2 раза больше 2.0. Поэкспериментируйте с кодом, задавая разный масштаб квадратов для каждой оси.

Ну теперь все вроде понятно с зумингом, нам надо просто создать переменную масштаба Zoom:Float , которая будет хранить текущий масштаб карты, и прицепить изменение этой переменной на кнопки. Вот так:
 
If( KeyDown(KEY_A) ) Then Zoom :+ 0.01
If( KeyDown(KEY_Z) ) Then Zoom :- 0.01

а перед отрисовкой всех объектов впиндюрим SetScale( Zoom , Zoom ). Да, это все так. Но не забывайте, что при введении масштаба, мы вводим как бы третье измерение для нашей карты, а это надо учитывать. Ведь чем меньше масштаб карты тем плотнее тайлы друг к другу, соответственно их координаты подвержены влиянию коэффициента зума. Проходим по всем функциям отрисовки объектов и домножаем x и y координаты на наш коэффициент масштаба, вот так: x * Zoom, y * Zoom

Весь листинг программы здесь:
 
SuperStrict

'========== Параметры графики ===========
Global ScrWidth:Int  = 640
Global ScrHeight:Int = 480
'===================================

Global CameraX:Int = 0
Global CameraY:Int = 0
Global Zoom:Float = 1.0

Global ALLGameObjList : TList = CreateList()

Const TILESIZE:Int       = 32

Type TBase
        Field x:Int
        Field y:Int
        Field Width:Byte
        Field Height:Byte
      
        Method update() Abstract
        Method draw()   Abstract
End Type      

Type TTile Extends TBase
      
        Field xTile:Int
        Field yTile:Int
        Field Walkable:Byte
      
        Function Create(sx:Int, sy:Int, WB:Byte)
                Local TT:TTile = New TTile
                        TT.width  = TiLESIZE          
                        TT.height = TiLESIZE          
                        TT.xTile = sx                         
                        TT.yTile = sy                 
                        TT.x = TT.xTile * TT.width            
                        TT.y = TT.yTile * TT.height           
                        TT.Walkable = WB                              

                ListAddLast(ALLGameObjList , TT)      
        End Function  

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

        Method Draw()
            DrawRect(x * Zoom, y * Zoom, 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 CurObj:TBase = EachIn ALLGameObjList
                        CurObj.Update()
                        CurObj.Draw()
                Next  
              
        End Method
      
End Type

Type TBonus Extends TBase

        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(ALLGameObjList , TB)
        End Function  
      
        Method Update()
                If(Animdelay < 0)

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

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

Type TMovingX Extends TBase
      
        Field mindir:Int
        Field maxdir:Int

        Field dirx:Int
        Field speed:Int
      
        Function Create(xt:Int , yt:Int , mn:Int , mx:Int , d:Int)
                Local TMX:TMovingX = New TMovingX

                        TMX.x = xt * TILESIZE
                        TMX.y = yt * TILESIZE

                        TMX.width = TILESIZE
                        TMX.height = TILESIZE

                        TMX.speed = 1

                        TMX.dirx = d

                        TMX.mindir = (mn + xt) * TILESIZE      
                        TMX.maxdir = (mx + xt + 1) * TILESIZE 

                ListAddLast(ALLGameObjList , TMX)      
        End Function

        Method Update()
              
                If( mindir >= x Or maxdir <= (x + width) )    
                                dirx = - dirx
                EndIf
              
                        x :+ speed * dirx
      
        End Method    
      
        Method Draw()  
                SetColor(128 , 128 , 128)        ' gray
                DrawRect(x * Zoom, y * Zoom, Width, Height)    
                SetColor(255 , 255 , 255)        ' white line
                DrawLine(x * Zoom, y * Zoom, (x * Zoom) + width - 1, y * Zoom)
        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  

TMovingX.Create(13 , 3 , - 2 , 5 , 1)


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

Init_All_Bonuses()

Repeat
         Cls

                If( KeyDown(KEY_LEFT) ) Then CameraX :- 5
                If( KeyDown(KEY_RIGHT) ) Then CameraX :+ 5
                If( KeyDown(KEY_UP) ) Then CameraY :- 5
                If( KeyDown(KEY_DOWN) ) Then CameraY :+ 5

                If( KeyDown(KEY_A) ) Then Zoom :+ 0.01
                If( KeyDown(KEY_Z) ) Then Zoom :- 0.01

                SetOrigin( -CameraX , -CameraY )
                SetScale( Zoom , Zoom )
                              
                MyLevel.Render()
              
         Flip
Until KeyDown(KEY_ESCAPE) Or AppTerminate()

End

Здорово! Кстати заметьте, что как только коэффициент масштаба станет отрицательным, то карта снова начнет увеличиваться, но уже будет перевернута верхом вниз и правая сторона поменяется с левой. Это такая фича функции SetScale(). Если вы загрузите картинку и перед ее отображением напишите SetScale(-1.0 , 1.0) , то картинка нарисуется отраженной (инвертированной) по оси Х, если напишем SetScale(1.0 , -1.0) , то отразится по У. В нашем же случае, карта отразится сразу по обеим осям, так как мы изменяем их пропорционально и синхронно.


Выведение

Ну вот в общем-то и все на сегодня. Вы теперь знаете, что такое ViewPort и как им манипулировать в своих целях. Знаете как осуществляется скроллинг и зумминг карты. На основе этих данных вы смело можете писать уже что-то очень похожее на игру. Надеюсь я не сильно загрузил вашу голову, и в ней еще есть место для следующих туторов. ;) А ваше домашнее задание - создать карту побольше нашей, которую мы использовали для экспериментов, и ввести лимит на скроллинг и зуминг карты по ее размерам. Удачи! У вас все получится – я уверен.

Спасибо вам за внимание. И как всегда, обо всех ошибках в тексте и коде, сообщайте мне на почтовый ящик. Комменты тоже приветствуются. Чао.



Источник: http://blitzetc.blitzmax.ru/index.php/Тайловая_игра_на_BlitzMax%2C_часть_2
Категория: BlitzMax | Добавил: dimanche (24.05.2008) | Автор: Dmitriy
Просмотров: 1263 | Комментарии: 1 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Имя *:
Email *:
Код *:
Copyright MyCorp © 2024