4.複数のキャラの表示

プレイヤー以外のキャラを表示します。素材集サイトFirst Seed Materialのキャラクターチップをお借りします。

勇者増殖中

基本的には2.主人公を表示するで使った、キャラクターの座標などの変数を配列変数にしただけです。

キャラが移動する際に当たり判定などを行うルーチンをユーザー定義命令にしました。
ユーザー定義命令については、モジュール機能、ユーザー定義命令(関数)で説明しています。

定義命令、move p1,p2 はp1番目の要素番号をもつキャラをp2で指定した方向に移動させる命令です。
p2は(0:左 1:上 2:右 3:下に対応しています)

randomize
buffer 1,96,32
picload "maptip.bmp"
buffer 2,72,128
picload "charatip.bmp"
screen 0,320,320

dim map,10,10

en = 5 //表示するキャラの人数
dim ex,en //キャラの座標
dim ey,en
dim edir,en //キャラの向き
dim walk,en //キャラの歩行制御
dim wdx,en //キャラの移動方向
dim wdy,en
ex = 1,2,3,4,5 //キャラの初期位置
ey = 1,2,3,4,5

*main
gosub *keyEvent //プレイヤーの操作
gosub *cpuMove //コンピュータの移動
gosub *draw_map //マップの描画
gosub *draw_chara //キャラクターの描画

redraw 1
wait 8
redraw 0
goto *main

//ユーザー定義命令
#deffunc move int mi,int mdir
edir(mi) = mdir //向きを変える
wdx(mi) = 0: wdy(mi) = 0
if mdir = 0: wdx(mi)--
if mdir = 1: wdy(mi)--
if mdir = 2: wdx(mi)++
if mdir = 3: wdy(mi)++
x = ex(mi)+wdx(mi) : y = ey(mi)+wdy(mi) //(x,y)は移動先の座標
if (x < 0) | (x > 9) : return //移動先が画面外だったら移動しない
if (y < 0) | (y > 9) : return
if map(x,y) :return //移動先に障害物があれば移動しない
walk(mi) = 1
	//他のキャラと衝突判定をする
	repeat en
	if mi = cnt :continue
	if (x = ex(cnt)) & (y = ey(cnt)) :walk(mi) = 0 :break
	if (x = ex(cnt)+wdx(cnt)) & (y = ey(cnt)+wdy(cnt)) :walk(mi) = 0 :break
	loop
return

*keyEvent
stick key,15
i = 0
if walk(0) = 0 {
	if (key = 1) | (key = 2) | (key = 4) | (key = 8) : move 0,logf(key)/logf(2)
}
return

*cpuMove
repeat en
	if cnt = 0 :continue	//0番目の配列はプレイヤーなのでスキップ
	if walk(cnt) :continue
	i = rnd(10)
	if i <= 3 :move cnt,i
loop
return

*draw_map
gmode 0
x = 0 : y = 0
repeat 10
j = cnt
	repeat 10
	i = cnt
	pos x,y
	if map(i,j) = 0:gcopy 1,0,0,32,32 //草の下地を表示
	if map(i,j) = 1:gcopy 1,32,0,32,32 //ブロックを表示
	if map(i,j) = 2:gcopy 1,64,0,32,32 //箱を表示
	x += 32
	loop
x = 0 : y += 32
loop
return

*draw_chara
gmode 4,24,32,256
color 0,117,117
	repeat en
	i = cnt
	pos ex(i)*32+walk(i)*wdx(i)*8+4,ey(i)*32+walk(i)*wdy(i)*8
	if walk(i) = 0 : gcopy 2,24,(edir(i) * 32),24,32
	if walk(i) = 1 : gcopy 2,0,(edir(i) * 32),24,32
	if walk(i) = 2 : gcopy 2,24,(edir(i) * 32),24,32
	if walk(i) = 3 : gcopy 2,48,(edir(i) * 32),24,32
	if walk(i) = 4 {
		gcopy 2,24,(edir(i) * 32),24,32
		walk(i) = 0
		ex(i) += wdx(i)
		ey(i) += wdy(i)
		wdx(i) = 0 : wdy(i) = 0
	}
	if walk(i):walk(i)++
	loop
return

下のソースはユーザー定義命令を使わないで書き直したものです。

randomize
buffer 1,96,32
picload "maptip.bmp"
buffer 2,72,128
picload "charatip.bmp"
screen 0,320,320

dim map,10,10

en = 5			//表示するキャラの人数
dim ex,en		//イベントの座標
dim ey,en
dim edir,en		//イベントの向き
dim walk,en		//イベントの歩行制御
dim wdx,en		//イベントの移動方向
dim wdy,en
ex = 1,2,3,4,5	//キャラの初期位置
ey = 1,2,3,4,5

*main
gosub *moving		//移動処理
gosub *draw_map		//マップの描画
gosub *draw_chara	//キャラクターの描画

redraw 1
wait 8
redraw 0
goto *main

//移動処理
*moving
repeat en
if cnt = 0 {
	stick key,15
	if walk(0) = 0 {
		if (key = 1)|(key = 2)|(key = 4)|(key = 8) {
			edir(0) = int(logf(key)/logf(2)) } else :continue
	}else :continue
}else{
	if walk(cnt) :continue	//移動中ならスキップ
	i = rnd(10)
	if i <= 3 :edir(cnt) = i :else :continue
}
i = cnt
wdx(i) = 0 :wdy(i) = 0
if edir(i) = 0: wdx(i)--
if edir(i) = 1: wdy(i)--
if edir(i) = 2: wdx(i)++
if edir(i) = 3: wdy(i)++
x = ex(i)+wdx(i) : y = ey(i)+wdy(i) //(x,y)は移動先の座標
if (x < 0) | (x > 9) : return //移動先が画面外だったら移動しない
if (y < 0) | (y > 9) : return
if map(x,y) :return //移動先に障害物があれば移動しない
walk(i) = 1
	repeat en
	if i = cnt :continue
	if (x = ex(cnt)) & (y = ey(cnt)) :walk(i) = 0 :break
	if (x = ex(cnt)+wdx(cnt)) & (y = ey(cnt)+wdy(cnt)) :walk(i) = 0 :break
	loop
loop

*draw_map
gmode 0
x = 0 : y = 0
repeat 10
j = cnt
	repeat 10
	i = cnt
	pos x,y
	gcopy 1,map(i,j)*32,0,32,32
	x += 32
	loop
x = 0 : y += 32
loop
return

*draw_chara
gmode 4,24,32,256
color 0,117,117
	repeat en
	i = cnt
	pos ex(i)*32+walk(i)*wdx(i)*8+4,ey(i)*32+walk(i)*wdy(i)*8
	if walk(i) = 0 : gcopy 2,24,(edir(i) * 32),24,32
	if walk(i) = 1 : gcopy 2,0,(edir(i) * 32),24,32
	if walk(i) = 2 : gcopy 2,24,(edir(i) * 32),24,32
	if walk(i) = 3 : gcopy 2,48,(edir(i) * 32),24,32
	if walk(i) = 4 {
		gcopy 2,24,(edir(i) * 32),24,32
		walk(i) = 0
		ex(i) += wdx(i) :ey(i) += wdy(i)
		wdx(i) = 0 : wdy(i) = 0
	}
	if walk(i):walk(i)++
	loop
return