1 июня 2010 в 13:36
Blitz3d уроки 16. Первая 3Д игра. Итог
И вот теперь только мы готовы к тому, чтобы создать остальные части игры – это Стартовый экран и экран Гейм Овера (можно было бы и больше, конечно, но нам хватит).
Для начала введём переменную, в которой будет находится информация о том, какой экран мы сейчас показываем. Ну, назовём её GameScr, а значения она будет принимать: 0 - стартовый экран, 6 - Экран Гейм Овера, и, например 9 – экран самой игры.
Global GameScr=0
Т.е. начинаться у нас будет со стартового экрана.
Теперь изменения пойдут в главном цикле. После которых он будет выглядеть вот так:
Repeat Select GameScr Case 0 UpdateStartScreen() Case 9 UpdateGame() End Select Flip Until KeyHit(1)
Вы хотите узнать, что это за команды - Select и Case? Ну, это просто команды условия. Например, нам нужно что-то делать, в зависимости от того, какое значение принимает переменная variable. Можно написать так:
If variable=0 then
…
EndIf
If variable=1 then
…
EndIf
If variable=2 then
…
EndIf
If variable=3 then
…
EndIf
If variable=4 then
…
EndIf
А можно – так:
Select variable
Case 0
…
Case 1
…
Case 2
…
Case 3
…
Case 4
…
End Select
Достоинства последнего метода перечислять не буду
Дальше, в зависимости от того, какое значение у переменной GameScr, выполняются определённые действия… т.е. если GameScr=9 (идёт сама игра), то мы вызываем функции UpdateGame(), в которую мы поместили все наши команды игры. А если GameScr=0, мы должны показывать стартовый экран. Мы вызываем функцию UpdateStartScreen(), которую сейчас напишем.
Так, стартовый экран у нас будет выглядеть таким образом: сверху большими буквами название – “First Game”, например, а снизу две опции – Start и Quit. Всё это будем делать текстом. Для этого нам нужно загрузить шрифт (два шрифта точнее):
Global fontB=LoadFont("Verdana",72)
Global FontM=LoadFont("Verdana",32)
Эти строчки поставьте после команд инициализации графики.
Синтакс: LoadFont (название,размер) – загружает шрифт. По-моему, всё ясно…
Теперь создадим саму функцию UpdateStartScreen()
Function UpdateStartScreen() Cls SetFont FontB Color 255,100,40 Text 320,150,"First Game",True,True SetFont FontM Text 320,240, "Start",True,True Text 320,280, "Quit",True,True End Function
Так, экран сделали, теперь нам нужен курсор. Как сделать курсор? Так как наша игра никаких внешних ресурсов до сих пор не использовала, здесь тоже обойдёмся без картинок… Более того, я вообще предлагаю вместо курсора текст использовать, точнее символ «*»…
Вот как это сделать (вставить в функцию):
Color 250,200,0 Text MouseX(),MouseY(),"*",True,True
Получился жёлтый курсор. Однако кликание на текст ничего не даёт... Нам нужна проверка – не находится ли курсор над надписью Start или Quit.
Function UpdateStartScreen() Cls SetFont FontB Color 255,100,40 Text 320,150,"First Game",True,True SetFont FontM Text 320,240, "Start",True,True Text 320,280, "Quit",True,True End Function
Всё очень просто (хотя это и 2Д … Здесь мы используем команды RectsOverlap – она проверяет, не пересекаются ли заданные прямоугольники.
Синтакс: RectsOverlap (X коорд. прямоугольника 1, Y коорд. прямоугольника 1, Ширина прямоугольника 1, Высота прямоугольника 1, X коорд. прямоугольника 2, Y коорд. прямоугольника 2, Ширина прямоугольника 2, Высота прямоугольника 2)
X и Y координаты – левого верхнего угла прямоугольника.
tShift=0 If RectsOverlap(MouseX(),MouseY(),1,1,320-50,240-12,100,32) tShift=1 If RectsOverlap(MouseX(),MouseY(),1,1,320-50,280-12,100,32) tShift=2
Эти команды нужно вставить в начало функции.
Теперь мы у нас есть курсор и мы знаем, когда он находится над “Start” и ”Quit”. Теперь надо сделать так, чтобы цвет текста менялся, когда курсор будет наведён на него, так что немного перепишем строки:
If tShift=1 Color 0,255,0 Else Color 255,0,0 Text 320,240, "Start",True,True If tShift=2 Color 0,255,0 Else Color 255,0,0 Text 320,280, "Quit",True,True
Так, интерактивность (хоть и примитивная, но хотя бы что-то присутствует, осталось только заставить это работать. Для этого нужно поставить в конец функции вот эти строчки:
If MouseHit(1) Select tShift Case 1 CreatePlayer() CreateWalls(29) CreateTarget() CreateEnv() Collisions TypePlayer,TypeWalls,2,2 Collisions TypePlayer,TypeTarget,2,2 GameScr=9 Case 2 End End Select EndIf
Здесь у нас идёт проверка на нажатие левой кнопки. Затем, если курсор находится над Start`ом, происходит инициализация (мы её из начала кода вырезали), и меняется переменная GameScr, так, что со следующим кадром покажется уже не стартовый экран, а сама игра. Ну, а если курсор над кнопкой Quit, то программа просто выходит…
Дальше, теперь нам надо сделать так, чтобы при проигрыше или нажатии кнопки Esc, игра выходила на стартовый экран. Но перед этим, показывала экран ГеймОвера. Для этого внесём некоторые изменения в функцию UpdateGame():
Во первых сменим строчку, где игра заканчивается при столкновении с кубиком
If EntityCollided (Player,TypeWalls) End на эту: If EntityCollided (Player,TypeWalls) Or KeyDown(1) GameScr= 6 FreeGame() EndIf
Теперь игра будет очищаться и выходить на экран геймовера. И теперь у нас будет только один способ (без нажатия Ctrl+Alt+Del выйти из игры – нажать Quit или Esc на стартовом экране. Поэтому немного поменяем условие в главном цикле:
Until KeyHit(1) …на : Until Quit
Quit – будет нашей переменной, которая будет показывать, что на этом шаге игра выходит…
Сначала создадим её (в самом начале программы есь-сно, где мы задаём остальные глобальные переменные):
Global Quit=False
False будет обозначать, что, типа, игра не выходит ещё…
И сделаем некоторые изменения в функции UpdateStartScreen()
Case 2 End поменяем на: Case 2 Quit=True И добавим ещё условие: If KeyDown(1) Quit=True
Так, вот уже почти всё, осталось только сделать сам экран Геймовера, о котором мы тут столько говорим
В главный цикл вставляем строчки Select`овского условия:
Case 6 Cls Flip Cls SetFont fontB Color 255,0,0 Text 320,240,"Game Over",True,True Flip Delay 1000 FlushKeys GameScr = 0
Здесь у нас описан экран Геймовера: Что здесь и как – объясняю по порядку:
Сначала очищаем первую поверхность, флипим, очищаем вторую, устанавливаем шрифт, цвет и пишем Гейм Овер, опять флипим, ждём одну секунду (1000 миллисекунд) командой FlushKeys очищаем список всех нажатых клавиш (если была нажата Esc игра выйдет, дойдя до условия в функции UpdateStartScreen()), и меняем переменную GameScr на 0… вот экран Гейм Овера и готов….
На этом можно и закончить – мы сделали хоть и примитивную, но всё-таки полноценную игру!!! Практически можно поздравить вас, что вы всё-таки заставили себя дочитать это до конца, ну и себя самого, за то что этот кошмар под названием «писать туториал» позади. Я постарался показать (хотя бы мельком) все аспекты программирования игры. Кстати, они не очень сильно отличаются от более «серьёзных» проектов, в которых просто больше элементов. Так что вы теперь готовы к писанию своих игрушек!!!
Вот весь код нашей получившейся в итоге игры:
SeedRnd MilliSecs()
Global GameScr=0
Global Quit=False
Type Walls
Field model
End Type
Const TypePlayer=1,TypeWalls=2,TypeTarget=3
Global Speed#=.1,Score=0
Global Player
Global Target
Global cam
Global lit
Graphics3D 640,480,16,1
SetBuffer BackBuffer()
Global fontB=LoadFont("Verdana",72)
Global FontM=LoadFont("Verdana",32)
;*******************
;Main Cycle
;*******************
Repeat
Select GameScr
Case 0
UpdateStartScreen()
Case 6
Cls
Flip
Cls
SetFont fontB
Color 255,0,0
Text 320,240,"Game Over",True,True
Flip
Delay 1000
FlushKeys
GameScr = 0
Case 9
UpdateGame()
End Select
Flip
Until Quit
End
;*******************
;Functions
;*******************
Function CreateWalls(tn)
For i=0 To tn
w.Walls = New Walls
w\model=CreateCube()
Repeat
PositionEntity w\model,Rnd(-40,40),0,Rnd(-40,40)
Until Abs(EntityX(w\model))>10 Or Abs(EntityZ(w\model))>10
EntityType w\model, TypeWalls
EntityColor w\model,255,0,0
Next
w.Walls = New Walls
w\model=CreateCube()
EntityColor w\model,100,20,0
EntityType w\model,TypeWalls
PositionEntity w\model,-50,0,0
FitMesh w\model,-1,-1,-50,2,3,100
w.Walls = New Walls
w\model=CreateCube()
EntityColor w\model,100,20,0
EntityType w\model,TypeWalls
PositionEntity w\model,50,0,0
FitMesh w\model,-1,-1,-50,2,3,100
w.Walls = New Walls
w\model=CreateCube()
EntityColor w\model,100,20,0
EntityType w\model,TypeWalls
PositionEntity w\model,0,0,-50
FitMesh w\model,-50,-1,-1,100,3,2
w.Walls = New Walls
w\model=CreateCube()
EntityColor w\model,100,20,0
EntityType w\model,TypeWalls
PositionEntity w\model,0,0,50
FitMesh w\model,-50,-1,-1,100,3,2
End Function
Function PositionTarget()
Repeat
inter=False
PositionEntity Target,Rnd(-40,40),0,Rnd(-40,40)
For w.Walls = Each Walls
If MeshesIntersect(Target, w\model) inter=True
Next
Until inter=False
End Function
Function CreatePlayer()
Player=CreateSphere()
Plac=CreateCone(8)
RotateMesh Plac,-90,0,0
ScaleMesh Plac,1,1,1.2
PositionMesh Plac,0,0,-1.5
AddMesh Plac,Player
EntityType Player, TypePlayer
EntityColor Player,0,255,0
FreeEntity Plac
End Function
Function CreateTarget()
Target=CreateCylinder()
PositionTarget()
EntityColor Target,255,215,0
EntityType Target,TypeTarget
End Function
Function CreateEnv()
cam=CreateCamera()
PositionEntity cam,0,40,0
TurnEntity cam,90,0,0
lit=CreateLight()
TurnEntity lit,70,70,0
End Function
Function UpdateGame()
MoveEntity Player,0,0,Speed#
If KeyDown(203) TurnEntity Player,0,3,0
If KeyDown(205) TurnEntity Player,0,-3,0
PointEntity cam,Player
If EntityCollided (Player,TypeTarget)
PositionTarget()
UpdateWorld
Score=Score+1
Speed=Speed+.01
EndIf
If EntityCollided (Player,TypeWalls) Or KeyDown(1)
GameScr=6
FreeGame()
EndIf
UpdateWorld
RenderWorld
Color 255,215,0
Text 320,10,"Score : "+Score,True,True
End Function
Function UpdateStartScreen()
tShift=0
If RectsOverlap(MouseX(),MouseY(),2,2,320-50,240-12,100,32) tShift=1
If RectsOverlap(MouseX(),MouseY(),2,2,320-50,280-12,100,32) tShift=2
Cls
SetFont FontB
Color 255,0,0
Text 320,150,"First Game",True,True
SetFont FontM
If tShift=1 Color 0,255,0 Else Color 255,0,0
Text 320,240, "Start",True,True
If tShift=2 Color 0,255,0 Else Color 255,0,0
Text 320,280, "Quit",True,True
Color 250,200,0
Text MouseX(),MouseY(),"*",True,True
If MouseHit(1)
Select tShift
Case 1
CreatePlayer()
CreateWalls(29)
CreateTarget()
CreateEnv()
Collisions TypePlayer,TypeWalls,2,2
Collisions TypePlayer,TypeTarget,2,2
GameScr=9
Case 2
Quit=True
End Select
EndIf
If KeyHit(1) Quit=True
End Function
Function FreeGame()
ClearCollisions
FreeEntity cam
FreeEntity lit
FreeEntity Player
FreeEntity Target
For w.Walls=Each Walls
FreeEntity w\model
Delete w
Next
Speed#=.1
Score=0
End Function
комментарии отсутствуют
авторизуйтесь