見出し画像

ローグっぽい2D迷路探索ゲームを作る2(PowerShellで)

はじめに

ローグっぽい2D迷路探索ゲームを作る2回目です。

Windowsに標準搭載されているPowerShellを使って
ローグっぽい2D迷路探索ゲーム開発に挑戦します。

3回くらいの記事にしようと思います。
 1回目 ローグの解説、ゲーム基礎部分
 2回目 ゲーム部分の機能強化
 3回目 ランダムな迷路の自動生成
今回は2回目の記事です。




前回の記事


プログラム

# 変えたところ
#- 方向入力の数字をテンキーに合わせる
#- 壁の文字変更
#- 移動量の制限の追加(食料の概念)
#- 移動数の表示
#- イベントの追加
#- 壁が壊せる


$maze=@(
"▓▓▓▓▓▓▓▓▓▓▓",
"▓       ▓ ▓",
"▓ ▓ ▓▓▓ ▓ ▓",
"▓ ▓▓  ▓   ▓",
"▓     ▓▓▓ ▓",
"▓ ▓▓▓ ▓G▓ ▓",
"▓ ▓   ▓ ▓ ▓",
"▓ ▓ ▓ ▓ ▓ ▓",
"▓S▓   ▓   ▓",
"▓▓▓▓▓▓▓▓▓▓▓"
)

# 変数初期化
# 自分の位置と向き
$my_x = -1
$my_y = -1
$my_direction = 8  # 向き 8北 6東 2南 4西 
$my_char = @("","","v","","<","",">","","^")  # 向き 8北 6東 2南 4西
$my_food = 50  # 食料 残り移動可能数
$my_scope = 2  # 見える範囲
$my_stepcount = 0  # 移動数
$my_mattockcnt = 1  # 壁が壊せる回数

# ゴールの位置
$goal_x = -1
$goal_y = -1
# 移動用変数
$dx = @(0,0,0,0,-1,0,1,0, 0)  # 向き 8北 6東 2南 4西
$dy = @(0,0,1,0, 0,0,0,0,-1)  # 向き 8北 6東 2南 4西

# 壁の文字
$kabemoji = "▓"

# 表示ウェイト時間(秒)
$waitcnt = 1

# スタートとゴールを探す
for($i=0;$i -lt $maze.length;$i++) {
	for($j=0;$j -lt $maze[$i].length;$j++) {
		if($maze[$i][$j] -eq "S") {
			$my_x = $j
			$my_y = $i
		}
		if($maze[$i][$j] -eq "G") {
			$goal_x = $j
			$goal_y = $i
		}
	}
}

# 自分キャラの上書き
$maze[$my_y] = $maze[$my_y].Remove($my_x,1)
$maze[$my_y] = $maze[$my_y].Insert($my_x,$my_char[$my_direction])



function disp-maze($x,$y,$maze,$scope) {
	# 表示範囲の計算
	$mx = $x - $scope
	$my = $y - $scope
	if($mx -lt 0) {$mx = 0}
	if($my -lt 0) {$my = 0}

	# 表示範囲の計算 横の最大値
	$width = $x + $scope
	if($width -ge $maze[0].length) {
		$width = $maze[0].length - 1
	}

	# 表示範囲の計算 縦の最大値
	$height =  $y + $scope + 1
	if($height -gt $maze.length) {
		$height = $maze.length
	}

	# 枠の表示 上側
	write-host "+" -NoNewline
	for($i=0;$i -le $width-$mx+2;$i++){
		write-host "-" -NoNewline
	}
	write-host "+"

	# 自分の周りの表示
	for($yy = $my;$yy -lt $height;$yy++) {
		$temp_maze = ""
		for($xx=$mx;$xx -le $width;$xx++) {
			$temp_maze+=$maze[$yy][$xx]
		}
		write-host "| $temp_maze |"
	}

	# 枠の表示 下側
	write-host "+" -NoNewline
	for($i=0;$i -le $width-$mx+2;$i++){
		write-host "-" -NoNewline
	}
	write-host "+"
}



