2 single: 2D ゲームエンジン; はじめに
4 ====================================
6 ====================================
8 シンプルな 2D ゲームエンジンの作成を通じて、多種多様なプログラミングパラダイムをプロジェクトで併用する方法を学びます。
10 これでデスクトップ、またはモバイル用 2D ゲームを作成できます。
13 pair: 2D ゲームエンジン; プロジェクトの階層
18 このような階層をプロジェクトで使用しています。
21 * ゲームエンジンのクラス (オブジェクト指向プログラミングのパラダイム)
22 * グラフィックスライブラリへのインタフェース (手続き型プログラミング)
23 * グラフィックスライブラリへのバインディング (RingAllegro と RingLibSDL)
26 pair: 2D ゲームエンジン; グラフィックスライブラリのバインディング
29 ========================================
31 Allegro ゲームプログラミング・ライブラリ用の RingAllegro と
32 LibSDL ゲームプログラミング・ライブラリ用の RingLibSDL があります。
34 RingAllegro と RingLibSDL は Ring コード生成器の支援により
37 RingAllegro と RingLibSDL はシンプルな設定ファイルを記述した後に生成される
38 10,000 行以上の C コードからなります (コード生成器による処理)。
40 RingAllegro と RingLibSDL の設定ファイルで関数名、構造体情報、および定数を決定後、
41 この設定ファイルを生成器で処理して C コードと
42 Ring コードから読み込み可能なライブラリを生成します。
44 RingAllegro と RingLibSDL の使用は同一関数を有する C コードから
45 Allegro および LibSDL の使用と非常に類似していますが Ring の機能で構築できます。
47 * RingAllegro のソースコード : https://github.com/ring-lang/ring/tree/master/extensions/ringallegro
48 * RingLibSDL のソースコード : https://github.com/ring-lang/ring/tree/master/extensions/ringsdl
51 pair: 2D ゲームエンジン; グラフィックスライブラリへのインタフェース
54 ==========================================
56 この階層には gl_allegro.ring および gl_libsdl.ring があります。
58 グラフィックスライブラリとの相互作用により、ライブラリ間で同一関数を使えます。
60 この階層は RingAllegro と RingLibSDL の詳細と差異を吸収します。
62 同一関数で Allegro と LibSDL を何時でも切り替えて使えます。
66 Allegro は非常に単純明快であり Windows, Linux および macOS 用の 2D ゲームを手軽に作成できます。
68 Ring 1.0 から Allegro へ対応しました。
70 また LibSDL は非常に強力かつ普及しており、モバイル開発では非常に簡単に使えます。
72 Ring 1.1 から LibSDL へ対応しているため、モバイル用のゲームを手軽に作成できます。
74 .. note:: このライブラリだけで、デスクトップとモバイル開発ができます。
76 * gl_allegro.ring のソースコード : https://github.com/ring-lang/ring/blob/master/ringlibs/gameengine/gl_allegro.ring
77 * gl_libsdl.ring のソースコード : https://github.com/ring-lang/ring/blob/master/ringlibs/gameengine/gl_libsdl.ring
80 pair: 2D ゲームエンジン; ゲームエンジンのクラス
83 ======================
97 * ソースコード : https://github.com/ring-lang/ring/blob/master/ringlibs/gameengine/gameengine.ring
100 pair: 2D ゲームエンジン; ゲームの階層
105 この階層では、ゲームエンジンのクラスを使用してゲームを作成します。
107 宣言型プログラミングでクラスの設計を行っています。
118 .. note:: エンジンに実装されている上記以外のクラスは、エンジンの内部処理用です。
123 * Flappy Bird 3000 ゲーム
127 pair: 2D ゲームエンジン; Game クラス
134 ============ =================================================================================
136 ============ =================================================================================
137 FPS 数値により毎秒ごとの draw() メソッドの呼び出し回数を決定します。
138 FixedFPS 数値により毎秒ごとの animate() メソッドの呼び出し回数を決定します。
139 Title 文字列によりゲームのウィンドウタイトルを決定します。
140 aObjects ゲーム内の全てのオブジェクトを有するリストです。
141 shutdown True/False 値によりゲームのループを終了します。
142 ============ =================================================================================
146 ================ =================================================================================
148 ================ =================================================================================
149 refresh() オブジェクトを削除します。
150 settitle(cTitle) 文字列による仮引数でウィンドウのタイトルを設定します。
151 shutdown() アプリケーションを閉じます。
152 find(cName) オブジェクト名でオブジェクトを検索します。
153 remove(nID) オブジェクト ID でオブジェクトを削除します。
154 ================ =================================================================================
156 この表はクラスで定義されているキーワードのグループです。
158 ================ =================================================================================
160 ================ =================================================================================
161 sprite 新しい Sprite オブジェクトを作成後に Game オブジェクトへ追加します。
162 text 新しい Text オブジェクトを作成後に Game オブジェクトへ追加します。
163 animate 新しい Animate オブジェクトを作成後に Game オブジェクトへ追加します。
164 sound 新しい Sound オブジェクトを作成後に Game オブジェクトへ追加します。
165 map 新しい Map オブジェクトを作成後に Game オブジェクトへ追加します。
166 ================ =================================================================================
169 pair: 2D ゲームエンジン; GameObject クラス
176 ============ =====================================================================================
178 ============ =====================================================================================
179 enabled True/False によりオブジェクトの状態 (活動または休止) を決定します
180 x オブジェクトの x 位置を数値で決定します。
181 y オブジェクトの y 位置を数値で決定します。
182 width オブジェクトの幅を数値で決定します。
183 height オブジェクトの高さを数値で決定します。
184 nIndex 数値によりオブジェクトの ID を決定します。
185 name 文字列によりオブジェクト名を決定します。
186 animate True/False によりオブジェクトのアニメーションを行うかどうか決定します。
187 move True/False によりキーボードでオブジェクトの画像を移動するかどうか決定します。
188 Scaled True/False によりオブジェクトの画像の寸法を変更するかどうか決定します。
189 draw オブジェクトの描画時に呼び出される関数です。
190 state オブジェクトのアニメーションで呼び出される関数です。
191 keypress キーが押し下げられた時に呼び出される関数です。
192 mouse マウスイベント発生時に呼び出される関数です。
193 ============ =====================================================================================
197 ============================== ================================================================
199 ============================== ================================================================
200 keyboard(oGame,nkey) キーボードイベントを返します。
201 mouse(oGame,nType,aMouseList) マウスイベントを確認します。
202 rgb(r,g,b) RGB (赤色、緑色、および青色) 値で新しい色を返します。
203 ============================== ================================================================
206 pair: 2D ゲームエンジン; Sprite クラス
211 親クラス : GameObject クラス
215 ============ =================================================================================
217 ============ =================================================================================
218 image 画像ファイル名を文字列で決定します。
219 point 数値によりオブジェクトにおける自動移動の制限を決定します。
220 direction 数値により移動方向を決定します。
221 nstep 数値により移動中の増分または減分を決定します。
222 type 数値によりゲームでのオブジェクトの種類を決定します (オプション扱い)。
223 transparent True/False の値により画像の透過を決定します。
224 ============ =================================================================================
228 ================ =================================================================================
230 ================ =================================================================================
231 Draw(oGame) オブジェクトを描画します。
232 ================ =================================================================================
235 pair: 2D ゲームエンジン; Text クラス
244 ============ =================================================================================
246 ============ =================================================================================
247 size 数値によりフォントの寸法を決定します。
248 font 文字列によりフォントのファイル名を決定します。
249 text 文字列により表示されるテキストを決定します。
251 ============ =================================================================================
255 ================ =================================================================================
257 ================ =================================================================================
258 Draw(oGame) オブジェクトを描画します。
259 ================ =================================================================================
263 pair: 2D ゲームエンジン; Animate クラス
272 ============ =================================================================================
274 ============ =================================================================================
275 frames 数値によりフレーム数を決定します。
276 frame 数値により有効なフレームを決定します。
277 framewidth 数値によりフレームの幅を決定します。
278 animate True/False によりアニメーションの使用を決定します。
279 scaled True/False により画像の尺度変更を決定します。
280 ============ =================================================================================
284 ================ =================================================================================
286 ================ =================================================================================
287 Draw(oGame) オブジェクトを描画します。
288 ================ =================================================================================
291 pair: 2D ゲームエンジン; Sound クラス
296 親クラス : GameObject クラス
300 ============ =================================================================================
302 ============ =================================================================================
303 file 音声ファイル名を文字列で決定します。
304 once True/False によりファイルを一回またはループ再生するかどうかを決定します。
305 ============ =================================================================================
309 ================ =================================================================================
311 ================ =================================================================================
312 playsound() 音声ファイルを再生します。
313 ================ =================================================================================
316 pair: 2D ゲームエンジン; Map クラス
325 ============ =================================================================================
327 ============ =================================================================================
328 aMap 数値でマップの中身をリストで決定します。
329 aImages マップの各番号で使用されている画像をリストで決定します。
330 BlockWidth ブロックの幅を数値で決定します (デフォルト = 32)。
331 BlockHeight ブロックの高さを数値で決定します (デフォルト = 32)。
332 Animate アニメーションの状態を True/False で決定します。
333 ============ =================================================================================
337 ================ =================================================================================
339 ================ =================================================================================
340 getvalue(x,y) 項目の値でマップの可視部分を返します。
341 ================ =================================================================================
344 pair: 2D ゲームエンジン; ゲームエンジンの用法 - ゲームウィンドウの作成
346 ゲームエンジンの用法 - ゲームウィンドウの作成
347 =============================================
351 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
353 func main # ゲームエンジンから呼び出されます。
355 oGame = New Game # Game オブジェクトの作成
357 title = "My First Game"
360 .. note:: この命令でゲームエンジンに制御権を委譲します。よって、グローバル変数の定義は "gameengine.ring" を読み込む前に行う必要があります。
364 .. image:: gameengineshot1.png
368 pair: 2D ゲームエンジン; テキストの描画
371 =====================================
375 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
377 func main # ゲームエンジンから呼び出されます。
379 oGame = New Game # Game オブジェクトの作成
381 title = "My First Game"
386 file = "fonts/pirulen.ttf"
387 text = "game development using ring is very fun!"
395 .. image:: gameengineshot2.png
399 pair: 2D ゲームエンジン; テキストの移動
402 =========================================
406 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
408 func main # ゲームエンジンから呼び出されます。
410 oGame = New Game # Game オブジェクトの作成
412 title = "My First Game"
417 file = "fonts/pirulen.ttf"
418 text = "game development using ring is very fun!"
419 color = rgb(0,0,0) # 配色 = 黒色
423 # アニメーション部分 =================================
424 animate = true # アニメーションの使用
425 direction = GE_DIRECTION_INCVERTICAL # y の増分
426 point = 400 # y=400 になるまで継続
427 nStep = 3 # 毎回 y+= 3 を行う
428 #=====================================================
430 file = "fonts/pirulen.ttf"
431 text = "welcome to the real world!"
432 color = rgb(0,0,255) # 配色 = 青色
438 .. image:: gameengineshot3.png
442 pair: 2D ゲームエンジン; 音声の再生
445 =====================================
449 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
451 func main # ゲームエンジンから呼び出されます。
453 oGame = New Game # Game オブジェクトの作成
455 title = "My First Game"
460 file = "fonts/pirulen.ttf"
461 text = "game development using ring is very fun!"
462 color = rgb(0,0,0) # 配色 = 黒色
466 # アニメーション部分 ======================================
467 animate = true # アニメーションの使用
468 direction = GE_DIRECTION_INCVERTICAL # y の増分
469 point = 400 # y=400 になるまで継続
470 nStep = 3 # 毎回 y+= 3 を行う
471 #==========================================================
473 file = "fonts/pirulen.ttf"
474 text = "welcome to the real world!"
475 color = rgb(0,0,255) # 配色 = 青色
478 file = "sound/music1.wav" # イベントループの開始
483 pair: 2D ゲームエンジン; アニメーション
486 =========================================
490 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
492 func main # ゲームエンジンから呼び出されます。
494 oGame = New Game # Game オブジェクトの作成
496 title = "My First Game"
499 file = "images/fire.png"
506 state = func oGame,oSelf { # エンジンの各フレームで呼び出されます
511 if frame < 13 # 13 フレームから構成されるアニメーション
514 oGame.remove(oself.nIndex) # オブジェクトの削除
525 .. image:: gameengineshot5.png
529 pair: 2D ゲームエンジン; アニメーションと関数
531 ゲームエンジンの用法 - アニメーションと関数
532 ===============================================
536 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
538 func main # ゲームエンジンから呼び出されます。
540 oGame = New Game # Game オブジェクトの作成
542 title = "My First Game"
543 for x = 70 to 700 step 50
544 for y = 70 to 500 step 50
551 func showfire oGame,nX,nY
554 file = "images/fire.png"
561 state = func oGame,oSelf { # エンジンの各フレームで呼び出されます
566 if frame < 13 # 13 フレームから構成されるアニメーション
577 .. image:: gameengineshot6.png
582 pair: 2D ゲームエンジン; キーボードによる自動移動
584 ゲームエンジンの用法 - スプライト - キーボードによる自動移動
585 ============================================================
589 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
591 func main # ゲームエンジンから呼び出されます。
593 oGame = New Game # Game オブジェクトの作成
595 title = "My First Game"
598 type = GE_TYPE_PLAYER # 用法
599 x=400 y=400 width=100 height=100
600 file = "images/player.png"
603 Move=true # キーボードの矢印キーで移動できます。
608 .. image:: gameengineshot7.png
613 pair: 2D ゲームエンジン; スプライト - キー入力イベント
615 ゲームエンジンの用法 - スプライト - キー入力イベント
616 ====================================================
620 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
622 func main # ゲームエンジンから呼び出されます。
624 oGame = New Game # Game オブジェクトの作成
626 title = "My First Game"
629 type = GE_TYPE_PLAYER # 用法
630 x=400 y=400 width=100 height=100
631 file = "images/player.png"
636 keypress = func oGame,oSelf,nKey {
654 pair: 2D ゲームエンジン; スプライト - マウスイベント
656 ゲームエンジンの用法 - スプライト - マウスイベント
657 ======================================================
661 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
663 func main # ゲームエンジンから呼び出されます。
665 oGame = New Game # Game オブジェクトの作成
667 title = "My First Game"
670 type = GE_TYPE_PLAYER # 用法
671 x=400 y=400 width=100 height=100
672 file = "images/player.png"
677 keypress = func oGame,oSelf,nKey {
691 mouse = func oGame,oSelf,nType,aMouseList {
692 if nType = GE_MOUSE_UP
694 x = aMouseList[GE_MOUSE_X]
695 y = aMouseList[GE_MOUSE_Y]
703 pair: 2D ゲームエンジン; スプライト - ステートイベント
705 ゲームエンジンの用法 - スプライト - ステートイベント
706 ========================================================
710 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
712 func main # ゲームエンジンから呼び出されます。
714 oGame = New Game # Game オブジェクトの作成
716 title = "My First Game"
719 type = GE_TYPE_PLAYER # 用法
720 x=400 y=400 width=100 height=100
721 file = "images/player.png"
726 keypress = func oGame,oSelf,nKey {
740 mouse = func oGame,oSelf,nType,aMouseList {
741 if nType = GE_MOUSE_UP
743 x = aMouseList[GE_MOUSE_X]
744 y = aMouseList[GE_MOUSE_Y]
748 state = func oGame,oSelf {
752 if x > ogame.width-width
753 x= ogame.width - width ok
754 if y > ogame.height-height
755 y=ogame.height - height ok
763 pair: 2D ゲームエンジン; アニメーション - イベント
765 ゲームエンジンの用法 - アニメーション - イベント
766 ====================================================
770 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
772 func main # ゲームエンジンから呼び出されます。
774 oGame = New Game # Game オブジェクトの作成
776 title = "My First Game"
780 file = "images/fbbird.png"
790 state = func oGame,oSelf {
812 keypress = func ogame,oself,nKey {
821 mouse = func ogame,oself,nType,aMouseList {
822 if nType = GE_MOUSE_UP
823 cFunc = oself.keypress
824 call cFunc(oGame,oSelf,Key_Space)
832 .. image:: gameengineshot11.png
836 pair: 2D ゲームエンジン; マップ
840 =================================
844 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
846 func main # ゲームエンジンから呼び出されます。
848 oGame = New Game # Game オブジェクトの作成
850 title = "My First Game"
858 [0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],
859 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],
860 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0],
861 [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0],
862 [0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0],
863 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
864 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
865 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0]
868 aImages = ["images/fbwall.png",
869 "images/fbwallup.png",
870 "images/fbwalldown.png"]
872 state = func oGame,oSelf {
875 if x < - 2100 x = 0 ok
885 .. image:: gameengineshot12.png
890 pair: 2D ゲームエンジン; マップイベント
893 =========================================
897 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
899 func main # ゲームエンジンから呼び出されます。
901 oGame = New Game # Game オブジェクトの作成
903 title = "My First Game"
911 [0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],
912 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],
913 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0],
914 [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0],
915 [0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0],
916 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
917 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
918 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0]
921 aImages = ["images/fbwall.png",
922 "images/fbwallup.png",
923 "images/fbwalldown.png"]
925 state = func oGame,oSelf {
928 if x < - 2100 x = 0 ok
932 mouse = func ogame,oself,nType,aMouseList {
933 if nType = GE_MOUSE_UP
935 mX = aMouseList[GE_MOUSE_X]
936 mY = aMouseList[GE_MOUSE_Y]
937 nValue = GetValue(mX,mY)
941 On 1 aMap[nRow][nCol] = 0
942 On 2 aMap[nRow][nCol] = 0
943 On 3 aMap[nRow][nCol] = 0
944 On 0 aMap[nRow][nCol] = 1
955 .. image:: gameengineshot13.png
959 pair: 2D ゲームエンジン; オブジェクトと描画処理
961 ゲームエンジンの用法 - オブジェクトと描画処理
962 =============================================
964 GameObject クラスからオブジェクトを作成するには、 Object キーワード (ゲームエンジンで定義済み) を使用します。
970 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
972 func main # ゲームエンジンから呼び出されます。
974 oGame = New Game # Game オブジェクトの作成
976 title = "My First Game"
978 x = 0 y=300 width = 200 height=200
979 draw = func oGame,oSelf {
982 gl_draw_circle(x,y,t,
983 gl_map_rgb(t*random(255),
988 state = func oGame,oSelf {
997 keypress = func oGame,oSelf,nKey {
1017 .. image:: gameengineshot14.png
1022 .. code-block:: ring
1024 Load "gameengine.ring" # ゲームエンジンへ制御権を与えます。
1026 func main # ゲームエンジンから呼び出されます。
1028 oGame = New Game # Game オブジェクトの作成
1030 title = "My First Game"
1032 x = 400 y=300 width = 200 height=200
1033 draw = func oGame,oSelf {
1036 gl_draw_rectangle(x+t,y+t,
1038 gl_map_rgb(t*random(255),
1040 gl_draw_rectangle(x+t*2,y+t*2,
1042 gl_map_rgb(t*random(255),
1047 keypress = func oGame,oSelf,nKey {
1068 .. image:: gameengineshot15.png
1072 pair: 2D ゲームエンジン; Stars Fighter ゲーム
1075 ====================
1077 Stars Fighter ゲームのソースコード
1079 .. code-block:: ring
1083 # 2016, Mahmoud Fayed <msfclipper@yahoo.com>
1087 load "gameengine.ring"
1095 oGameState = new GameState
1098 title = "Stars Fighter!"
1101 file = "images/menu1.jpg"
1102 x = 0 y=0 width=800 height = 600 scaled = true animate = false
1103 keypress = func ogame,oself,nKey {
1104 if nkey = key_esc or nKey = GE_AC_BACK
1106 but nKey = key_space
1107 oGameState.startplay=true
1111 mouse = func ogame,oself,nType,aMouseList {
1112 if nType = GE_MOUSE_UP
1113 oGameState.startplay=true
1121 file = "fonts/pirulen.ttf"
1122 text = "Stars Fighter"
1128 file = "fonts/pirulen.ttf"
1129 text = "Version 1.0"
1135 file = "fonts/pirulen.ttf"
1136 text = "(C) 2016, Mahmoud Fayed"
1143 file = "fonts/pirulen.ttf"
1144 text = "Press Space to start"
1150 file = "fonts/pirulen.ttf"
1151 text = "Press Esc to Exit"
1155 file = "sound/music1.wav"
1159 if oGameState.startplay
1167 func playstart oGame
1169 oSound = New Sound {
1170 file = "sound/music2.wav"
1175 if ogame.shutdown = true and oGameState.value = 0
1189 title = "Stars Fighter!"
1192 file = "images/stars.jpg"
1196 direction = ge_direction_dec
1197 type = ge_type_background
1198 state = func ogame,oself {
1201 direction = ge_direction_inc
1203 but x = 0 and direction = ge_direction_inc
1204 direction = ge_direction_dec
1212 file = "images/player.png"
1214 type = ge_type_player
1215 x = 400 y =400 width=100 height=100
1216 animate=false move=true Scaled=true
1217 mouse = func ogame,oself,nType,aMouseList {
1219 if not ( aMouseList[GE_MOUSE_X] >= oSelf.x and
1220 aMouseList[GE_MOUSE_X] <= oSelf.x+oSelf.width and
1221 aMouseList[GE_MOUSE_Y] >= oself.y and
1222 aMouseList[GE_MOUSE_Y] <= oSelf.y+oSelf.height )
1224 if nType = GE_MOUSE_DOWN
1225 if aMouseList[1] < oSelf.X # 左
1230 if aMouseList[2] < oSelf.Y # 上
1238 if nType = GE_MOUSE_UP
1239 cFunc = oself.keypress
1240 call cFunc(oGame,oSelf,Key_Space)
1244 keypress = func oGame,oself,nkey {
1249 file = "images/rocket.png"
1257 direction = ge_direction_decvertical
1258 state = func oGame,oSelf {
1259 for x in oGame.aObjects
1260 if x.type = ge_type_enemy
1261 if oself.x >= x.x and oself.y >= x.y and
1262 oself.x <= x.x + x.width and
1263 oself.y <= x.y + x.height
1264 showfire(oGame,x.x+40,x.y+40)
1265 ogame.remove(x.nindex)
1266 oGameState.score+=10
1267 oGameState.enemies--
1276 but nkey = key_esc or nKey = GE_AC_BACK ogame.shutdown()
1279 state = func oGame,oSelf {
1283 if x > ogame.screen_w-width x= ogame.screen_w - width ok
1284 if y > ogame.screen_h-height y=ogame.screen_h-height ok
1288 for g = 1 to oGameState.enemies
1291 type = ge_type_enemy
1292 file = "images/enemy.png"
1294 x = g*random(50) y =g width=100 height=100
1295 animate=true Scaled=true
1296 direction = ge_direction_random
1297 state = func oGame,oSelf {
1301 if x > ogame.screen_w-width x= ogame.screen_w - width ok
1302 if y > ogame.screen_h-height y=ogame.screen_h-height ok
1308 file = "images/rocket2.png"
1311 y = oself.y + oself.height+ 30
1314 point = ogame.screen_h+30
1316 direction = ge_direction_incvertical
1317 state = func oGame,oSelf {
1318 x = oGame.aObjects[oGameState.playerindex]
1319 if oself.x >= x.x and oself.y >= x.y and
1320 oself.x <= x.x + x.width and
1321 oself.y <= x.y + x.height
1322 if oGameState.value > 0
1323 oGameState.value-=10
1325 ogame.remove(oself.nindex)
1326 checkgameover(oGame)
1337 file = "fonts/pirulen.ttf"
1338 text = "Destroy All Enemies!"
1340 color = GE_COLOR_GREEN
1342 direction = ge_direction_incvertical
1349 file = "fonts/pirulen.ttf"
1350 text = "Score : " + oGameState.score
1352 state = func oGame,oSelf { oSelf { text = "Score : " + oGameState.score } }
1358 file = "fonts/pirulen.ttf"
1359 text = "Energy : " + oGameState.value
1361 state = func oGame,oSelf { oSelf { text = "Energy : " + oGameState.value } }
1367 file = "fonts/pirulen.ttf"
1368 text = "Level : " + oGameState.level
1375 if oGameState.gameresult return ok
1376 if oGameState.enemies = 0
1377 oGameState.gameresult = true
1379 if oGameState.level < 30
1383 file = "fonts/pirulen.ttf"
1384 text = "Level Completed!"
1387 state = func ogame,oself {
1389 ogame.shutdown = true
1391 oGameState.enemies = oGameState.level
1392 oGameState.gameresult = false
1401 file = "fonts/pirulen.ttf"
1402 text = "You Win !!!"
1404 state = func ogame,oself {
1406 ogame.shutdown = true
1407 oGameState.value = 0
1415 func checkgameover ogame
1416 if oGameState.gameresult return ok
1417 if oGameState.value <= 0
1418 oGameState.gameresult = true
1424 file = "fonts/pirulen.ttf"
1425 text = "Game Over !!!"
1427 state = func ogame,oself {
1429 ogame.shutdown = true
1434 showfire(oGame,oGame.aObjects[oGameState.PlayerIndex].x+40,
1435 oGame.aObjects[oGameState.PlayerIndex].y+40)
1436 oGame.aObjects[oGameState.PlayerIndex].enabled = false
1437 oGame.remove(oGameState.PlayerIndex)
1441 func showfire oGame,nX,nY
1444 file = "images/fire.png"
1451 state = func oGame,oSelf {
1460 oGame.remove(oself.nIndex)
1480 .. image:: starsfighter.png
1485 pair: 2D ゲームエンジン; Flappy Bird 3000 ゲーム
1487 Flappy Bird 3000 ゲーム
1488 =======================
1490 Flappy Bird 3000 ゲームのソースコード
1492 .. code-block:: ring
1496 # 2016, Mahmoud Fayed <msfclipper@yahoo.com>
1500 Load "gameengine.ring"
1509 oGameState = New GameState
1512 title = "Flappy Bird 3000"
1515 file = "images/fbback.png"
1516 x = 0 y=0 width=800 height = 600 scaled = true animate = false
1517 keypress = func ogame,oself,nKey {
1518 if nkey = key_esc or nKey = GE_AC_BACK
1520 but nKey = key_space
1521 oGameState.startplay=true
1525 mouse = func ogame,oself,nType,aMouseList {
1526 if nType = GE_MOUSE_UP
1527 cFunc = oself.keypress
1528 call cFunc(oGame,oSelf,Key_Space)
1535 file = "fonts/pirulen.ttf"
1536 text = "Flappy Bird 3000"
1542 file = "fonts/pirulen.ttf"
1543 text = "Version 1.0"
1549 file = "fonts/pirulen.ttf"
1550 text = "(C) 2016, Mahmoud Fayed"
1557 file = "fonts/pirulen.ttf"
1558 text = "To Win Get Score = 3000"
1565 file = "fonts/pirulen.ttf"
1566 text = "Press Space to start"
1572 file = "fonts/pirulen.ttf"
1573 text = "Press Esc to Exit"
1578 file = "images/fbbird.png"
1588 direction = ge_direction_random
1589 state = func oGame,oSelf {
1602 if x >= 750 x= 750 ok
1609 file = "sound/music2.wav"
1612 if oGameState.startplay
1621 func playstart oGame
1626 Title = "Flappy Bird 3000"
1628 file = "images/fbback.png"
1629 x = 0 y=0 width=800 height = 600 scaled = true animate = false
1630 keypress = func ogame,oself,nKey {
1631 if nkey = key_esc or nKey = GE_AC_BACK
1641 [0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],
1642 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],
1643 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0],
1644 [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0],
1645 [0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0],
1646 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
1647 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],
1648 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0]
1651 aImages = ["images/fbwall.png","images/fbwallup.png",
1652 "images/fbwalldown.png"]
1653 state = func oGame,oSelf {
1654 if oGameState.gameresult = false
1655 px = oGame.aObjects[3].x
1656 py = oGame.aObjects[3].y
1664 if nCol=11 or nCol=15 or nCol=19 or nCol=23 or nCol=27
1665 if nCol != oGameState.lastcol
1666 oGameState.lastcol = nCol
1667 oGameState.Score += 100
1670 file = "sound/sfx_point.wav"
1676 if oSelf.getvalue(px+40,py) != 0 or
1677 oSelf.getvalue(px+40,py+40) != 0 or
1678 oSelf.getvalue(px,py) != 0 or
1679 oSelf.getvalue(px,py+40) != 0
1680 oGameState.gameresult = true
1686 file = "fonts/pirulen.ttf"
1687 text = "Game Over !!!"
1689 state = func ogame,oself {
1691 ogame.shutdown = true
1697 file = "sound/sfx_die.wav"
1705 file = "sound/sfx_hit.wav"
1714 file = "images/fbbird.png"
1723 state = func oGame,oSelf {
1736 if not oGameState.playerwin
1738 if oGameState.down = 0
1748 keypress = func ogame,oself,nKey {
1749 if oGameState.gameresult = false
1753 oGameState.down = 60
1759 mouse = func ogame,oself,nType,aMouseList {
1760 if nType = GE_MOUSE_UP
1761 cFunc = oself.keypress
1762 call cFunc(oGame,oSelf,Key_Space)
1771 file = "fonts/pirulen.ttf"
1772 text = "Score : " + oGameState.score
1774 state = func oGame,oSelf {
1775 oSelf { text = "Score : " + oGameState.score }
1795 for x = 10 to 24 step 4
1796 aVar = aV[ (random(10)+1) ]
1798 aMap[y][x] = aVar[y]
1803 if oGameState.score = 3000
1804 oGameState.gameresult = true
1805 oGameState.playerwin = true
1811 file = "fonts/pirulen.ttf"
1812 text = "You Win !!!"
1814 state = func ogame,oself {
1816 ogame.shutdown = true
1817 oGameState.value = 0
1834 .. image:: flappybird.png
1835 :alt: Flappy Bird 300
1839 pair: 2D ゲームエンジン; Super Man 2016 ゲーム
1842 =====================
1844 Super Man 2016 ゲームのソースコード
1846 .. code-block:: ring
1850 # 2016, Mahmoud Fayed <msfclipper@yahoo.com>
1854 Load "gameengine.ring"
1862 oGameState = new GameState
1865 title = "Super Man 2016"
1868 file = "images/superman.jpg"
1869 x = 0 y=0 width=800 height = 600 scaled = true animate = false
1870 keypress = func ogame,oself,nKey {
1871 if nkey = key_esc or nKey = GE_AC_BACK
1873 but nKey = key_space
1874 oGameState.startplay=true
1878 mouse = func ogame,oself,nType,aMouseList {
1879 if nType = GE_MOUSE_UP
1880 oGameState.startplay=true
1884 state = func ogame,oself {
1898 file = "fonts/pirulen.ttf"
1899 text = "Super Man 2016"
1905 file = "fonts/pirulen.ttf"
1906 text = "Version 1.0"
1912 file = "fonts/pirulen.ttf"
1913 text = "(C) 2016, Mahmoud Fayed"
1920 file = "fonts/pirulen.ttf"
1921 text = "Press Space to start"
1927 file = "fonts/pirulen.ttf"
1928 text = "Press Esc to Exit"
1933 file = "images/superman.png"
1943 direction = ge_direction_random
1944 state = func oGame,oSelf {
1957 if x >= 750 x= 750 ok
1964 file = "sound/music2.wav"
1967 if oGameState.startplay
1976 func playstart oGame
1981 Title = "Super Man 2016"
1983 file = "images/supermancity.jpg"
1984 x = 0 y=0 width=800 height = 600 scaled = true animate = false
1990 [0,0,0,4,4,4,0,0,0,1,0,0,0,1,4,4,0,1,0,0,0,0,4,4,0,1,4,
1991 4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,0,0,0,1,0,0,0,1,0,3,3,3,5,3,3,3,3,0],
1992 [0,0,4,0,4,0,4,0,0,1,0,0,0,3,4,4,4,1,0,0,0,0,4,4,0,1,4,
1993 4,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,1,4,1,0,0,0,1,0,0,0,1,0,4,4,4,4,4,4,4,4,0],
1994 [0,0,0,4,4,4,0,0,0,1,0,0,0,4,4,4,4,1,0,0,0,0,0,0,0,3,4,
1995 4,4,0,0,4,0,0,0,0,0,0,4,2,0,0,4,1,4,1,4,2,4,1,0,2,0,1,0,4,4,4,4,4,4,4,4,0],
1996 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
1997 0,0,0,0,4,4,4,4,4,4,4,4,1,0,0,4,1,4,1,4,1,4,1,0,1,0,1,0,2,2,2,2,2,2,2,2,0],
1998 [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
1999 0,0,0,0,2,0,0,0,0,0,2,0,3,0,0,0,1,4,1,4,1,4,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0],
2000 [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,0,0,
2001 0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,4,3,4,1,4,3,0,1,0,3,0,1,0,0,0,0,0,0,0,0],
2002 [0,0,2,0,0,2,0,0,2,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,
2003 0,0,0,0,1,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0],
2004 [0,0,1,0,0,1,0,0,1,3,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,
2005 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0]
2007 aImages = ["images/smwall.png","images/smwallup.png",
2008 "images/smwalldown.png","images/smstar.png",
2009 "images/smkey.png","images/smstar2.png"]
2013 type = ge_type_enemy
2015 file = "images/smhome.png"
2022 state = func oGame,oSelf {
2024 x = 5000 + oGame.aObjects[2].x
2025 if x < 0 or x > SCREEN_W return ok
2027 if oGameState.gameresult or oGameState.DoorKey = false return ok
2028 if oGame.aObjects[oGameState.playerindex].x > oself.x + 100 and
2029 oGame.aObjects[oGameState.playerindex].y > oself.y + 50
2030 oGameState.gameresult = true
2033 file = "images/smwin.jpg"
2034 x=0 y=0 width=800 height=600
2035 scaled = true animate=false
2036 state = func ogame,oself {
2043 ogame.shutdown = true
2055 file = "images/superman.png"
2064 state = func oGame,oSelf {
2066 checkstarskeycol(oGame,oSelf)
2068 if not oGameState.playerwin
2070 file = "images/superman.png"
2074 if checkwall2(oGame,oSelf,0,5,[2,1])
2085 keypress = func ogame,oself,nKey {
2086 if oGameState.gameresult = false
2089 if nkey = key_up and checkwall(oGame,oSelf,0,-40)
2090 oGameState.value -= 1
2091 checkgameover(oGame)
2092 file = "images/supermanup.png"
2096 oGameState.down = 10
2098 but nkey = key_down and checkwall(oGame,oSelf,0,40)
2099 file = "images/supermandown.png"
2103 but nKey = key_right and checkwall(oGame,oSelf,10,0)
2104 file = "images/supermanright.png"
2108 if oGame.aObjects[2].x > -4500
2109 oGame.aObjects[2].x -= 50
2110 callenemystate(oGame)
2113 if checkwall(oGame,oSelf,10,0)
2117 if checkwall(oGame,oSelf,-10,0)
2125 but nKey = key_left and checkwall(oGame,oSelf,-10,0)
2126 file = "images/supermanleft.png"
2131 if oGame.aObjects[2].x != 0
2132 oGame.aObjects[2].x += 50
2133 callenemystate(oGame)
2137 but nkey = key_esc or nKey = GE_AC_BACK
2143 mouse = func ogame,oself,nType,aMouseList {
2144 if nType = GE_MOUSE_DOWN
2145 oGameState.moveplayer = TRUE
2146 But nType = GE_MOUSE_UP
2147 oGameState.moveplayer = FALSE
2149 if oGameState.moveplayer = TRUE
2150 if aMouseList[GE_MOUSE_X] < oSelf.X # 左
2151 cFunc = oself.keypress
2152 call cFunc(oGame,oSelf,Key_left)
2154 cFunc = oself.keypress
2155 call cFunc(oGame,oSelf,Key_right)
2157 if aMouseList[GE_MOUSE_Y] < oSelf.Y # 上
2158 cFunc = oself.keypress
2159 call cFunc(oGame,oSelf,Key_up)
2161 cFunc = oself.keypress
2162 call cFunc(oGame,oSelf,Key_down)
2170 addenemy(oGame,1550)
2171 addenemy(oGame,2350)
2172 addenemy(oGame,3350)
2173 addenemy(oGame,3500)
2174 addenemy(oGame,3670)
2175 addenemy(oGame,3840)
2181 file = "fonts/pirulen.ttf"
2182 text = "Score : " + oGameState.score
2184 state = func oGame,oSelf {
2185 oSelf { text = "Score : " + oGameState.score }
2193 file = "fonts/pirulen.ttf"
2194 text = "Energy : " + oGameState.value
2196 state = func oGame,oSelf { oSelf { text = "Energy : " + oGameState.value } }
2201 func inlist nValue,aList
2209 func checkwall oGame,oself,diffx,diffy
2211 return checkwall2(oGame,oself,diffx,diffy,aList)
2213 func checkwall2 oGame,oself,diffx,diffy,aList
2214 xPos = oSelf.x + diffx
2215 yPos = oSelf.y + diffy
2216 nValue = oGame.aObjects[2].getvalue(xPos,yPos)
2217 nValue = inlist(nValue,aList)
2219 if nValue = 0 return nValue ok
2221 xPos = oSelf.x + diffx
2222 yPos = oSelf.y + diffy + oSelf.height
2223 nValue = oGame.aObjects[2].getvalue(xPos,yPos)
2224 nValue = inlist(nValue,aList)
2226 if nValue = 0 return nValue ok
2228 xPos = oSelf.x + diffx + oSelf.width
2229 yPos = oSelf.y + diffy
2230 nValue = oGame.aObjects[2].getvalue(xPos,yPos)
2231 nValue = inlist(nValue,aList)
2233 if nValue = 0 return nValue ok
2235 xPos = oSelf.x + diffx + oSelf.width
2236 yPos = oSelf.y + diffy + oSelf.height
2237 nValue = oGame.aObjects[2].getvalue(xPos,yPos)
2238 nValue = inlist(nValue,aList)
2240 if nValue = 0 return nValue ok
2244 func checkopenwall oGame
2245 if oGameState.score = 900
2246 oGame.aObjects[2].aMap[3][10] = 3
2247 oGame.aObjects[2].aMap[4][10] = 0
2248 oGame.aObjects[2].aMap[5][10] = 0
2249 oGame.aObjects[2].aMap[6][10] = 0
2250 oGame.aObjects[2].aMap[7][10] = 0
2251 oGame.aObjects[2].aMap[8][10] = 0
2252 but oGameState.score = 1800
2253 oGame.aObjects[2].aMap[3][18] = 3
2254 oGame.aObjects[2].aMap[4][18] = 0
2255 oGame.aObjects[2].aMap[5][18] = 0
2256 oGame.aObjects[2].aMap[6][18] = 0
2257 oGame.aObjects[2].aMap[7][18] = 0
2258 oGame.aObjects[2].aMap[8][18] = 0
2259 but oGameState.score = 5500
2260 oGame.aObjects[2].aMap[1][44] = 0
2261 oGame.aObjects[2].aMap[2][44] = 0
2262 oGame.aObjects[2].aMap[3][44] = 2
2266 func checkgameover ogame
2267 if oGameState.gameresult return ok
2268 if oGameState.value <= 0
2269 oGameState.value = 0
2270 oGameState.gameresult = true
2276 file = "fonts/pirulen.ttf"
2277 text = "Game Over !!!"
2279 state = func ogame,oself {
2281 ogame.shutdown = true
2286 showfire(oGame,oGame.aObjects[oGameState.PlayerIndex].x+40,
2287 oGame.aObjects[oGameState.PlayerIndex].y+40)
2288 oGame.aObjects[oGameState.PlayerIndex].enabled = false
2289 oGame.remove(oGameState.PlayerIndex)
2293 func showfire oGame,nX,nY
2296 file = "images/fire.png"
2303 state = func oGame,oSelf {
2312 oGame.remove(oself.nIndex)
2320 func addenemy oGame,xPos
2324 type = ge_type_enemy
2325 file = "images/smenemy.png"
2327 x = xPos y =10 width=100 height=100
2328 animate=true Scaled=true
2329 direction = GE_DIRECTION_NOMOVE
2331 state = func oGame,oSelf {
2333 x = oSelf.temp + oGame.aObjects[2].x
2336 if x > SCREEN_W or x < 0 return ok
2340 if oGameState.gameresult return ok
2344 file = "images/smrocket.png"
2348 y = oself.y + oself.height+ 30
2351 point = ogame.screen_h+30
2353 direction = ge_direction_incvertical
2354 xvalue = oGame.aObjects[2].x
2355 temp = oself.x + 30 - xvalue
2356 state = func oGame,oSelf {
2357 oself { x = oSelf.temp + oGame.aObjects[2].x }
2358 x = oGame.aObjects[oGameState.playerindex]
2359 if oself.x >= x.x and oself.y >= x.y and
2360 oself.x <= x.x + x.width and
2361 oself.y <= x.y + x.height
2362 if oGameState.value > 0
2363 oGameState.value-=1000
2365 ogame.remove(oself.nindex)
2366 checkgameover(oGame)
2375 ogame.lbraceend = true
2378 func checkstarskey oGame,oSelf,nValue,nRow,nCol
2381 oGame.aObjects[2].aMap[nRow][nCol] = 6
2382 oGameState.Score += 100
2383 checkopenwall(oGame)
2386 file = "sound/sfx_point.wav"
2389 oGame.aObjects[2].aMap[nRow][nCol] = 0
2390 oGameState.DoorKey = true
2391 oGameState.Score += 500
2392 checkopenwall(oGame)
2395 file = "sound/sfx_point.wav"
2399 func checkstarskeycol oGame,oSelf
2400 nValue = oGame.aObjects[2].getvalue(oSelf.x,oSelf.y)
2401 nRow = oGame.aObjects[2].getrow(oSelf.x,oSelf.y)
2402 nCol = oGame.aObjects[2].getcol(oSelf.x,oSelf.y)
2403 checkstarskey(oGame,oSelf,nValue,nRow,nCol)
2405 nValue = oGame.aObjects[2].getvalue(oSelf.x+oSelf.width,oSelf.y+oSelf.height)
2406 nRow = oGame.aObjects[2].getrow(oSelf.x+oSelf.width,oSelf.y+oSelf.height)
2407 nCol = oGame.aObjects[2].getcol(oSelf.x+oSelf.width,oSelf.y+oSelf.height)
2408 checkstarskey(oGame,oSelf,nValue,nRow,nCol)
2410 nValue = oGame.aObjects[2].getvalue(oSelf.x+oSelf.width,oSelf.y)
2411 nRow = oGame.aObjects[2].getrow(oSelf.x+oSelf.width,oSelf.y)
2412 nCol = oGame.aObjects[2].getcol(oSelf.x+oSelf.width,oSelf.y)
2413 checkstarskey(oGame,oSelf,nValue,nRow,nCol)
2415 nValue = oGame.aObjects[2].getvalue(oSelf.x,oSelf.y+oSelf.height)
2416 nRow = oGame.aObjects[2].getrow(oSelf.x,oSelf.y+oSelf.height)
2417 nCol = oGame.aObjects[2].getcol(oSelf.x,oSelf.y+oSelf.height)
2418 checkstarskey(oGame,oSelf,nValue,nRow,nCol)
2420 func callenemystate oGame
2421 for t in oGame.aObjects
2423 if type = GE_TYPE_ENEMY
2444 .. image:: superman.png
2445 :alt: Super Man 2016