Chapter 07

スプライト同士の衝突(1対多)

かじるプログラミング
かじるプログラミング
2022.09.30に更新

スプライト同士の衝突(1対多)

今回は1対多の衝突についてのお話です。
"Group"を使う事で、まとめてスプライトを管理する事が可能になります。

今回は、次の状態をベースにして解説を進めていきますね。

let reimu;// スプライト

function preload(){

	// アニメーション
	loadAni("r_good", "reimu_good_01.png", 3);
	loadAni("m_good", "marisa_good_01.png", 3);
}

function setup(){
	createCanvas(windowWidth, windowHeight);
	angleMode(DEGREES);
	frameRate(32);
	noSmooth();
	noStroke();

	// スプライト(霊夢)
	reimu = new Sprite(width/2, height/2, 45);
	reimu.shapeColor = color("white");
	reimu.ani = "r_good";
	reimu.scale = 2;
}

function draw(){
	background(33);

	// 全てのスプライトを調べる
	for(let sprite of allSprites){
		// キャンバスの外に出たら反対側へ移動させる(4方向)
		if(width < sprite.x) sprite.x = 0; // 右から出たら
		if(sprite.x < 0) sprite.x = width; // 左から出たら
		if(height < sprite.y) sprite.y = 0;// 下から出たら
		if(sprite.y < 0) sprite.y = height;// 上から出たら
	}

	// Debug
	allSprites.debug = mouse.pressing();
}

真ん中に霊夢が佇んでいる。。。
(何かが起こりそうな予感)

スプライトをまとめて管理する"Group"

今回は1対多の"多"である魔理沙を大量に発生させます。
この様な場合、"Group"という機能を使えるととても便利です。
次のコードを"preload関数"に記述します。

グループ = new Group();

そして、グループ用にスプライトを生成するだけです。(超簡単!!)

スプライト = new グループ.Sprite(x座標, y座標, 直径);

次のコードは、グループを使って5体の魔理沙軍団を生成するコードです。
(1, 2, 3の順にコードを追いかけてください)

let marisaGroup;// 1, グループ
let reimu;// スプライト

function preload(){

	// アニメーション
	loadAni("r_good", "./assets/reimu_good_01.png", 3);
	loadAni("m_good", "./assets/marisa_good_01.png", 3);

	// 2, グループを作る
	marisaGroup = new Group();
}

function setup(){
	createCanvas(windowWidth, windowHeight);
	angleMode(DEGREES);
	frameRate(32);
	noSmooth();
	noStroke();

	// スプライト(霊夢)
	reimu = new Sprite(width/2, height/2, 45);
	reimu.shapeColor = color("white");
	reimu.ani = "r_good";
	reimu.scale = 2;

	// スプライト(魔理沙)
	for(let i=0; i<5; i++){
		const x = random(width);
		const y = random(height);
		// 3, グループにスプライトを追加する(位置はランダム)
		let marisa = new marisaGroup.Sprite(x, y, 45);
		marisa.shapeColor = color("white");
		marisa.ani = "m_good";
		marisa.scale = 2;
	}
}

// 省略

魔理沙軍団に囲まれた絶体絶命の霊夢です。

スプライトをマウスで操作

このままでは霊夢が圧倒的に不利なので、
"moveTowards関数"を使って、マウスに追随する処理を実装します。
("draw関数"に記述します)

スプライト.moveTowards(mouse.x, mouse.y, 0.2);

具体的には次の様になります。
(今回の完成コードです)

let marisaGroup;// グループ
let reimu;// スプライト

function preload(){

	// アニメーション
	loadAni("r_good", "reimu_good_01.png", 3);
	loadAni("m_good", "marisa_good_01.png", 3);

	// グループ
	marisaGroup = new Group();
}

function setup(){
	createCanvas(windowWidth, windowHeight);
	angleMode(DEGREES);
	frameRate(32);
	noSmooth();
	noStroke();

	// スプライト(霊夢)
	reimu = new Sprite(width/2, height/2, 45);
	reimu.shapeColor = color("white");
	reimu.ani = "r_good";
	reimu.scale = 2;

	// スプライト(魔理沙)
	for(let i=0; i<5; i++){
		const x = random(width);
		const y = random(height);
		let marisa = new marisaGroup.Sprite(x, y, 45);
		marisa.shapeColor = color("white");
		marisa.ani = "m_good";
		marisa.scale = 2;
	}
}

function draw(){
	background(33);

	// 1, マウス座標に追随する
	reimu.moveTowards(mouse.x, mouse.y, 0.2);

	// 全てのスプライトを調べる
	for(let sprite of allSprites){
		// キャンバスの外に出たら反対側へ移動させる(4方向)
		if(width < sprite.x) sprite.x = 0; // 右から出たら
		if(sprite.x < 0) sprite.x = width; // 左から出たら
		if(height < sprite.y) sprite.y = 0;// 下から出たら
		if(sprite.y < 0) sprite.y = height;// 上から出たら
	}

	// Debug
	allSprites.debug = mouse.pressing();
}

返り討ちに遭う魔理沙軍団。

次回は簡単なゲームを作ってみます。