function checkEvent($my_food ,$my_scope ,$my_mattockcnt ,$auto) {

    # 乱数リセット
    $event = Get-Random -SetSeed $(Get-Date -Format "ffff")

    if($auto -eq $False) { # 自発的に見回した時とそれ以外で発生率を分ける
	    write-host "周りを見回した..."
        Start-Sleep -Seconds $waitcnt
        $event = Get-Random -Minimum 0 -Maximum 20
    } else {
        $event = Get-Random -Minimum 0 -Maximum 100
    }

    if($event -lt 3) {

		write-host "壁の隙間にキノコが生えている..."
        Start-Sleep -Seconds $waitcnt
    	$rand_food = Get-Random -Minimum 5 -Maximum 8
		write-host "食料を ${rand_food}個見つけました"
		$my_food+=$rand_food+1
        Start-Sleep -Seconds $waitcnt

    } elseif($event -eq 5) {

		write-host "壁の隙間にキノコが生えている..."
        Start-Sleep -Seconds $waitcnt
		write-host "食べられないようだ"
        Start-Sleep -Seconds $waitcnt

    } elseif($event -eq 10) {

		write-host "ネズミが足元を走り抜けた..."
        Start-Sleep -Seconds $waitcnt
    	$rand_food = Get-Random -Minimum 3 -Maximum 5
		write-host "食料を ${rand_food}個失った"
		$my_food-=$rand_food+1
        Start-Sleep -Seconds $waitcnt

    } elseif($event -eq 11) {

		write-host "ネズミが足元を走り抜けた..."
        Start-Sleep -Seconds $waitcnt
		write-host "捕まえて食料にした"
        Start-Sleep -Seconds $waitcnt
    	$rand_food = Get-Random -Minimum 5 -Maximum 8
		write-host "食料が ${rand_food}個増えた"
		$my_food+=$rand_food+1
        Start-Sleep -Seconds $waitcnt

    } elseif($event -eq 12) {

		write-host "ネズミが足元を走り抜けた..."
        Start-Sleep -Seconds $waitcnt
		write-host "松明を振り回して追い払った"
        Start-Sleep -Seconds $waitcnt
		write-host "松明の火が小さくなった"
		$my_scope-=1
		if($my_scope -eq 0){
    		$my_scope = 1
        }
        Start-Sleep -Seconds $waitcnt

    } elseif($event -eq 15) {

		write-host "つまずいて食料と松明を落とした..."
        Start-Sleep -Seconds $waitcnt
    	$rand_food = Get-Random -Minimum 3 -Maximum 5
		write-host "食料を ${rand_food}個失った"
		$my_food-=$rand_food+1
        Start-Sleep -Seconds $waitcnt
		write-host "松明の火が小さくなった"
		$my_scope-=1
		if($my_scope -eq 0){
    		$my_scope = 1
        }
        Start-Sleep -Seconds $waitcnt

    } elseif($event -eq 16) {

		write-host "突風が吹いて松明の火が小さくなった..."
		$my_scope-=1
        Start-Sleep -Seconds $waitcnt
		if($my_scope -eq 0){
    		write-host "...かと思ったら、天井から油が滴っていた"
            Start-Sleep -Seconds $waitcnt
        	write-host "油を松明に擦り付けて火を大きくした"
            Start-Sleep -Seconds $waitcnt
    		$my_scope = 3
        }
        Start-Sleep -Seconds $waitcnt

    } elseif($event -eq 17) {

		write-host "壁から木の根が生い茂っている..."
        Start-Sleep -Seconds $waitcnt
		if($my_scope -lt 3){
    		$my_scope+=1
    		write-host "はがして松明にした"
        } else {
    		write-host "剝がそうとしたがビクともしなかった"
        }
        Start-Sleep -Seconds $waitcnt

    } else {

        if($auto -eq $False) {
		    write-host "...何もなかった"
            Start-Sleep -Seconds $waitcnt
        }

    }

    return $my_food ,$my_scope ,$my_mattockcnt
}


