1.ゲームの設計
大きなプログラムを作成するにあたって最初に考えなくてはならないのは、やはりどのようなゲームを作成するかです。
ゲームの設計を考えるには様々なやり方 がありますが、昔からの方法の1つとしてペンと紙による設計があります。
どのようなゲームを作成したいか既に決まっている場合は実際にペンで紙に書いてみ ましょう。
下記のメモはこのチュートリアルを作成したプログラマーがFPSゲームを作成する際に書いたメモ書きです。
大まかにでも描いてみると分かり易くなりますね。
#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
2.メディアの収集
次はゲームに必要となるメディアを準備していきましょう。
メディアとは3Dワールド、3Dモデル、サウンド、ミュージック、イメージ、画像などのゲームのメインプログラムに追加する素材ファイルのことを指します。
FPSゲームを作成するには、上記であげたメディアのほとんどが必要となります。必要となるメ ディアを自分で集めてももちろん結構です。
例えば、空の背景には天球、ゲームプレイヤーの視点には銃のモデル、また倒すべき敵には敵のモデルなどゲーム作成においてはBSP(Binary Space Partitioning)もメディアの一部であると考えられます。ゲーム中に流れる音楽の巨大ループなどもメディアの一部と考えられます。
炎のイメージを表現するのにパーティクル(粒子)を使用するなどメディアを準備することで、ゲームがより精巧になります。
ダークベーシックプロフェッショナル日本語版には、各種素材をパックにした「ダークマター」や、素材をご自身で作成できる「ゲームスペースライト」が収納されております。アイデア次第で、あなだだけの素晴らしいオリジナルなゲームを作成出来る事でしょう。
3.プログラムの骨組み
ゲームの設計が終了したら、次はゲームプログラムの骨組みについて学習していきましょう。
ほとんどのゲームの基本的な骨組みは同じで、設定ステージ(オブジェクトのロードと準備)、メインループ(ゲームロジックの実行)、クリーンアップステージ(ロードしたメディアの解放)が存在します。
DarkBasic Professionalを終了するとロード済みメディアは自動的に解放されますので、Dark Basic Professionalでゲームを作成する際には、通常、上記の3つのステージの内の最初の2つのステージについてのみ考慮すればよいでしょう。それではまず設定ステージを作成しましょう。
rem TUT3A
rem Initial settings
sync on :sync rate 100
backdrop off : hide mouse
rem Load all media for game
gosub_load_game
rem Setup all objects for game
gosub_setup_game
次にゲーム内の要素を制御するメインループと繰り返し行う呼び出しを作成します。
rem TUT3B
rem Game loop
do
rem Control game elements
gosub_control_player
gosub_control_gunandbullet
gosub_control_enemies
rem Update screen
sync
rem End loop
loop
最後に最初の2ステージで呼び出されるサブルーチンを作成していきましょう。
サブルーチンとはコードブロックのことをさし、どこからでもジャンプしてその サブタスクを実行することができます。
サブタスクとは例えばプレイヤーのロード/コントロール/削除などを行います。サブルーチンには分かり易い名前をつ けて何をするサブルーチンなのか分かるようにしましょう。
rem TUT3C
_control_player:
return
_control_gunandbullet:
return
_control_enemies:
return
_control_stats:
return
_setup_game:
return
_load_game:
return
上記の例にも、各サブルーチンには内容が分かり易いように名前がつけてあります。現段階では、すべてのサブルーチンにコードが入っていませんが、このチュートリアルの後半で、実際にコードを入力していきましょう。
4.ワールドのロード
ゲームの設計が終了したら、次はゲームプログラムの骨組みについて学習していきましょう。ほとんどのゲームの基本的な骨組みは同じで、設定ステージ(オブ ジェクトのロードと準備)、メインループ(ゲームロジックの実行)、クリーンアップステージ(ロードしたメディアの解放)が存在します。
最初の課題は、ゲームを実行するワールドを作成することです。以前はワールドの作成は非常に複雑で、ゲーム作成者を悩ませることが多かったのですが、BSP
コマンドを使用することで、ワールドの作成はとてもシンプルな作業になりました。
簡単なコマンドを実行するだけで、ポリゴン、コリジョン、テクスチャ、シェーダーエフェクト情報を含むBSPワールドをまるごとロードすることができます。
また次のコマンドで天球を作成し、ゲームを実行するワールドに空を作成することができます。
rem TUT4A
rem Load BSP world and sky model
load bsp "world¥ikzdm1.pk3","ikzdm1.bsp"
SkyObj=1 : load object "models\sky\am.x",SkyObj
BSPワールドと空がロードされたら、次はカメラを設定して指定どおりに動くようにしなくてはなりません。
AutoCamが開始時に勝手に移動しないことを確認してください。
rem TUT4B
rem Setup camera
set camera range 1,10000
autocam off
rem Setup sky model
set object SkyObj,1,0,0,0,0,0,0
scale object SkyObj,20,20,20
#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
BSPのロード中には、ユーザーにロード中であることを知らせるためのテキストを画面に表示する必要があります。
ロードするBSPワールドが大きければ、 ロードに数分かかることもありえますので、画面にこのテキストを表示させることは非常に重要になります。
使い易いゲームをユーザーに提案するためにも、テキストの表示には大きくた見やすいフォントを使用するようにしましょう。
rem TUT4C
rem Select font
set text font "arial" : set text size 16
set text to bold : set text transparent
rem Loading prompt
sync : center text screen width()/2,screen height()/2,"LOADING" : sync
コードの最初/最後にSYNCコマンドを追加することで、プログラムを初期化して、手動で画面を更新することができます。
作成したテキストを確認するには、テキストの作成後にSYNCを作成する必要があります。
5.プレイヤーの追加
ワールドをロードしたら、次にゲームのプレイヤー(キャラクター)を作成していきましょう。FPSゲームではプレイヤーの視点がカメラになることが基本です。
カメラが動くとその動きがプレイヤーの動きとなります。
rem TUT5A
Rem Trigger player initialisation
Restart=1
次にこの値が1に設定された際にプレイヤーをセットアップするコードを準備します。
カメラのBSPコリジョンを使用して3Dワールドのコリジョンを完全自動化することができます。
自動化はスライディングコリジョンだけではなく、早いスピードのコリジョンも可能です。
rem TUT5B
rem In case of restart
if restart=1
restart=0
set bsp collision off 1
rotate camera 0,0,0
position camera 2,2,2
set bsp camera collision 1,0,0.75,0
endif
プレイヤーのセットアップ後に制御が可能になります。はじめはプレイヤーの回転、動き、重力を準備しましょう。
rem TUT5C
rem Control player direction
rotate camera camera angle x(0)+(mousemovey( )/2.0), camera angle y(0)+(mousemovex ( )/2.0),0
rem Conrol player movement
cx#=camera angle x(0) : cy#=camera angle y(0)
if upkey( )=1 then xrotate camera 0,0 : move camera 0,0.2 : xrotate camera 0, cx#
if downkey( )=1 then xrotate camera 0,0 : move camera 0,-0.2 : xrotate camera 0, cx#
if leftkey( )=1 then yrotate camera 0,cy#-90 : move camera 0.2 : yrotate camera 0, cy#
if rightkey( )=1 then yrotate camera 0,cy#+90 : move camera 0.2 : yrotate camera 0, cy#
if wrapcalue(camera angle x(0))>40 and wrapvalue(camera angle x(0))180 then xrotate camera 0,40
if wrapvalue(camera angle x(0))>180 and wrapvalue(camera angle x(0))280 then xrotate camera 0,280
rem Apply simple gravity to player
position camera camera position x( ), camera position y(-0.1, camera position z( )
また、FPSゲームでは常にプレイヤーが画面の中心に位置している必要がありますので、プレイヤーの動きに合わせて空と3Dリスナーの位置を調整する必要があります。
rem TUT5D
rem Player is always focal point of sky
position object SkyObj, camera position x( ), camera position y( ), camera position z( )
rem position object listener at player for 3D sound
position listener camera position x( ), camera position y( ), camera position z( )
rotate listener camera anglex( ), camera angle y( ), camera angle z( )
6.銃の追加
FPSゲームのプレイヤーが銃とその銃に入れる銃弾を持っていなければ、ゲームはすぐに終わってしまいますよね。
通常、FPSゲームの銃は画面下の部分から突き出る形で表示されることが多く、銃弾が発射される方向は画面中央に十字型の印で表示されます。
#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
コードの最初の部分では画面を構成するすべてのモデル、サウンド、イメージをロードします。
具体的にあげると銃モデル、銃が発射されたときの音、バックグラウンドミュージック、画面に表示する十字のマークなどです。
rem TUT6A
rem Lad model for gun
GunObj=2 : load object “models\gun\gun.x”, GunObj
rem Lad all sounds
GunSnd=1 : load sound “sounds\gun.wav”, GunSnd
ImpactSnd=2 : load 3dsound “sounds\impact.wav”, ImpactSnd
DieSnd=101 : load sound “sounds\ingame.wav”, MusicSnd
rem Load music (WAV best for looping)
MusicSnd=101 : load sound “sounds\ingame.wav”, MusicSnd
Loop sound MusicSnd : set sound volume MusicSnd, 80
rem Load images
FireImg=1 : load image “image\fire.bmp”, FireImg
CrossHairImg=2 : Lad image “images\crossfari.bmp”, CrossHairImg
メディアをロードした後は、ゲームの開始前にオブジェクトの設定をしましょう。
銃はプレイヤーの視点(カメラ)の一部として画面に固定しなくてはなりません。
銃弾と画面上の十字マークを作成するのも忘れないでおきましょう。
rem TUT6B
rem Setup gun for player
lock object on GunObj
scale object GunObj
scale object GunObj, 2,2,4
rotate object GunObj, 270,0,0
position object GunObj, 0.5,-1,2
disable object zdepth GunObj
rem Create object for bullet
bulletObj=3 : make object cube BulletObj, 0.1
rem Create simple sprite based crosshair
sprite 1, 320-16, 240-16, CrossHairImg
set sprite 1,0,1
次はユーザーがマウスボタンを押した際に銃が発射するように設定します。銃が銃弾を1発発射すると次の銃弾を発射するまで少し時間がかかります。
次の銃弾を発射するまでのクールダウン時間が必要であるというような筋書きにすればユーザーにとって違和感がないと思います。
rem TUT6C
rem Control gun firing
if mouseclick( )=1 and bullet=-50
bullet=100
play sound GunSnd
position object BulletObj, camera position x(0),camera position y(0), camera position z(0)
rotate object BulletObj, camera angle x(0), camera angle y(0), 0
set bsp object collision 2, BulletObj, 0.1,1
move object BulletObj, 0.2
endif
次は銃弾について設定していきましょう。発射後、銃弾は前に進み、壁にあったときに破壊されるようにしなくてはなりません。
簡単に設定するには前述のコード内のBSPコリジョン設定のビルトインコマンドを使用しましょう。
rem TUT6D
rem Control life of bullet
if bullet>0
rem If bullet collides with BSP world
if bsp collision hit(2)=1 or bulletimpact=1
rem End bullet on wall
position sound ImpactSnd, object position x(BulletObj), object position y(BulletObj), object position z(BulletObj)
play sound ImpactSnd
bulletimpact=0
bullet=0
else
rem Move bullet
dec bullet
move object BulletObj, 0.5
endif
rem Bullet dies
if bullet=0
set bsp collision off 2
endif
else
rem Gun recharge phase
if bullet>-50 then dec bullet
endif
7.敵の追加
FPSゲームには銃で撃つ標的が不可欠です。このチュートリアルではエイリアンを設定することにします。
エイリアンは平和を求めてやってくるかも知れませんが、このゲーム内ではとにかくシューティングのターゲットとして撃ってしまいましょう。
まずは敵のオブジェクトのモデルをロードします。
rem TUT7A
rem Load models for enemies
EneObj=11
for ene=EneObj to EneObj+4
load object “models\enemy\H-Alien Psionic-Idle.x”, ene
append object “models\enemy\H-Alien Psionic-Die.x”, total object frames(ene)+1
position object ene,2,2,4
loop object ene,0,25
next ene
次にエイリアンの存在をより現実的なものにするためのサウンドを追加していきましょう。
エイリアンが近づくに従って聞こえてくるエイリアンの息遣いを追加すれば、エイリアンの怖さをより強調することができます。
rem TUT7B
EnemySnd=11 : load 3dsound “sound\enemy.wav”, EnemySnd
EnemygunSnd=12 : load 3dsound “sounds\enemygun.wav”, EnemygunSnd
EnemydieSnd=13 : load 3dsound “sounds\enemydie.wav”, EnemydieSnd
これで敵のメディアはロードできました。次は敵の動き、回転、重力、そして3Dサウ ンド制御について設定していきましょう。
rem TUT7c
rem Variable for finding closest enemy
cdist#=9999.99
rem Handle enemies within world
for ene=EneObj to EneObj+4
rem If enemy alive
if object visible(ene)=1
rem Kill this enemy
killenemy=0
rem Move enemy on a slow curve for appearnce of intelligence
if object angle z(ene)=0
yrotate object ene, wrapvalue(object angle y(ene)+2)
endif
if object angle z(ene)=1
yrotate object ene, wrapvalue(object angle y(ene)-2)
endif
if object angle z(ene)=2
move object ene, 0.05
else
move object ene, 0.02
endif
rem Switch direction of curve based on a random value
if rnd(200)=1 then zrotate object ene, rnd(1)
rem Handle gravity for enemy
position object ene, object position x(ene), object position y(ene)-0.01, object position
z(ene)
rem Work out angle and distance between enemy and aplyer
dx#=camera position x(0)-object position x(ene)
dy#=camera position y(0)-object position y(ene)
dz#=camera position z(0)-object position z(ene)
dist#=ads(sqrt(abs(dx#*dx#)+abs(dy#*dy#)+( dz#*dz#)))
viewa#=wrapvalue(atanfull(dx#, dz#))
obja#=wrapvalue(object angle y(ene))
if viewa#>180 then viewa#=viewa#-360
if obja#>180 then obja#=obja#-360
rem Closest enemy emits the enemy sound
if dist#26+25 and object visible(ene)=1
killenemy=1
endif
if killenemy=1
set bsp collision off 3+(ene-Eneobj)
hide object ene : dec aliensleft
killenemy=0
endif
rem If enemy alive ENDIF
endif
next ene
彼らの息遣いのサウンドを常にバックグランドに小さな音量で流し続け、彼らがプレイヤーに近づいたときにプレイヤーの耳に初めて息遣いが聞こえるように設定すると、エイリアンの気持ち悪さがより際立つと思います。
rem TUT7D
rem Start the enemy presence sound
loop sound EnemySnd
scale listener 0.1
8.ロジックの追加
ロジックとはジャンルに関わらず、すべてのゲームの要となるもので、ゲーム内で起こるすべての事柄をコントロールしています。
今回作成しているゲームでは、ロジックのコードによって、「プレイヤーがエイリアンを殺す」、「エイリアンがプレイヤーを殺す」、 「プレイヤーがゲームに勝つ/負ける」の事柄がコントロールされます。このチュートリアルの目的はゲームを完成させることではありませんので、すべてのロジックを説明することはしませんが、例としてプレイヤーが死んだ後に再びゲームを再スタートするロジックの作り方を説明していきましょう。
ゲームに登場するエイリアンの視界にプレイヤーが入っているとき、エイリアンがプレイヤーに向かって移動するようにすることができます。
rem TUT8A
rem If enemy 'facing player' and 'on similar height' and 'close', zoom in
if abs(viewa#-obja#)10.0 and abs(dy#)5.0 and dist#30.0
if object angle z(ene)>2 then play sound EnemygunSnd
rotate object ene,0,viewa#,2
set object speed ene,2
else
set object speed ene,1
endif
プレイヤーと敵(エイリアン)が近づきすぎるとプレイヤーが死ぬように設定する必要があります。
プレイヤーが生き返ったときに、死んだときと同じ位置にエイリアンが居たらプレイヤーはまたすぐに死んでしまいますので、プレイヤーが生き返ったときには敵(エイリアン)をゲーム上から一度削除する必要があります。
rem TUT8B
rem If enemy gets too close to player, player dies
if dist#2.0
play sound DieSnd
for x=0 to 100
point camera object position x(ene), object position y(ene)+(x/20.0), object position z(ene)
sync
next x
restart=1
killenemy=1
endif
敵に銃弾がヒットすると敵と銃弾の両方が死ぬようにします。
プレイヤーが銃を発射すれば銃弾は再び敵を撃つことができますが、敵であるエイリアンの寿命はその場で終わるようにします。
rem TUT8C
rem If enemy and bullet in same space, enemy dies
if bullet>0
if object collision(BulletObj,ene)>0
play sound EnemydieSnd
play object ene,26,26+50
set object speed ene,1
bulletimpact=1
endif
endif
すべての敵をプレイヤーの前に配置すると、ゲームがすぐに終わってしまいおもしろくありませんので、敵を画面上のいたるところに配置して敵が壁などの障害物を通り抜けできないようにコリジョンを設定するロジックを追加します。
rem TUT8D
rem Place enemies throughout world and set BSP collision for them
aliensleft=0
restore EnemyPosData
for ene=EneObj to EneObj+4
read ex#,ey#,ez#
position object ene,ex#,ey#,ez#
set bsp object collision 3+(ene-EneObj),ene,0.75,0
yrotate object ene,180 : fix object pivot ene
inc aliensleft
next ene
上記のコードではRESTORE、READコマンドを使用していますので、敵の配置を決める座標のDATAステートメントを準備する必要があります。
敵はプレイヤーに向かって移動しますので、敵の座標はプレイヤーの座標を下に計算されます。
rem TUT8E
rem Enemy position data within level
EnemyPosData:
data -9.27,9.98,-2.78
data -16.54,-0.22,19.18
data 2.0,9.0,25.0
data -2.0,-9.0,25.0
data 2,4.0,10.0
8.ロジックの追加
光沢を追加することでゲームは更に良いものとなります。最新式の車、ステレオ、洗濯機などがよく見えるのはそれらの製品に光沢があるからです。
光沢には6層あります。
オブジェクトに追加した光沢はずっと続きます。このチュートリアルではstatistical shineとparticle bullet shineの2層の光沢を追加することにします。statistical shineを追加するにはレベル内に何匹のエイリアンがいるのか、いつレベルが完了するのか、一番近いエイリアンまでどれくらいの距離があるのかという情報を提供する必要があります。
銃弾の作成
Rem TUT9E
if particles exist(1)=1 then delete particles 1
make particles 1, FireImg, 50, 0.5
set particle emissions 1,10
set particle speed 1,0.01
銃弾の制御
rem TUT9C
rem Update particle using bullet object position
set particle emissions 1,1+(bullet/10)
rotate particles 1,90-object angle x(BulletObj), object angle y(BulletObj)+180,0
position particles 1, object position x(BulletObj), object angle y(BulletObj), object position
z(BulletObj)
銃弾の方向
rem TUT9D
set particle emissions 1,0
以上で終了です。是非お試しください!
最終更新:2007年09月19日 21:20