- タイトル
インベーダー - 開発環境
IchigojamBASIC1.2.1 - 内容
宇宙からインベーダーが大挙して攻めてきます。
あなたは地球を守るためインベーダーを迎撃しなくてはなりません。 - 遊び方
画面上方から徐々に侵略してくるインベーダーを、画面下部の砲台よりミサイルを打って撃墜してください。
インベーダーの攻撃に当たる、もしくはインベーダーが地上に着いて地球侵略された時点でゲームオーバーです。 - 操作方法
[1]キー 左移動
[2]キー 右移動
[スペース]キー ミサイル発射 - プログラムのしくみ
機械語部分(プログラム1)とBASIC部分(プログラム2)に分かれています。
プログラム1の2行目はキャラクタ設定を行っています。
機械語部分はBASE16というエンコード方法で変換されています。
(8bitのうち上位4bitと下位4bitをそれぞれ@~Oの文字に変換)
インベーダーの動き、インベーダーのミサイル、自機のミサイルなど、処理速度が必要な部分を機械語で処理しています。
画面描画、自機の動き、UFOの発生、得点、サウンドなど比較的処理速度の必要でない部分をBASICで処理しています。
変数については、変数領域の半分くらいまで機械語プログラムが書き込まれているため、変数の後半(Z~W)のみを使用しています。 - (5)プログラムの具体的な入力方法
機械語部分は入力を間違えると操作不能になってしまうので、間違えないようにしてください。
もしプログラムを実行して操作不能になってしまった場合は、一度IchigoJamの電源を切ってから再度電源を入れ直してください。
まずプログラム1を入力して保存、次にプログラム2を入力してしてください。
遊ぶ時は、まずプログラム1をロードして実行します。するとメモリ内に機械語プログラムが書き込まれます。
次にプログラム2をロードして実行しするとゲームが始まります。
プログラム1の8行目のendを「LRUN(プログラム2の保存番号)」に変更すると、プログラム1を実行後に自動でプログラム2を読み込み実行させることができます。 - プログラムの改造
プログラム2(BASICプログラム)の数値の変更による難易度変更は下記の通りです。
80行のFOR文のループ数を大きくすると、自機ミサイルの速度が上がります。
同じく80行のWAIT文の式を変更するとインベーダーの移動速度が変わります。(現在は点数に連動)
120行のWの値を変えるとインベーダーのミサイルの発生率が変わります。
130行のWの値を変えるとUFOの発生率が変わります。
他の改造については、BASIC部分にメモリの余裕があるので改造しやすいと思います。
(例:自機数を増やす、面ごとにインベーダーの初期描画位置を下げるなど)
変数領域まで機械語プログラムが書き込まれているため、改造の際は使用する変数をK以後にしてください。
機械語プログラム(プログラム1)
機械語ルーチンへの渡し値 | |
---|---|
#770-#771 | 自機ミサイル位置 |
#77E | 面クリアフラグ |
#77F | インベーダー移動方向 |
機械語ルーチンから戻り値(USR関数) | |
1 | Invader撃墜 |
2 | UFO撃墜 |
#FF | 自機被弾 |
キャラクタ表 | |
---|---|
#E0 | 上段インベーダー |
#E1 | 中段インベーダー |
#E2 | 下段インベーダー |
#E3 | 敵ミサイル |
#E4 | 自ミサイル |
#E5 | 砲台 |
#E6 | UFO |
#E7 | 爆発 |
画面構成 | |
---|---|
#900-#91F | SCORE |
#920-#93F | UFO |
#920-BE0 | Invaders |
#BE0-BFF | SHIP |
BASICプログラム(プログラム2)
変数一覧表 | |
---|---|
Z | 点数 |
Y | 得点(1or2)またはゲームオーバーフラグ(=#FF) |
X | 自機の位置 |
W | ループ用 |
各行の処理 | |
---|---|
10行 | コメント行 |
20行 | キャラクタ定義 |
30行 | 点数クリア |
40行 | 初期設定() |
50行 | 初期画面描画 |
60行 | インベーダー移動 |
70行 | 面クリア判定 |
80行 | インベーダーのミサイル移動 |
90行 | 自機のミサイル移動 |
100行 | キー入力:ミサイル発射 |
110行 | 自機左右移動 |
120行 | 自機描画 |
130行 | インベーダーのミサイル発生 |
140行 | UFO出現 |
150行 | 繰り返し |
160行 | ゲームオーバー判定:加点処理 |
機械語処理については、機械語プログラムのコメントを参照してください。
インベーダー(プログラム1) |
---|
1'invader1 2CLS:CLP:CLV:W=#50:LET[0],#0B,#EC,#ED,#F2,#1E,#F0,#F1,#F4:FORZ=0TO7:COPY(#E0+Z)*8,[Z]*8,8:NEXT 3Z="G@KD@@BFIABDBD@A@OCDFCAHAJGHN@BJ@AMKNBBJA@MMEJGHN@BJ@AMKNBBJ@KMMB@CDBE@IKOBMO@MKGGBDBD@A@OCDFBEL@@BJBAM@@ABJCFM@KOBDBD@AFEAHBJGHN@BJ@KMKNBBJ@IMLBC@IKLBKABMJ@@BC":Y=#780:GSB9 4Z="BKG@B@CEBKGHNEBK@LM@BJG@@ACLBE@II@BMNKMAGGBDBD@A@OCDFBEL@ABCEJD@FBEDMINGOOB@BLN@KOBDBD@AFDAHBBGHN@BJ@JMKNBBJ@HMLAFALFCGHNDBK@AMA@AB@@@BBFBG@@@BBBBG@@ACLFCAJAK@J":Y=#7D0:GSB9 5Z="@HBKNLMAAEN@IBBDBD@AFDAHFBGHN@BJ@JMKNBBJ@HMLAFALBCGHNDBK@AMA@AB@@@BBBBG@@@BBFBG@@ACDFCAJAK@IKOBKNLMAGGBBAB@A@NCBEFEDG@KLG@DG@@@@C@KDB@BEKOBDBD@A@OCDFDAHBBGHNCBJ":Y=#820:GSB9 6Z="@LMA@@BCBCG@FCAJAK@IKNBK@FMJFCEM@@BK@BM@NEBK@AMAOOB@FBEE@ACLFCAJAK@IIABKNJMAC@KLG@DG@@@@@@@@@@@@G@KDGGBEBM@AFLEJ@@BLAEM@@@BFFFEDB@CLBBDFBC@IIBBK@NMKNDBCFBEL@BB@":Y=#870:GSB9 7Z="NFBJ@FM@@@B@BFDFN@BJ@DMKNCBJ@BML@AB@@@BC@@BFFCEDFNEBG@KLG@DG":Y=#8C0:W=#1E:GSB9 8END 9FORX=YTOY+W-1:POKEX,PEEK(Z)&15<<4+PEEK(Z+1)&15:Z=Z+2:?"#";HEX$(X),HEX$(PEEK(X)):NEXT:RTN |
インベーダー(プログラム2) |
---|
10 'invader2 20 POKE#E0*8,#42,#24,#7E,#DB,#FF,#BD,#24,#42,#3C,#7E,#FF,#99,#FF,#FF,#66,#DB,#18,#3C,#7E,#DB,#FF,#5A,#81,#42 30 Z=0 40 CLS:?"SCORE:":LC8,0:?Z:POKE#770,0,0:POKE#77E,0,0:X=#BF0:POKEX,#E5 50 FORW=0TO4:FORY=0TO7:LCY*3+1,8-W*2+1:?CHR$(#E0+W/2):NEXT:POKE#B40+3+W*6,1,1,1:NEXT 60 Y=USR(#780,0):GSB160:BEEP255,1:IFYPOKE#770,0,0 70 IFPEEK(#77E)=0LC10,10:?"CLEAR":PLAY"O4BO5GB":WAIT60:GOTO40 80 Y=USR(#860,0):GSB160 90 FORW=0TO4:Y=USR(#8A0,0):GSB160:WAIT(100-Z)/10 100 Y=INKEY()-50:POKE#1003,0:IFY=-18ANDPEEK(#771)=0THENPOKE#770,#C0+(X-#BE0),#0B:GOTO120 110 IFABS(Y)=1POKEX,0:X=X+Y:IFX<#BE0ORX>#BFFX=X-Y 120 POKEX,#E5:NEXT 130 W=3:Y=RND(#60*W):IFY%WIFPEEK(#A40+Y/W)=0POKE#A40+Y/W,#E3 140 W=#10:Y=RND(#20*W):IFPEEK(#920+Y/W)=#E6POKE#920+Y/W,0ELSEIFNOT(Y%W)IFPEEK(#920+Y/W)=0POKE#920+Y/W,#E6 150 GOTO60 160 IFYIFY=#FFPOKEX,#E7:LC10,10:?"GAME OVER":PLAY"C02EDC":ENDELSEZ=Z+Y:LC8,0:?Z 170 RTN |
プログラム1のアセンブラリスト |
---|
'インベーダー移動 usr(#780,0) '左端、右端チェック処理 push {r4,r5,r6} mov r6,0 '敵存在フラグクリア mov r4,#91 lsl r4,r4,4 add r4,#f '探索VRAM=#91F:右端 @lr_loop_down add r3,r4,r1 'R3=実VRAM ldrb r2,[r3,0] '右端キャラ cmp r2,#e0 blt @l_chk_down 'R2<#E0なら左端をチェック cmp r2,#e2 ble @vector_down 'R2<=#E2なら1段下げ処理へ @l_chk_down ldrb r2,[r3,1] '左端キャラ cmp r2,#e0 blt @chk_add_down 'R2<#E0なら1行下チェックへ cmp r2,#e2 ble @vector_down 'R2<=#E2なら1段下げ処理へ @chk_add_down add r4,#20 '1行下 lsr r5,r4,4 cmp r5,#bf blt @lr_loop_down 'R4<#BF*ならループ '左右移動に分岐処理 @lr_move mov r4,#77 lsl r4,r4,4 add r4,#f ldrb r2,[r4,r1] '#7FF=インベーダー移動方向 cmp r2,0 '0=右/1=左 beq @inv_r_move '右移動処理へ cmp r2,1 beq @inv_l_move '左移動処理へ '1段下げる処理 @vector_down mov r4,#bf '開始VRAM=#BF0 lsl r4,r4,4 @loop_down '1段下げループ add r5,r4,r1 'R5=実VRAM ldrb r2,[r5,0] cmp r2,#e0 blt @add_down 'R2<#E0なら左隣チェックへ cmp r2,#e2 bgt @add_down 'R2>#E2なら左隣アドレスへ lsr r3,r4,4 cmp r3,#bc '#BC*=最下行 bge @game_over 'R3>=#BC*ならゲームオーバー処理 mov r3,0 strb r3,[r5,0] '元位置クリア add r5,#20 ldrb r3,[r5,0] '1段下のキャラ cmp r3,#e5 beq @game_over '1段下が砲台ならゲームオーバー処理 strb r2,[r5,0] '1段下にインベーダー描画 @add_down sub r4,1 '左隣のアドレス lsr r5,r4,4 'アドレス#90* cmp r5,#90 bne @loop_down 'R5!=#90なら1段下げループへ '進行方向逆転 mov r4,#77 lsl r4,r4,4 add r4,#f ldrb r2,[r4,r1] '#7FF=インベーダー移動方向 mov r3,1 '0=右/1=左 eor r2,r3 '0,1を反転 strb r2,[r4,r1] bla @lr_move '左右移動に分岐処理 'ゲームオーバー処理 @game_over mov r0,#FF 'ゲームオーバーフラグ bla @end '右移動 @inv_r_move mov r4,#bf '開始VRAM=#BF0 lsl r4,r4,4 add r4,r4,r1 'R4=実VRAM @loop_rmov 'ループ開始 ldrb r2,[r4,0] '移動元のキャラクタ cmp r2,#e0 blt @add_rmov 'R2<#E0なら左隣アドレスへ cmp r2,#e2 bgt @add_rmov 'R2>#E2なら左隣アドレスへ mov r6,r2 '敵存在フラグ ldrb r3,[r4,1] '移動先のキャラクタ cmp r3,#e4 '自弾 bne @hit_rmov 'R3!=#E4ならキャラクタ移動へ mov r0,1 '撃墜フラグセット mov r2,0 'インベーダー消去 @hit_rmov strb r2,[r4,1] 'キャラクタを移動先に mov r2,0 strb r2,[r4,0] '元位置をクリア @add_rmov sub r4,1 '左隣のアドレス sub r3,r4,r1 lsr r3,r3,8 cmp r3,8 bne @loop_rmov 'R3!=#8**ならループへ bla @end @inv_l_move mov r4,#92 '開始VRAM=#920 lsl r4,r4,4 add r4,r4,r1 'R4=実VRAM @loop_lmov 'ループ開始 ldrb r2,[r4,1] '移動元のキャラクタ cmp r2,#e0 blt @add_lmov 'R2<#E0なら右隣アドレスへ cmp r2,#e2 bgt @add_lmov 'R2>#E2なら右隣アドレスへ mov r6,r2 '敵存在フラグ ldrb r3,[r4,0] '移動先のキャラクタ cmp r3,#e4 '自弾 bne @hit_lmov 'R3!=#E4ならキャラクタ移動へ mov r0,1 '撃墜フラグセット mov r2,0 'インベーダー消去 @hit_lmov strb r2,[r4,0] 'キャラクタを移動先に mov r2,0 strb r2,[r4,1] '元位置をクリア @add_lmov add r4,1 '右隣のアドレス sub r3,r4,r1 lsr r3,r3,4 cmp r3,#bf bne @loop_lmov 'R3!=#BF*ならループへ @end 'インベーダー移動終了処 mov r2,#77 lsl r2,r2,4 add r2,#e strb r6,[r2,r1] '敵存在フラグ=#77E pop {r4,r5,r6} ret nop '敵弾(全走査) usr(#860,0) push {r4,r5} mov r5,#20 '1行のアドレス増分 mov r4,#bf lsl r4,r4,4 add r4,#f '開始VRAM=#BFF add r4,r4,r1 'R4=実VRAM @loop_bomb ldrb r2,[r4,0] '移動元のキャラクタ cmp r2,#e3 '敵弾 bne @no_bomb 'R2!=#E3なら左隣のアドレスへ mov r3,0 strb r3,[r4,0] '元位置クリア sub r3,r4,r1 lsr r3,r3,4 cmp r3,#be bge @no_bomb 'R3>=#BE*なら左隣のアドレスへ ldrb r3,[r4,r5] '移動先のキャラ cmp r3,0 beq @mov_bomb '空白なら敵弾移動 cmp r3,#e5 '砲台 bne @no_bomb 'R3!=#E5なら左隣のアドレスへ mov r0,#FF 'ゲームオーバーフラグ @mov_bomb strb r2,[r4,r5] '敵弾移動 @no_bomb sub r4,1 '左隣のアドレス sub r3,r4,r1 lsr r3,r3,4 cmp r3,#91 'アドレス#91* bne @loop_bomb 'R3!=#91ならループへ pop {r4,r5} ret nop nop nop '自弾(自位置=#770) usr(#8A0,0) push {r4,r5,r6} mov r5,#77 '自弾位置ポインタ=#770 lsl r5,r5,4 ldrh r4,[r5,r1] '自弾位置 cmp r4,0 '自弾無し beq @exit_msl 'r4==0処理終了 mov r6,0 strb r6,[r4,r1] '元位置クリア sub r4,#20 '1行上 cpy r2,r4 '自弾1行上位置コピー lsr r3,r4,4 cmp r3,#92 'VRAM=#920 blt @exit_msl 'R3<=#920なら処理終了 mov r3,#e4 '自弾キャラクタ ldrb r2,[r4,r1] '1行上キャラクタ mov r0,2 'UFO=2pts cmp r2,#e6 'UFO=#E6 beq @clr_msl 'R2==#E6なら自弾クリアへ mov r0,0 'notUFO=0pts cpy r6,r4 cmp r2,#e0 blt @mov_msl 'R2<#E0なら自弾移動へ cmp r2,#e3 bgt @mov_msl 'R2>#E3なら自弾移動へ mov r0,1 'Invader=1pts @clr_msl mov r3,0 '自弾クリア mov r6,0 '自弾位置クリア @mov_msl strb r3,[r4,r1] '1行上に自弾orクリア @exit_msl '処理終了 strh r6,[r5,r1] '自弾位置保存 pop {r4,r5,r6} ret |
インベーダー1 http://tagiyasoft.blog.jp/invader1.bin
インベーダー2 http://tagiyasoft.blog.jp/invader2.bin
以下のように入力してD/Lしてください。
NEW ? MJ GET tagiyasoft.blog.jp/invader1.bin ? MJ GET tagiyasoft.blog.jp/invader2.bin |
ブラウザでD/LしてIchigoJamに転送する場合は、通信ソフトでバイナリ送信をしてください。
(例:TeraTermの場合は、メニューの[ファイル]-[ファイル送信]で当該ファイルを送信します)
コメント