$loopflg = $True
while($loopflg) {
    # 画面表示
	disp-maze $my_x $my_y $maze $my_scope

	# 入力
    write-host "食料:${my_food} 松明:${my_scope} マトック:${my_mattockcnt} 移動数:${my_stepcount}歩"
    write-host "どちらに進みますか "
	$keyinput = (read-host "8:北 6:東 2:南 4:西 77:周りを見る 88:壁を壊す 99:終了") # 向き 8北 6東 2南 4西

	# 入力チェック
	if($keyinput -ne "8" -and $keyinput -ne "6" -and $keyinput -ne "2" -and $keyinput -ne "4" -and $keyinput -ne "88" -and $keyinput -ne "77" -and $keyinput -ne "99") {
		# 該当の数字以外は無効とする
        write-host "入力は半角数字 2,4,6,8,77,88,99のみ"
		continue;
	}
	
	# 終了判定
	if($keyinput -eq "99"){
		$loopflg = $False
		continue;
	} 

	# 壁を壊す
	if($keyinput -eq "88"){
		if($my_mattockcnt -ge 1) {
            $tmp_my_x = $my_x + $dx[$my_direction]
		    $tmp_my_y = $my_y + $dy[$my_direction]
            if($tmp_my_x -lt 1 -or $tmp_my_x -ge $maze[$tmp_my_x].length-1 -or $tmp_my_y -lt 1 -or $tmp_my_y -ge $maze.length-1){
                write-host "その壁は壊せなかった"
            } elseif($maze[$tmp_my_y][$tmp_my_x] -eq $kabemoji){
                write-host "壁を壊した"
                $my_mattockcnt-=1
		        $maze[$tmp_my_y] = $maze[$tmp_my_y].Remove($tmp_my_x,1)
		        $maze[$tmp_my_y] = $maze[$tmp_my_y].Insert($tmp_my_x," ")
            } else {
                write-host "壁はなかった"
            }
        }
		continue;
	} 

	# 周りを見る
	if($keyinput -eq "77"){
        $my_food ,$my_scope ,$my_mattockcnt = checkEvent $my_food $my_scope $my_mattockcnt $False
		continue;
	} 

	# 移動処理
	if($keyinput -ne $my_direction) {
		# 向きが違う場合、向きを変えるのみ
		$tmp_my_direction = $keyinput 
		$tmp_my_x = $my_x
		$tmp_my_y = $my_y
	} else {
		# 向きが同じなら進む
		$tmp_my_direction = $keyinput 
		$tmp_my_x = $my_x + $dx[$keyinput]
		$tmp_my_y = $my_y + $dy[$keyinput]
	}

	# 進む処理
	if($maze[$tmp_my_y][$tmp_my_x] -ne $kabemoji){# 壁の判定

        $my_stepcount+=1

		# 現在地を空白で消す
		$maze[$my_y] = $maze[$my_y].Remove($my_x,1)
		$maze[$my_y] = $maze[$my_y].Insert($my_x," ")

		# 位置移動
		$my_x = $tmp_my_x
		$my_y = $tmp_my_y
		$my_direction = $tmp_my_direction 

		# 表示
		$maze[$my_y] = $maze[$my_y].Remove($my_x,1)
		$maze[$my_y] = $maze[$my_y].Insert($my_x,$my_char[$my_direction])

		# ゴールの判定
        if($my_x -eq $goal_x -and $my_y -eq $goal_y) {
            write-host "ゴールに到着しました"
            disp-maze $my_x $my_y $maze $my_scope
            $loopflg = $False
        } else {
            # イベント発生チェック
            $my_food ,$my_scope ,$my_mattockcnt = checkEvent $my_food $my_scope $my_mattockcnt $True
        }

        # 終了の判定
        $my_food-=1
		if($my_food -lt 0 -and $loopflg -eq $True){
			write-host "食料が底をつきました"
			$loopflg = $False
		}

	}

}

プログラム解説

 次の機能を盛り込みました。

  • 方向入力の数字をテンキーに合わせる

  • 見える範囲の概念

  • 移動量の制限(食料の概念)

  • 壁が壊せる

  • 壁の文字変更

  • イベントの追加


方向入力の数字をテンキーに合わせる:
 これは、前回入力が0,1,2,3だったのをテンキーの数字の並び8,6,4,2に合わせました。8,6,4,2の方が直感的に遊びやすいので変えました。自分のパソコンにはテンキーが無いんですけども昔のパソコンゲームは方向を8,6,4,2にしているものが多かったのでこうしてみました。

見える範囲の概念:
 松明というステータスを足して、見える範囲が変わるようにしました。
変数$my_scopeが見える範囲です。

移動量の制限(食料の概念):
 ローグライクゲームに食料の概念があったので取り入れてみました。

壁が壊せる:
 今は迷路が固定なのですが、次の記事でランダムに迷路を生成するようにしたいので、閉路で積んでしまわないように壁が壊せるようにしました。
変数$my_mattockcntが壁を壊せる回数です。
壁を壊して通路を作ったら、周りの通路のどれかが塞がるとかにしたら面白くなるかな?と考えたのですが今回は壊すだけにしました。

壁の文字変更:
 壁の文字が*だったのを▓にしました。▓は見たことがない半角文字なんですけどWindows系なら大丈夫だろうと思って変えてみました。

イベントの追加:
 周りを見回す行動を追加して、見回したときにイベントがランダムに起こるようにしました。食料が手に入ったり、見える範囲が広がることがあります。プログラムコードが同じような記述が繰り返し出てきてキレイじゃないし、処理が丸見えなんですが取り合えずで作ってみました。


なんか、あんまり面白くないですね。
やりこみ要素とかが無いからでしょうか。

次回予告

 次は迷路をランダムなものに変えようと思います。
下の記事を参考にします。


#PowerShell #テキストゲーム #ローグライク #プログラミング初心者
#プログラミング入門


いいなと思ったら応援しよう!