CHATGPTでインベーダーゲームを書かせてみた。
イメージ的には、インベーダーが体当たりで降りてくるイメージだが、ソース的には十分な内容だった。
玉を発射したりするルーチンは無いけど、たぶんココからちょっと指示しただけで、追加してくれると思う。
なんか妙に懐かしく、PC8001のゲームが作りたくなってきた。
; インベーダーゲーム
; Z80アセンブラで書いたサンプルプログラム
org 100h
; スタートアップルーチン
startup:
ld a,#0
ld (score),a ; スコアをゼロに設定
ld (lives),a ; 残機をゼロに設定
call init ; 初期化
call play ; ゲーム開始
jp finish ; 終了
; 初期化ルーチン
init:
ld a,#20 ; 画面の幅を20文字に設定
ld (width),a
ld a,#16 ; 画面の高さを16行に設定
ld (height),a
call clear_screen ; 画面を消去
call create_ship ; 自機を作成
call create_invader ; インベーダーを作成
jp startup ; スタートアップに戻る
; 画面を消去するルーチン
clear_screen:
ld hl,#0000h ; 画面の先頭アドレスを設定
ld bc,#4000h ; 画面サイズを設定
ld a,#20h ; 画面を消去するためのデータ
ldir ; 全てを20hで埋め尽くす
jp startup ; スタートアップに戻る
; 自機を作成するルーチン
create_ship:
ld hl,#4000h ; 画面の底端をHLに設定
ld (ship_pos),hl ; 自機の座標を記憶
ld a,#0fh ; 自機を作成するためのデータ
ld (hl),a ; 自機を画面に描画
jp startup ; スタートアップに戻る
; インベーダーを作成するルーチン
create_invader:
ld hl,#0000h ; 画面の先頭アドレスをHLに設定
ld a,#0eh ; インベーダーを作成するためのデータ
ld (hl),a ; インベーダーを画面に描画
jp startup ; スタートアップに戻る
; ゲームを開始するルーチン
play:
call draw_screen ; 画面を描画
call control ; 操作を受け付ける
call move_ship ; 自機を動かす
call move_invader ; インベーダーを動かす
call check_collision ; 衝突をチェックする
call check_end ; ゲーム終了をチェックする
jp play ; 繰り返す
; 画面を描画するルーチン
draw_screen:
ld hl,#0000h ; 画面の先頭アドレスをHLに設定
ld bc,#4000h ; 画面サイズを設定
ldir ; 画面を描画
jp startup ; スタートアップに戻る
; 操作を受け付けるルーチン
control:
in a,(#00h) ; キー入力を受け取る
cp #01h ; 左キーが押されたかチェック
jp z,move_left ; 押されていたら左に移動
cp #02h ; 右キーが押されたかチェック
jp z,move_right ; 押されていたら右に移動
jp startup ; スタートアップに戻る
; 左に移動するルーチン
move_left:
ld a,#0fh ; 自機を消去するためのデータ
ld (ship_pos),a ; 自機を消去
dec hl ; 左に1文字移動
ld (ship_pos),hl ; 自機の座標を記憶
ld a,#0fh ; 自機を作成するためのデータ
ld (hl),a ; 自機を描画
jp startup ; スタートアップに戻る
; 右に移動するルーチン
move_right:
ld a,#0fh ; 自機を消去するためのデータ
ld (ship_pos),a ; 自機を消去
inc hl ; 右に1文字移動
ld (ship_pos),hl ; 自機の座標を記憶
ld a,#0fh ; 自機を作成するためのデータ
ld (hl),a ; 自機を描画
jp startup ; スタートアップに戻る
; インベーダーを動かすルーチン
move_invader:
ld a,(inv_pos) ; インベーダーの座標を取得
ld hl,a ; HLに設定
ld a,#0eh ; インベーダーを消去するためのデータ
ld (hl),a ; インベーダーを消去
inc hl ; インベーダーを1文字右へ移動
ld (inv_pos),hl ; インベーダーの座標を記憶
ld a,#0eh ; インベーダーを作成するためのデータ
ld (hl),a ; インベーダーを描画
jp startup ; スタートアップに戻る
; 衝突をチェックするルーチン
check_collision:
ld a,(ship_pos) ; 自機の座標を取得
cp (inv_pos) ; インベーダーの座標をチェック
jp z,game_over ; 衝突したらゲームオーバー
jp startup ; スタートアップに戻る
; ゲームオーバー時の処理
game_over:
dec (lives) ; 残機を減らす
ld a,(lives) ; 残機を取得
or a ; 残機がゼロかチェック
jp z,finish ; ゼロなら終了
call create_invader ; インベーダーを再作成
jp startup ; スタートアップに戻る
; ゲーム終了をチェックするルーチン
check_end:
ld hl,#4000h ; 画面の底端をHLに設定
ld a,(inv_pos) ; インベーダーの座標を取得
cp hl ; 画面の底端と比較
jp nc,startup ; 画面の底端以外ならスタートアップに戻る
inc (score) ; スコアを1増やす
call create_invader ; インベーダーを再作成
jp startup ; スタートアップに戻る
; 終了ルーチン
finish:
halt ; プログラムを終了
; 変数定義
score defb 00h ; スコア
lives defb 00h ; 残機
width defb 20h ; 画面の幅
height defb 16h ; 画面の高さ
ship_pos defw 0000h ; 自機の座標
inv_pos defw 0000h ; インベーダーの座標
end