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
комментарии отсутствуют
авторизуйтесь