|
DWD-009 |
|
Меню Сайта |
 |
|
 |
|
 |
__________________
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
____________________
|
 |
|
 |
|
 |
|
 |
_______________
|
 |
|
 |
|
 |
|
 |
|
 |
_______________________
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
|
 |
___________________
|
 |
|
 |
_________________
|
 |
|
 |
|
 |
|
 |
|
 |
|
|
 |
ToP Sites
http://mo3del.ru/
http://mir3d.3dn.ru/
http://sw-in.narod.ru/
|
Создание Kосмической Aркады---
Урок 7. Создание космической аркады
7.1. Игровая сцена и объекты.
Если вы не видели одну из первых игр Джона Кармака (John Carmack) (создателя легендарных игр - Wolfenstein 3D, Doom и многих других) Slordax The Unknown Enemy то самое время с ней ознакомиться, так как мы постараемся создать нечто подобное. Суть игры Slordax в следующем: мы управляем маленьким космическим корабликом, который несется сквозь пространство и своей огневой мощью вселяет страх в пытающиеся ему противостоять вражеские летающие объекты Создавая такую игру мы закрепим пройденный материал, так как:
1. Создадим модели кораблей
2. Вспомним управление объектами при помощи клавиатуры
3. Повторим тему коллизий (столкновений спрайтов и объектов типа mesh)
4. Затронем создание спрайтовых эффектов
5. Научимся вести список лучших результатов игры и т.д.
Что же из себя будет представлять наша игровая сцена ? Игровое поле будет состоять из двух объектов типа plane которые будут двигаться в одном направлении, но с разными скоростями, имитируя ближние и удаленные звезды. Текстуру для этих целей можно создать в стандартном редакторе Paint в течении 30 секунд. Если у вас не возникло такого желания, то можете воспользоваться этой:

Что касается объектов, то нас их будет 4 вида: наш корабль, уверенно рассекающий космические просторы, вражеские корабли (по сути один и тот же корабль, только в большом количестве), объект - выстрел нашего корабля (их тоже может быть несколько на экране) и объект - взрыв (нашего и вражеского корабля).
Логика нашей игры совершенно бесхитростна: если во вражеский корабль попадает одна из выпущенных нами ракет, то он взрывается и распадается на мелкие части. Реально мы, конечно, не будем дробить модель вражеского корабля на частицы - мы просто уберем его с экрана, а в месте его пребывания создадим эффект взрыва. Если же враждебный нам корабль зацепит наш своим корпусом, то погибают оба. У нас в запасе будет 3 жизни, посему гибель одного - двух наших кораблей будет не критична, главное сохранить хотя бы один, уничтожив при этом всех врагов!
Итак опишем типы, отвечающие за информацию об объектах нашей стрелялки:
; Тип вражеского корабля
Type EnemyShip
Field Ship
Field ShipX#
Field ShipZ#
Field ShipSpeed#
End Type
; Тип взрыва после столкновения или попадания
Type Frag
Field alpha#,entity
End Type
; Тип ракеты (выстрел нашего корабля)
Type Bullet
Field rot#,sprite,time_out
End Type |
Тип вражеского корабля состоит из поля в котором содержится ссылка на модель, две координаты по осям X и Z (расположение в текущий момент времени) и скорость.
Тип взрыва характеризуется двумя полями: ссылкой на спрайт, визуализирующий одну из частиц взрыва и величиной прозрачности этой частицы, которая меняется со временем.
Тип ракеты определяется углом поворота спрайта, ссылкой на спрайт, и временем жизни ракеты в игре.
7.2. Создадим модели кораблей.
К этому уроку у Вас уже должен был накопиться порядочный опыт общения с редактором моделей Milkshape3D. Наверняка после нашего ознакомительного занятия с его возможностями не раз пробовали создать какой-нибудь свой анимированный объект или скачивали с Интернета готовые модели и редактировали их в этой программе.
Поэтому процесс создания примитивных модели кораблей не должно вызвать у Вас затруднений.
Давайте для начала создадим вражеский корабль. Откройте редактор Milkshape3D и используя инструменты: сфера, цилиндр и коробка (box) смоделируйте нечто подобное рисунку приведенному ниже:

Из рисунка видно, что центральной частью нашего простенького кораблика является сфера, из которой в разные стороны торчат пять цилиндров внешние концы которых соединены планками (объект box). Не забудьте внедрить один объект типа Joint (на рисунке - синим цветом) и привязать его ко всем точкам нашей модели, для того чтоб Milkshape3D правильно экспортировал его в формат .md2. На Ваше усмотрение вы можете экспортировать модель в .Х, .3ds или .b3d формат так как модель все равно не будет содержать никакой анимации. Мы же все таки остановимся на .md2., для чего в папку, где будет содержаться итоговая модель запишем файл типа .qc, с описанием только одной последовательности:
$sequence stop 1 1
Таким образом, модель лишена какой-либо анимации и будет двигаться только повинуясь алгоритму нашей программы. Вы можете скачать модель и файл ms3d - для вражеского корабля. Если у Вас есть огромное желание, то для разминки создайте текстуру для этой модели и обтяните ею корабль.
Столь же просто создадим и модель нашего корабля, для чего понадобятся три объекта типа цилиндр и четыре объекта ящик (box). Цилиндры можно чуть сузить (операция масштабирования на выделенном фрагменте объекта) для большего правдоподобия. Должно получиться примерно следующее:

Не забудьте, как и в предыдущем случае внедрить один объект типа Joint (на рисунке - синим цветом) и привязать его ко всем точкам (вертексам) нашей модели, для того чтоб Milkshape3D правильно экспортировал его в формат .md2. Создание текстуры для корабля остается за Вами.
Вы можете скачать модель и файл ms3d - для нашего корабля.
7.3. Перемещение кораблей и контроль столкновений.
Перемещение нашего корабля строго линейное, а именно вдоль осей Х и Z. Нам остается только контролировать, чтоб корабль не мог покинуть пределы игрового пространства.
If KeyDown(200) ; Up
If EntityZ(ship) < 14
MoveEntity ship, 0, 0, 0.2
EndIf
EndIf
If KeyDown(208) ; Down
If EntityZ(ship) > -1
MoveEntity ship, 0, 0, -0.2
EndIf
EndIf
If KeyDown(203) ; Left
If EntityX(ship) > -8
MoveEntity ship, -0.2, 0, 0
EndIf
EndIf
If KeyDown(205) ; Right
If EntityX(ship) < 8
MoveEntity ship, 0.2, 0, 0
EndIf
EndIf |
Как Вы видите из приведенного кода, корабль жестко замкнут в диапазоне координат
-1, 14 по оси Z и -8, 8 по оси Х. Дискретность перемещений выбираем 0.2, однако Вы можете поварьировать этот параметр в зависимости с Вашими предпочтениями.
По замыслу игры, корабли противника должны появляться с некоторым интервалом в игровой зоне нашей стрелялки. Само собой напрашивается решение применить функцию времени Millisecs() для контроля появления кораблей противника. Давайте зададим число вражеских кораблей константой, зарезервируем специальный массив, в котором будет хранится время появления в игровой зоне всех кораблей врага и напишем функцию, которая случайным образом генерирует это время.
Const NUM_ENEMY_ROCKETS = 20
Dim aEnemies( NUM_ENEMY_ROCKETS )
;---------------------------------------------------------
Function CreateRNDRockets()
aEnemies(0) = MilliSecs()+1000
SeedRnd MilliSecs()
For i=1 To NUM_ENEMY_ROCKETS
aEnemies(i) = aEnemies(i-1)+Rnd(1000,3000)
Next
iEnemy = 1
End Function |
Как видно из вышеприведенного фрагмента кода - 20 вражеских кораблей будут появляться в игре с интервалом в 1000 - 3000 миллисекунд одна за другой. После вызова нашей функции CreateRNDRockets() массив aEnemies будет содержать время появления врагов на игровом поле.
Теперь давайте займемся созданием и перемещением кораблей противника. В главном цикле программы создадим условие, которое будет сравнивать текущее время со временем уже занесенным ранее в массив aEnemies и при истинности этого условия создавать новую вражескую ракету в игровой зоне.
If iEnemy <= NUM_ENEMY_ROCKETS
If (MilliSecs() >= aEnemies(iEnemy))
CreateShip()
iEnemy = iEnemy + 1
EndIf
EndIf
;---------------------------------------------------------
Function CreateShip.EnemyShip()
es.EnemyShip=New EnemyShip
esShipSpeed=0.1
esShip=CopyEntity( ship3 )
EntityType esShip, TypeEnemy
PositionEntity esShip, Rnd(-8,8), 1, 18
SeedRnd MilliSecs()
esShipX = Rnd(-0.1,0.1)
esShipZ = Rnd(-0.4,0.4)
Return es
End Function |
Что касается функции CreateShip , то она возвращает созданный элемент списка (очередную ракету противника). Позиция вновь созданного вражеского корабля задается чуть выше верхней границы игровой зоны, чтоб имитировать появление ракеты из-за пределов видимой области. К тому же координата Х ее задается случайным образом из диапазона (-8,8). Кроме того функция сразу задает скорости дальнейшего перемещения по осям Х и Z (в виде приращений), таким образом косвенно задавая угол под которым корабль будет двигаться после его появления.
Перемещениями вражеских кораблей по экрану занимается созданная нами функция MoveShip. В ее обязанности будет входить определение столкновений нашего корабля с вражескими и осуществлять приращения к текущим координатам каждой из вражеских ракет.
Function MoveShip( es.EnemyShip )
b_collision = EntityCollided( esShip,TypePlayer )
; Enemy collided with player ship
If b_collision
DeleteEShip(esShip)
DestroyPlayerShip()
Else
MoveEntity esShip, esShipX, 0, esShipZ
If (EntityX(esShip) < -9.2) Or EntityX(esShip) > 9.2
esShipX = -1*(esShipX )
EndIf
If (EntityZ(esShip) < -2.5) Or EntityZ(esShip) > 18.5
esShipZ = -1*(esShipZ )
EndIf
EndIf
End Function |
Первая же строчка в функции MoveShip проверяет произошло ли столкновение вражеской ракеты с объектом типа TypePlayer то есть с нашим кораблем и если да, то вызывает функции удаления вражеской ракеты и нашего корабля (по крайней мере наш корабль теряет одну жизнь). Если же нет никаких столкновений, то происходит приращение координат и контроль за нахождением вражеской ракеты внутри игровой зоны. Таким образом вражеский корабль просто заперт в экране игры и отталкивается от стен меняя угол перемещений пока не будет убит выстрелом нашего корабля или после столкновения с ним.
Функции уничтожения вражеских ракет и гибели одной из жизней нашего корабля приведены ниже:
Function DeleteEShip(b_collision)
For es.EnemyShip=Each EnemyShip
If b_collision = esShip
CreateExplosion(esShip,5)
EmitSound expl, esShip
FreeEntity esShip
Delete es
iKilled = iKilled + 1
EndIf
Next
End Function
Function DestroyPlayerShip()
HideEntity ship
lModeImmortal = True
lImmortalTime = MilliSecs() + 3000
lRefreshShip = MilliSecs() + 100
CreateExplosion(ship,10)
PositionEntity ship, 0, 1, 0 ; Return Ship to start position
EmitSound playerexpl, ship
If lModeImmortal
If iNumRockets > 0
iNumRockets = iNumRockets - 1
Else
lGameLost = True
HideEntity ship
lModeImmortal = False
EndIf
EndIf
End Function |
Функция DeleteEShip вызывается после двух событий - столкновения с нашим кораблем и после попадания нашей ракеты во вражеский корабль. Ей передается аргумент - ссылка на вражеский корабль, который нужно удалить из игры. В результате выполнения этой функции по нашему замыслу должен прозвучать звук взрыва (EmitSound ) и его визуализация (CreateExplosion().
Функция DestroyPlayerShip прячет наш корабль и переводит игру в режим lModeImmortal. Это такой режим, когда на 3 секунды (3000 мили секунд) наш корабль начинает мигать на экране и становится неуязвимым для вражеских кораблей. В этой функции также проверяется количество оставшихся жизней нашего корабля, за которые отвечает переменная iNumRockets .
Кроме того после гибели функция возвращает наш корабль на стартовую точку или вообще убирает с экрана, если потрачена последняя жизнь при этом инициализируется флаг lGameLost = True символизирующий о том, что игра проиграна.
7.4. Стрельба по врагам.
Для визуализации процесса стрельбы по вражеским ракетам, используем спрайт, которым мы уже пользовались ранее:

Загрузим его в игру. При этом заметим, что один и тот же спрайт будет использоваться и для выстрелов нашего корабля и для взрывов нашего и вражеских кораблей в результате попаданий и столкновений.
Global bull_sprite=LoadSprite( "spritesbluspark.bmp" )
ScaleSprite bull_sprite,0.5, 0.5
EntityRadius bull_sprite,0.01
EntityType bull_sprite, TypeBullet
HideEntity bull_sprite |
Так как в программе проверяется столкновение ракеты с вражескими кораблями, то нужно описать тип коллизий:
Collisions TypeBullet, TypeEnemy, 1, 1 |
В главном цикле программы осуществим вызов функции, отвечающей за выстрел, причем клавишей для инициации выстрела, к примеру, выберем - Ctrl.
If KeyHit(29) And (Not lGameLost) ;Ctrl - fire
CreateBullet( ship )
EndIf |
После нажатия на эту злополучную для наших врагов клавишу, должен визуализироваться шарик, который начинает свое движение вдоль оси Z на встречу вражескому кораблю. Напишем функцию создания этого шарика с учетом того, что их может быть несколько в любой конкретный момент времени:
Function CreateBullet.Bullet( sh )
b.Bullet=New Bullet
btime_out=150
bsprite=CopyEntity( bull_sprite, sh )
EntityParent bsprite,0
Return b
End Function |
Итак функция CreateBullet создает экземпляр выстрела нашего корабля и возвращает его значение. Одно из полей типа выстрела содержит тайм-аут, что по сути является временем жизни экземпляра этого объекта. В данном случае ему присвоено значение 100. Попробуйте уменьшить это число и вы увидите, что пущенный снаряд будет исчезать не долетев верхней границы экрана. Так как в качестве родительского объекта для копирования спрайта используется наш корабль, то снаряд вылетает из места текущего расположения нашего корабля.
Теперь осталось создать функцию для обновления позиций всех выстрелов и проверки их столкновений с вражескими ракетами:
Function UpdateBullet( b.Bullet )
btime_out=btime_out-1
b_collision = EntityCollided( bsprite,TypeEnemy )
If (btime_out=0) Or b_collision
iCollision = 2
FreeEntity bsprite
Delete b
DeleteEShip(b_collision)
Return
EndIf
brot=brot+30
RotateSprite bsprite,brot
MoveEntity bsprite,0,0,0.2
End Function
|
Функция UpdateBullet должна располагаться в главном цикле программы. Для каждого из экземпляров выстрела функция уменьшает его время жизни btime_out и по достижении нуля уничтожает его. Уничтожение объекта спрайт, самого экземпляра объекта и вызов функции уничтожения вражеского корабля также возложено на хрупкие плечи этой функции. Нахождение коллизий с вражеским кораблем как всегда определяется функцией EntityCollided из набора Blitz3D. Если не происходит никаких столкновений, функция UpdateBullet просто осуществляет вращения спрайта и его перемещение к верхней границе экрана.
7.5. Эффект взрыва объектов
Для создания более динамичного действия можно написать парочку функций красочного уничтожения объектов. Конечно мы могли просто удалять уничтоженные объекты с экрана, но это было бы очень скучно. Посему создадим эффект разлетающихся частиц в космическом пространстве. Для начала понадобятся несколько констант, которые мы определим в начале программы:
Const grav# = -.02, intensity = 3 |
Константа grav - будет отвечать за гравитацию частиц, а intensity за насыщенность частицами
нашего эффекта.
Само собой разумеется, что взрыв должен произойти в том месте, где располагался корабль в момент наступления события его уничтожения.
Создадим функцию CreateExplosion, которая и будет создавать эффект взрыва
Function CreateExplosion(EnemyShip, num)
For i=1 To num
For t=1 To intensity
f.Frag=New Frag
falpha=Rnd(2,3)
fentity=CopyEntity( bull_sprite, EnemyShip )
ScaleSprite fentity, 0.2, 0.2
EntityColor fentity,Rnd(255),Rnd(255),Rnd(255)
EntityParent fentity,0
RotateEntity fentity,Rnd(360),Rnd(360),Rnd(360)
Next
Next
End Function |
В качестве аргументов наша функция CreateExplosion получает объект вражеского корабля, который должен взорваться и число частиц взрыва, которое должно быть визуализировано на экране. Цвет частиц задается генератором случайных чисел (функция Rnd) Углы частиц также задаются случайным образом для того чтоб они разлетались в объемных координатах.
Теперь осталось создать функцию, которая будет обновлять эффект взрыва на экране. Назовем ее UpdateExplosion и приведем текст ниже:
Function UpdateExplosion()
For f.Frag=Each Frag
falpha=falpha-dt*.02
If falpha>0
al#=falpha
If al>1 Then al=1
EntityAlpha fentity,al
MoveEntity fentity,0,0,dt*.4
ys#=fys+grav*dt
dy#=fys*dt
fys=ys
TranslateEntity fentity,0,dy,0
Else
FreeEntity fentity
Delete f
EndIf
Next
End Function |
Как видно из функции - время жизни каждой из частиц составляющих взрыв зависит от интенсивности ее свечения (falpha). Если этот параметр достигает нуля - частица удаляется из игры. Скорость перемещения частиц взрыва задается в главном цикле программы следующими строками кода:
Repeat
elapsed=MilliSecs()-time
Until elapsed>0
time=time+elapsed
dt=elapsed*60.0/3000.0 |
Попробуйте изменить число 3000 на меньшее и скорость частиц заметно повысится. Наоборот увеличение этого числа понижает скорость частиц.
7.6. Итоги и полный текст программы
Итак, мы с Вами без лишних усилий создали космическую аркаду, которая вобрала в себя весь пройденный материал предыдущих шести уроков. Полный текст программы приведен ниже:
Graphics3D 640, 680
SetBuffer BackBuffer()
Const TypePlayer = 1, TypeBullet = 2, TypeEnemy = 3
Const NUM_ENEMY_ROCKETS = 20
Const grav#=-.02,intensity=3
Global iNumRockets% = 3
Global lModeImmortal = False
Global lImmortalTime, lRefreshShip
Global lShowShip = False
Global lGameLost = False
Global lGameWon = False
Global Font1, Font2
Font1 = LoadFont("Arial Cyr",14, True)
Font2 = LoadFont("Arial Cyr",40)
Dim aEnemies(NUM_ENEMY_ROCKETS)
Global iEnemy = 1
Global iKilled = 0
Global iCollision = 0
Global player=CreateSphere()
PositionEntity player,0, 10, 7
TurnEntity player,90,0,0
Global cam=CreateCamera(player)
light=CreateLight(1)
PositionEntity light, 2,3,4
; Sounds
Global expl=Load3DSound( "soundsshipexpl.wav" )
Global playerexpl=Load3DSound( "soundsrocketexpl.wav" )
; Our ship
Global ship=LoadMD2("MODELSship1.md2")
ScaleEntity ship, .1,.1,.1
PositionEntity ship, 0, 1, 0
EntityRadius ship,0.5
EntityType ship, TypePlayer
;Enemy Ship
Global ship3=LoadMD2("MODELSship3.md2")
ScaleEntity ship3, .1,.1,.1
PositionEntity ship3, 0, 1, 10
EntityRadius ship3,1.0
EntityType ship3, TypeEnemy
Global ShipX# = -0.04
Global ShipZ# = -0.02
HideEntity ship3
Global Startex=LoadTexture("stars2.jpg")
Sky1=CreatePlane()
PositionEntity Sky1,0,-1,0
EntityTexture Sky1, Startex
ScaleTexture Startex, 5, 5
Global Startex2=LoadTexture("stars2.jpg",4)
Sky2=CreatePlane()
PositionEntity Sky2,0,-0.5,0
EntityTexture Sky2, Startex2
ScaleTexture Startex2, 10, 10
Global bull_sprite=LoadSprite( "spritesbluspark.bmp" )
ScaleSprite bull_sprite,0.5, 0.5
EntityRadius bull_sprite,0.01
EntityType bull_sprite,TypeBullet
HideEntity bull_sprite
; Тип вражеского корабля
Type EnemyShip
Field Ship
Field ShipX#
Field ShipZ#
Field ShipSpeed#
End Type
; Тип взрыва после столкновения или попадания
Type Frag
Field alpha#,entity
End Type
; Тип ракеты (выстрел нашего корабля)
Type Bullet
Field rot#,sprite,time_out
End Type
Collisions TypeBullet, TypeEnemy, 1, 1
Collisions TypePlayer, TypeEnemy, 1, 1
Collisions TypeEnemy, TypePlayer, 1, 1
CreateRNDRockets()
time=MilliSecs()
Global dt#
listener=CreateListener( player,.1,1,.2 )
While Not KeyDown( 1 )
Repeat
elapsed=MilliSecs()-time
Until elapsed>0
time=time+elapsed
dt=elapsed*60.0/3000.0
If KeyDown(200) ; Up
If EntityZ(ship) < 14
MoveEntity ship, 0, 0, 0.2
EndIf
EndIf
If KeyDown(208) ; Down
If EntityZ(ship) > -1
MoveEntity ship, 0, 0, -0.2
EndIf
EndIf
If KeyDown(203) ; Left
If EntityX(ship) > -8
MoveEntity ship, -0.2, 0, 0
EndIf
EndIf
If KeyDown(205) ; Right
If EntityX(ship) < 8
MoveEntity ship, 0.2, 0, 0
EndIf
EndIf
If KeyHit(29) And (Not lGameLost) ;Ctrl fire?
CreateBullet( ship )
EndIf
For es.EnemyShip=Each EnemyShip
Text 10,10+iPos, esShip
MoveShip( es )
iPos = iPos + 10
Next
MoveEntity Sky1, 0, 0, -0.05
MoveEntity Sky2, 0, 0, -0.07
If iEnemy <= NUM_ENEMY_ROCKETS
If (MilliSecs() >= aEnemies(iEnemy))
CreateShip()
iEnemy = iEnemy + 1
EndIf
EndIf
; Если установлен режим бессмертия
If lModeImmortal
If MilliSecs() > lRefreshShip
lRefreshShip = MilliSecs() + 100
If lShowShip
ShowEntity ship
lShowShip = False
Else
HideEntity ship
lShowShip = True
EndIf
If MilliSecs() > lImmortalTime
lModeImmortal = False
ShowEntity ship
EndIf
EndIf
EndIf
For b.Bullet=Each Bullet
UpdateBullet( b )
Next
UpdateExplosion()
UpdateWorld
RenderWorld
SetFont Font1
Text 10,50, "Rockets left: "+iNumRockets
If lGameLost
SetFont Font2
Text 180,250, "You Have Lost!"
EndIf
If (iKilled >= NUM_ENEMY_ROCKETS) And (Not lGameLost)
SetFont Font2
Text 150,250, "You Won The Game!"
EndIf
Flip
Wend
;-----------------------------------------------------------
; Create New Bullet
;-----------------------------------------------------------
Function CreateBullet.Bullet( sh )
b.Bullet=New Bullet
btime_out=100
bsprite=CopyEntity( bull_sprite, sh )
EntityParent bsprite,0
Return b
End Function
;-----------------------------------------------------------
; Update Bullet Position
;-----------------------------------------------------------
Function UpdateBullet( b.Bullet )
btime_out=btime_out-1
b_collision = EntityCollided( bsprite,TypeEnemy )
If (btime_out=0) Or b_collision
iCollision = 2
FreeEntity bsprite
Delete b
DeleteEShip(b_collision)
Return
EndIf
brot=brot+30
RotateSprite bsprite,brot
MoveEntity bsprite,0,0,0.2
End Function
;---------------------------------------
; Create New EnemyShip
;---------------------------------------
Function CreateShip.EnemyShip()
es.EnemyShip=New EnemyShip
esShipSpeed=0.1
esShip=CopyEntity( ship3 )
EntityType esShip, TypeEnemy
PositionEntity esShip, Rnd(-8,8), 1, 18
SeedRnd MilliSecs()
esShipX = Rnd(-0.1,0.1)
esShipZ = Rnd(-0.4,0.4)
Return es
End Function
;---------------------------------------
; Update Ship Position
;---------------------------------------
Function MoveShip( es.EnemyShip )
b_collision = EntityCollided( esShip,TypePlayer )
; Enemy collided with player ship
If b_collision
DeleteEShip(esShip)
DestroyPlayerShip()
Else
MoveEntity esShip, esShipX, 0, esShipZ
If (EntityX(esShip) < -9.2) Or EntityX(esShip) > 9.2
esShipX = -1*(esShipX )
EndIf
If (EntityZ(esShip) < -2.5) Or EntityZ(esShip) > 18.5
esShipZ = -1*(esShipZ )
EndIf
EndIf
End Function
;---------------------------------------
; Destroy Player Ship
;---------------------------------------
Function DestroyPlayerShip()
If Not lModeImmortal
If iNumRockets > 0
iNumRockets = iNumRockets - 1
Else
lGameLost = True
HideEntity ship
lModeImmortal = False
EndIf
PositionEntity ship, 0, 1, 0 ; Return Ship to start position
EmitSound playerexpl, ship
HideEntity ship
lImmortalTime = MilliSecs() + 3000
lRefreshShip = MilliSecs() + 100
CreateExplosion(ship,10)
lModeImmortal = True
EndIf
End Function
;---------------------------------------
; Update Ship Position
;---------------------------------------
Function CreateRNDRockets()
aEnemies(0) = MilliSecs()+1000
SeedRnd MilliSecs()
For i=1 To NUM_ENEMY_ROCKETS
aEnemies(i) = aEnemies(i-1)+Rnd(1000,3000)
Next
iEnemy = 1
End Function
;---------------------------------------
; Destroy EnemyShip
;---------------------------------------
Function DeleteEShip(b_collision)
For es.EnemyShip=Each EnemyShip
If b_collision = esShip
CreateExplosion(esShip,5)
EmitSound expl, esShip
FreeEntity esShip
Delete es
iKilled = iKilled + 1
EndIf
Next
End Function
;-------------------------------------
; Create Explosion
;-------------------------------------
Function CreateExplosion(EnemyShip, num)
For i=1 To num
For t=1 To intensity
f.Frag=New Frag
falpha=Rnd(2,3)
fentity=CopyEntity( bull_sprite, EnemyShip )
ScaleSprite fentity, 0.2, 0.2
EntityColor fentity,Rnd(255),Rnd(255),Rnd(255)
EntityParent fentity,0
RotateEntity fentity,Rnd(360),Rnd(360),Rnd(360)
Next
Next
End Function
;-------------------------------------
; Update Particles of Explosion
;-------------------------------------
Function UpdateExplosion()
For f.Frag=Each Frag
falpha=falpha-dt*.02
If falpha>0
al#=falpha
If al>1 Then al=1
EntityAlpha fentity,al
MoveEntity fentity,0,0,dt*.4
TranslateEntity fentity,0,dy,0
Else
FreeEntity fentity
Delete f
EndIf
Next
End Function
End |
Анализируя код программы космической аркады, вы также найдете функции загрузки шрифтов и звуков, с которыми мы ранее не сталкивались. Думается, что это не вызовет у вас никаких затруднений. Мы используем увеличение шрифта для вывода сообщений о поражении или победе в игре, а звуковые файл, который вы можете взять тут (shipexpl.wav и rocketexpl.wav), мы используем для озвучивания эффекта взрывов вражеских ракет и нашего корабля.
Заметим также, что все звуки должны располагаться в подкаталоге Sounds каталога с программным модулем, спрайт - в подкаталоге каталоге Sprites, а модели в подкаталог - Models. Вы можете расположить все модели звуки, спрайты в корневой каталог с игрой, если хотите, но тогда измените ссылки при загрузке этих ресурсов в теле программы.
Игровое окно программы выглядит примерно так:

После успешного уничтожения всех 20-и кораблей противника, вы получите радостное сообщение о своей победе. В противном случае программа сообщит о том что миссия провалена.
Что будет далее:
Следующей урок затронет тему создания ландшафтов. Мы научимся делать горы и впадины, рассаживать деревья и создавать водные массивы, небо и многое другое.
уже 16010 посетителей!
|
|