ページ 11

amachi

Posted: 2017年9月02日(土) 01:18
by クラス間での当たり判定
今私は上からコインが落ちてきて
そのコインを取るゲームを作成しているのですが
プレイヤーとコインとの当たり判定で詰まってしまいました。

checkhit.h

コード:

#pragma once
class CheckHit
{
public:
	static bool CheckHitRect(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh);
};
checkhit.cpp

コード:

#include	"checkhit.h"

bool CheckHit::CheckHitRect(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh)
{
	int al = ax - aw / 2;					//物体Aの左端(Left)
	int ar = ax + aw / 2;					//物体A右端(Right)
	int au = ay - ah;						//物体Aの上端(Up)
	int ad = ay;							//物体Aの下端(Down)

	int bl = bx - bw / 2;					//物体Bの左端(Left)
	int br = bx + bw / 2;					//物体Bの右端(Right)
	int bu = by - bh;						//物体Bの上端(Up)
	int bd = by;							//物体Bの下端(Down)

											//当たっていない条件
	if (ar < bl) return false;				//Aの右端 < Bの左端
	if (br < al) return false;				//Bの右端 < Aの左端
	if (bd < au) return false;				//Bの下端 < Aの上端
	if (ad < bu) return false;				//Aの下端 < Bの上端

	//当たっている
	return true;
}
item.h

コード:

#pragma once
#include	"bace.h"

#define ITEM_MAX 10

class Item :public Bace
{
private:
	std::unique_ptr<sprite> item[ITEM_MAX];
	int timer;

public:
	int item_x[10];
	int item_y;
	int item_w;
	int item_h;

	Item() {};
	Item(ID3D11Device* device, const wchar_t* file_name) : Bace(device, file_name)
	{
	};

	int GetItemX() { return item_x[ITEM_MAX]; }
	void SetItemX(int x) { item_x[ITEM_MAX] = x; }

	int GetItemY() { return item_y; }
	void SetItemY(int y) { item_y = y; }

	int GetItemW() { return item_w; }
	void SetItemW(int w) { item_w = w; }

	int GetItemH() { return item_h; }
	void SetItemH(int h) { item_h = h; }

	void Initialize();
	void Update();
	void Render(ID3D11DeviceContext* immediate_context);
};

item.cpp

コード:

#include	"framework.h"
#include	"item.h"
#include	"player.h"
#include	"checkhit.h"
#include	<cstdlib>
#include	<ctime>

void Item::Initialize()
{
	srand((unsigned int)time(NULL));

	timer = 0;

	item_y = -200;
	item_w = 50;
	item_h = 30;

	for (int i = 0; i < ITEM_MAX; i++)
	{
		item[i];
		item_x[i] = rand() % 1100 + 10;
	}
}

void Item::Update()
{
	timer++;
	if (timer > 60 * 2)
	{
		item_y += 2;
	}
}

void Item::Render(ID3D11DeviceContext * immediate_context)
{
	for (int i = 0; i < ITEM_MAX; i++)
	{
		picture->render(immediate_context, item_x[i], item_y, 100, 100, 10, 10, 500, 500, 0, 1, 1, 1, 1);
	}
}

player.h

コード:

#pragma once
#include	"bace.h"

class Player :public Bace
{
private:
	std::unique_ptr<sprite> player[1024];
	int player_x;
	int player_y;
	int move_x, move_y;  // キャラクタの移動量
	int anime_x;
	int anime_y;
	int player_w;
	int player_h;

public:
	Player() {};
	Player(ID3D11Device* device, const wchar_t* file_name) : Bace(device, file_name)
	{
	};

	int GetPlayerX() { return player_x; }
	void SetPlayerX(int x) { player_x = x; }

	int GetPlayerY() { return player_y; }
	void SetPlayerY(int y) { player_y = y; }

	int GetPlayerW() { return player_w; }
	void SetPlayerW(int w) { player_w = w; }

	int GetPlayerH() { return player_h; }
	void SetPlayerH(int h) { player_h = h; }


	void Initialize();
	void Update();
	void Render(ID3D11DeviceContext* immediate_context);
};

#define MARGIN 5	//余白
#define P_GRAVITY	1
player.cpp

コード:

#include	"framework.h"
#include	"player.h"
#include	"Key.h"
#include	"checkhit.h"
#include	"item.h"

void Player::Initialize()
{
	anime_x = 0;
	anime_y = 0;
	player_w = 120;
	player_h = 60;
	move_x = 10;  // 移動量の初期値
	move_y = 0;  //
	player_x = 500;
	player_y = 510;
}

void Player::Update()
{
	static bool flag = false;
	static bool flag2 = true;

	if (KEY.keyPush(DIK_A))
	{
		player_x -= move_x;
		if (flag2 == true)
		{
			anime_y = 240;
			anime_x = 13;
			flag2 = false;
		}
		anime_x -= 1;
		if (anime_x == 7)
		{
			anime_x = 13;
			anime_y = 240;
		}
		flag = true;
	}

	else if (flag2 == false)
	{
		anime_x = 13;
	}

	if (KEY.keyPush(DIK_D))
	{
		player_x += move_x;
		if (flag == true)
		{
			anime_x = 0;
			anime_y = 0;
			flag = false;
		}
		anime_x += 1;
		if (anime_x == 7)
		{
			anime_x = 1;
			anime_y = 0;
		}
		flag2 = true;
	}

	else if (flag == false)
	{
		anime_x = 0;
	}

	//キャラの移動制御
	if (player_x > 1150 - MARGIN)
	{
		player_x = 1150 - MARGIN;
	}
	else if (player_x < MARGIN)
	{
		player_x = MARGIN;
	}

	bool jf;
	move_y += P_GRAVITY;
	player_y += move_y;
	jf = true;

	if (player_y > 510)
	{
		player_y = 510; // 地面上に接地
		move_y = 0; // 落下速度も0に
		jf = false;
	}

	if (KEY.keyPush(DIK_W))
	{
		if (jf == false)
		{
			move_y -= 20;
		}
	}

	Item I;

	for (int i = 0; i < ITEM_MAX; i++)
	{
		if (CheckHit::CheckHitRect(Player::GetPlayerX(), Player::GetPlayerY(), Player::GetPlayerW(), Player::GetPlayerH(),
			I.GetItemX(), I.GetItemY(), I.GetItemW(), I.GetItemH()))
		{
			player_x = 0;//仮
		}
	}
}

void Player::Render(ID3D11DeviceContext* immediate_context)
{
	picture->render(immediate_context, player_x, player_y, 150, 150, 140 * anime_x, 1 * anime_y, 140, 240, 0, 1, 1, 1, 1);
}

という風にやっているのですが
何も起こりません
分かる方いましたらお願いします。

Re: amachi

Posted: 2017年9月02日(土) 01:31
by みけCAT
適当なアイテムのインスタンスを用意して、それを初期化せずに当たり判定に使用しても、意味が無いと思います。
落ちてくるコインをどう管理しているかがわからないので、改善方法はわかりません。

Re: amachi

Posted: 2017年9月02日(土) 01:34
by みけCAT
クラス間での当たり判定 さんが書きました:item.h

コード:

#define ITEM_MAX 10

コード:

	int item_x[10];

コード:

	int GetItemX() { return item_x[ITEM_MAX]; }
	void SetItemX(int x) { item_x[ITEM_MAX] = x; }
item_x[10]は10要素であり、有効な添字は0~9です。
item_x[ITEM_MAX]、すなわちitem_x[10]は範囲外なので、アクセス(読み書き)してはいけません。

Re: amachi

Posted: 2017年9月02日(土) 02:38
by amachi
返信ありがとうございます

プレイヤーではなくアイテムのほうに
判定を書きなおしたら一応判定はとれたのですが
アイテムが落ちて直ぐに判定がとれてします

今仮でプレイヤーとアイテムが当たったら
アイテムのy座標をマイナスする様にしているのですが
落ちて来て直ぐににアイテムのy座標が
マイナスになってしまいます(しかも全てのアイテムが(10個))

プレイヤーのheight、widthもしくは、
アイテムのheight、widthが大きすぎるのかなと思い
小さくしてみたりしたのですが何も変化しませんでした

どうすればいいでしょうか?

コード:

	Player p;

	for (int i = 0; i < ITEM_MAX; i++)
	{
		if (CheckHit::CheckHitRect
			(p.GetPlayerX(), p.GetPlayerY(), p.GetPlayerW(), p.GetPlayerH(),Item::GetItemX(), Item::GetItemY(), Item::GetItemW(), Item::GetItemH()))
		{
			item_y -= 10;//仮
		}
	}

Re: amachi

Posted: 2017年9月02日(土) 08:34
by みけCAT
amachi さんが書きました:

コード:

	Player p;

	for (int i = 0; i < ITEM_MAX; i++)
	{
		if (CheckHit::CheckHitRect
			(p.GetPlayerX(), p.GetPlayerY(), p.GetPlayerW(), p.GetPlayerH(),Item::GetItemX(), Item::GetItemY(), Item::GetItemW(), Item::GetItemH()))
		{
			item_y -= 10;//仮
		}
	}
提示されているコードのItem::GetItemX()などはstaticではないので、これでは動かないと思います。
【追記】
Itemクラスのメンバ関数に書けば動かなくはないでしょう。
しかし、「適当なインスタンスを作って初期化せずに当たり判定に使用しても意味がない」というのは、ItemだけでなくPlayerにもその他にもいえます。
amachi さんが書きました:どうすればいいでしょうか?
処理内容の改善をすればいいでしょう。
ヒントなどを考えてほしければ、メインループ(PlayerやItemの処理を呼び出している部分)など現状の処理内容がわかる資料を提示するといいでしょう。