ページ 1 / 1
弾がうまく発射できない
Posted: 2021年9月12日(日) 19:10
by ヨッシー
初投稿です。c/c++とDxLibを使ってシューティングゲームを作ろうとしているものです。
コード:
PlayerBullet.h
#pragma once
#include "Player.h"
#include "Define.h"
class PlayerBullet : public Task
{
friend class Player;
public:
PlayerBullet();
virtual ~PlayerBullet() = default;
bool update() override;
void draw() const override;
private:
void move();
bool flag; //フラグ
int cnt; //カウンタ
int type; //種類
float _x, _y; //座標
float speed; //スピード
};
PlayerBullet.cpp
#include <DxLib.h>
#include "Pad.h"
#include "Define.h"
#include "Image.h"
const static float SPEED = 9.0;
PlayerBullet::PlayerBullet() :
_x((float)Define::CENTER_X),
_y((float)Define::OUT_H * 0.8f)
{
flag = 0;
speed = 50;
}
bool PlayerBullet::update()
{
void move();
return true;
}
void PlayerBullet::draw() const
{
PlayerBullet Bullet[4][25];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
Bullet[i][j].flag = false;
}
}
if (Pad::getIns()->get(ePad::shot) > 0)
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == false) { //弾の座標の更新
Bullet[i][j]._x = _x + Define::coption0pos_x[i];
Bullet[i][j]._y = _y + Define::coption0pos_y[i];
Bullet[i][j].flag = true;
}
}
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == true)
{
Bullet[i][j]._y -= speed; //弾の座標を上にずらす
if (Bullet[i][j]._y <= Define::IN_Y) //枠外へ行ったらフラグをfalseにする。
{
Bullet[i][j].flag = false;
}
DrawRotaGraphF(Bullet[i][j]._x, Bullet[i][j]._y, 1.0, 0.0, Image::getIns()->getPlayerBullet()[1], FALSE); //描画する
}
}
}
}
void PlayerBullet::move()
{
float moveX = 0, moveY = 0;
if (Pad::getIns()->get(ePad::left) > 0) { //左移動
moveX -= SPEED;
}
if (Pad::getIns()->get(ePad::right) > 0) { //右移動
moveX += SPEED;
}
if (Pad::getIns()->get(ePad::down) > 0) { //下移動
moveY += SPEED;
}
if (Pad::getIns()->get(ePad::up) > 0) { //上移動
moveY -= SPEED;
}
if (moveX && moveY) { //斜め移動
moveX /= (float)sqrt(2.0);
moveY /= (float)sqrt(2.0);
}
if (Pad::getIns()->get(ePad::slow) > 0) { //低速移動
moveX /= 3;
moveY /= 3;
}
if (moveX + _x < Define::IN_X) { //左枠より左なら
_x = (float)Define::IN_X; //左枠で止める
}
else if (moveX + _x > Define::IN_X + Define::IN_W) { //右枠より右なら
_x = (float)(Define::IN_X + Define::IN_W); //右枠で止める
}
else { //枠内なら
_x += moveX; //普通に移動
}
if (moveY + _y < Define::IN_Y) { //上枠より上なら
_y = (float)Define::IN_Y; //上枠で止める
}
else if (moveY + _y > Define::IN_Y + Define::IN_H) { //下枠より下なら
_y = (float)(Define::IN_Y + Define::IN_H); //下枠で止める
}
else { //枠内なら
_y += moveY; //普通に移動
}
}
クラスの継承や、オーバーライドなど諸々の構造は龍神録2プログラミングの館を参考にして作成しました。
デバッグをしてみると、処理一回分だけ上に移動したところで重なって描画されてしまい、その場に留まってしまいます。
また、ショットキーを押すと自機のオプションの部分から弾が発射されるようにしたいのですが(そのためmove関数でオプションに合わせて座標を更新しているつもり)、常に最初の場所で描画がされてしまいます。
サイトなどで色々調べましたが結局うまくいかず、、助力をお願い致します。
Re: 弾がうまく発射できない
Posted: 2021年9月13日(月) 03:15
by あたっしゅ
東上☆海美☆「
よくあること ⇒ 『説明文』と『実際に起こっていること』が異なる。
おかしな点 ⇒ void PlayerBullet::draw() const 内で PlayerBullet Bullet[4][25]; が定義されているみみ。
そのため、void PlayerBullet::draw() const を抜けると、弾の位置などを忘れてしまうみみ。
コード:
class PlayerBullet {
public:
void move();
void daw();
PlayerBullet();
virtual ~PlayerBullet() = default;
};
class TPlayerBulletCollection {
PlayerBullet Bullet[4][25];
// 25 だったり Define::PBULLET_NUM / 4 だったりするのは、なぜ ?
public:
void move();
void draw();
void shot();
TPlayerBulletCollection();
virtual ~TPlayerBulletCollection() = default;
};
//
//
//
void TPlayerBulletCollection::draw()
{
DrawRotaGraphF(_x, _y, 1.0, 0.0, Image::getIns()->getPlayerBullet()[1], FALSE); //描画する
}
//
//
//
void TPlayerBulletCollection::move()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == true)
{
Bullet[i][j]._y -= speed; //弾の座標を上にずらす
if (Bullet[i][j]._y <= Define::IN_Y) //枠外へ行ったらフラグをfalseにする。
{
Bullet[i][j].flag = false;
}
}
}
}
}
void TPlayerBulletCollection::draw()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == true)
{
Bullet[i][j]->Draw();
}
}
}
}
void TPlayerBulletCollection::shot()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == false) {
Bullet[i][j]._x = Player._x + Define::coption0pos_x[i];
Bullet[i][j]._y = Player._y + Define::coption0pos_y[i];
Bullet[i][j].flag = true;
break;
}
}
}
}
TPlayerBulletCollection::TPlayerBulletCollection()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
Bullet[i][j].flag = false;
}
}
}
int
main()
{
TPlayerBulletCollection PlayerBulletCollection;
// loop
while(...) {
//
if( 弾発射キーが押された ) {
PlayerBulletCollection->shot();
}
//
PlayerBulletCollection->move();
//
PlayerBulletCollection->draw();
//
}
return 0;
}
すべてのソースが up されているわけではないので、足りない部分は、想像で書いたみみ。
」
Re: 弾がうまく発射できない
Posted: 2021年9月13日(月) 22:24
by ヨッシー
素早い対応ありがとうございます。
あたっしゅ様のソースコードを参考にしながら所々変更しながらあと一歩というところまで来ましたが、エラーが出てしまいました。(ソースコード参照)
コード:
PlayerBullet.h
#pragma once
#include "Player.h"
#include "PlayerOption.h"
#include "Define.h"
class PlayerBullet : public Task
{
friend class Player;
friend class PlayerOption;
friend class PlayerBulletCollection;
public:
PlayerBullet();
virtual ~PlayerBullet() = default;
bool update() override;
void draw() const override;
protected:
void move();
int cnt; //カウンタ
int type; //種類
bool flag; //フラグ
float _x, _y; //座標
static float speed; //スピード
};
class PlayerBulletCollection : public Task
{
PlayerBullet Bullet[4][25];
friend class PlayerBullet;
friend class PlayerOption;
public:
PlayerBulletCollection();
virtual ~PlayerBulletCollection() = default;
void move();
void draw();
void shot();
};
PlayerBullet.cpp
#include "PlayerBullet.h"
#include <DxLib.h>
#include "Pad.h"
#include "Define.h"
#include "Image.h"
const static float SPEED = 9.0;
PlayerBullet::PlayerBullet() :
_x((float)Define::CENTER_X),
_y((float)Define::OUT_H * 0.8f)
{
flag = 0;
speed = 50;
}
bool PlayerBullet::update()
{
void draw();
return true;
}
void PlayerBullet::draw() const
{
DrawRotaGraphF(_x, _y, 1.0, 0.0, Image::getIns()->getPlayerBullet()[1], FALSE);
}
void PlayerBullet::move()
{
//とりあえず後回し
}
PlayerBulletCollection::PlayerBulletCollection() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
Bullet[i][j].flag = false;
}
}
}
void PlayerBulletCollection::move() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == true)
{
Bullet[i][j]._y -= PlayerBullet::speed;
if (Bullet[i][j]._y <= Define::IN_Y)
{
Bullet[i][j].flag = false;
}
}
}
}
}
void PlayerBulletCollection::draw()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == true)
{
Bullet[i][j].draw();
}
}
}
}
void PlayerBulletCollection::shot()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == false) {
Bullet[i][j]._x = PlayerOption::_x; // ここでエラー発生
Bullet[i][j]._y = PlayerOption::_y; //ここでエラー発生
Bullet[i][j].flag = true;
break;
}
}
}
}
ちなみにつっこまれていました配列の要素数が25だったりDefine::PBULLET_NUMだったりするのは、const static intで宣言すると配列の定義の際、要素数に用いることができなかったためです。
PlayerOptionクラス(ソースは省きます)の座標用変数をもとにBullet[][]に座標を代入しようとした際に「静的でないメンバー参照は特定のオブジェクトを基準とする相対参照である必要があります」というエラーが出てしまい、デバッグ以前の問題となっている次第です。
以前からこのエラーはちょくちょく出ていて、自分の解釈としては静的メンバ関数(今回の場合void draw() const)内で外部の動的メンバを使用しようとした際に出るものだと思っていました、がその解釈が間違っていたようで困っています。
どうしてこのエラーが出てしまうのか、このエラーは回避できるのか、また回避できるならどうすべきなのかを教えていただけますでしょうか。
Re: 弾がうまく発射できない
Posted: 2021年9月14日(火) 00:04
by みけCAT
ヨッシー さんが書きました: ↑3年前
ちなみにつっこまれていました配列の要素数が25だったりDefine::PBULLET_NUMだったりするのは、const static intで宣言すると配列の定義の際、要素数に用いることができなかったためです。
const static int で宣言しても要素数に使えそうですが、どのようなエラーになりましたか?
コード:
namespace Define {
const static int a = 4;
const static int b = 100;
};
void x(){
int c[Define::a][Define::b / 4];
}
ヨッシー さんが書きました: ↑3年前
PlayerOptionクラス(ソースは省きます)の座標用変数をもとにBullet[][]に座標を代入しようとした際に「静的でないメンバー参照は特定のオブジェクトを基準とする相対参照である必要があります」というエラーが出てしまい、デバッグ以前の問題となっている次第です。
静的でないメンバーはインスタンスごとに存在するので、
「このクラスの変数」でなく、「このインスタンスの変数」というふうに指定しないと困ってしまいます。
コード:
class SomeClass {
public:
int x = 0; // 静的でないメンバ
};
SomeClass classObj; // あるインスタンス
void func() {
// 「このクラスの変数」という指定 (エラー)
int a = SomeClass::x;
// 「このインスタンスの変数」という指定
int b = classObj.x;
}
ヨッシー さんが書きました: ↑3年前
以前からこのエラーはちょくちょく出ていて、自分の解釈としては静的メンバ関数(今回の場合void draw() const)内で外部の動的メンバを使用しようとした際に出るものだと思っていました、がその解釈が間違っていたようで困っています。
今回の void draw() const は静的ではないので、静的メンバ関数ではありません。
Re: 弾がうまく発射できない
Posted: 2021年9月14日(火) 22:46
by ヨッシー
Define::PBULLET_NUMについてのエラー内容は「式には定数値が必要です。メンバー"Define::PBULLET_NUM"を定数の値として使うことはできません。」というものです。
あと、調べなおしてみると静的メンバというのはstaticがついているもののことを言うようですね。。失礼しました。
今日の進捗としては、PlayerBulletにてPlayerOptionの座標を参照しようと思った時、PlayerOptionのインスタンスを作る必要があると思って自分なりにやってみました。
コード:
PlayerOption.h
#pragma once
#include "Task.h"
#include "Player.h"
class PlayerOption : public Task
{
friend class PlayerOptionCollection;
friend class PlayerBulletCollection;
public:
PlayerOption();
virtual ~PlayerOption() = default;
void draw() const override;
bool update() override;
protected:
float _x, _y; //座標
int cnt; //カウンタ用変数
};
class PlayerOptionCollection : public Task
{
friend class PlayerOption;
public:
PlayerOptionCollection();
virtual ~PlayerOptionCollection() = default;
bool update() override;
void draw() const override;
private:
PlayerOption Option[4];
void move();
float _x, _y; //Playerクラスの_x,_yと同じ動きをさせる。
};
PlayerOption.cpp
#include "PlayerOption.h"
#include "Pad.h"
#include <DxLib.h>
#include "Image.h"
#include "Define.h"
#include "Looper.h"
const static float SPEED = 9;
PlayerOption::PlayerOption() :
_x((float)Define::CENTER_X),
_y((float)Define::OUT_H * 0.8f)
{
cnt = 0;
}
void PlayerOption::draw() const
{
DrawRotaGraphF(_x, _y, 1.5, Define::PI / 180 * cnt, Image::getIns()->getPlayerOption(), TRUE);
}
bool PlayerOption::update()
{
return true;
}
PlayerOptionCollection::PlayerOptionCollection() :
_x((float)Define::CENTER_X),
_y((float)Define::OUT_H * 0.8f)
{
}
bool PlayerOptionCollection::update()
{
for (int i = 0; i < 4; i++) {
Option[i].cnt++;
}
void move();
return true;
}
void PlayerOptionCollection::draw() const
{
for (int i = 0; i < 4; i++) {
Option[i].draw();
}
}
void PlayerOptionCollection::move() //Playerクラスと同じ処理を行い、その値をPlayerOption Option[]の座標の更新の際に用いる。
{
float moveX = 0, moveY = 0;
if (Pad::getIns()->get(ePad::left) > 0) { //左移動
moveX -= SPEED;
}
if (Pad::getIns()->get(ePad::right) > 0) { //右移動
moveX += SPEED;
}
if (Pad::getIns()->get(ePad::down) > 0) { //下移動
moveY += SPEED;
}
if (Pad::getIns()->get(ePad::up) > 0) { //上移動
moveY -= SPEED;
}
if (moveX && moveY) { //斜め移動
moveX /= (float)sqrt(2.0);
moveY /= (float)sqrt(2.0);
}
if (Pad::getIns()->get(ePad::slow) > 0) { //低速移動
moveX /= 3;
moveY /= 3;
}
if (moveX + _x < Define::IN_X) { //左枠より左なら
_x = (float)Define::IN_X; //左枠で止める
}
else if (moveX + _x > Define::IN_X + Define::IN_W) { //右枠より右なら
_x = (float)(Define::IN_X + Define::IN_W); //右枠で止める
}
else { //枠内なら
_x += moveX; //普通に移動
}
if (moveY + _y < Define::IN_Y) { //上枠より上なら
_y = (float)Define::IN_Y; //上枠で止める
}
else if (moveY + _y > Define::IN_Y + Define::IN_H) { //下枠より下なら
_y = (float)(Define::IN_Y + Define::IN_H); //下枠で止める
}
else { //枠内なら
_y += moveY; //普通に移動
}
for (int i = 0; i < 4; i++) { //上で計算した_x, _yに自機から見たオプションの座標coption0posを足したものを代入する。
Option[i]._x = _x + Define::coption0pos_x[i];
Option[i]._y = _y + Define::coption0pos_y[i];
}
}
このコードでコンパイルも無事通り、いざデバッグしてみると、今度はオプションの画像が最初の場所で動かずに重なって表示されてしまいました。自分なりにPlayerOption::draw()で変数(_x, _y, cnt)を参照するときにPlayerOptionのコンストラクタの値が用いられているのではと考えましたが、画像を回転させながら描画させるDefine::PI / 180 * cntが問題なく処理できていたので見当違いだと思われます。この事と最初の場所から動かない事からソースコードの一番最後のfor文によるOption[]の座標の更新がうまくいっていないと思うのですが、どう変更したらいいのかがイマイチうかばず、、アドバイスをいただきたいです。
Re: 弾がうまく発射できない
Posted: 2021年9月15日(水) 01:41
by みけCAT
関数
コード:
bool PlayerOptionCollection::update()
内の行
はmove関数を宣言しているだけであり、move関数の呼び出しは行われません。
move関数を呼び出したければ、
とするべきです。
Re: 弾がうまく発射できない
Posted: 2021年9月17日(金) 22:21
by ヨッシー
指摘された部分を直してコンパイルしてみたところ、無事思った通りに動きました。
このままPlayerBulletも当初の予定とは違う形ですが実装することが出来ました!!
返信してくれた方々や、同じような問題で悩んでいる方に向けて自分はどうやって実装したかソースコードを載せときます(かなり汚いけど)。
コード:
PlayerBullet.h
#pragma once
#include "Player.h"
#include "PlayerOption.h"
#include "Define.h"
class PlayerBullet : public Task
{
friend class PlayerOption;
friend class PlayerBulletCollection;
public:
PlayerBullet();
virtual ~PlayerBullet() = default;
bool update() override;
void draw() const override;
protected:
int type; //種類
bool flag; //フラグ
float _x, _y; //座標
float speed; //スピード
};
class PlayerBulletCollection : public Task
{
friend class PlayerOption;
friend class PlayerOptionCollection;
public:
PlayerBulletCollection();
virtual ~PlayerBulletCollection() = default;
bool update() override;
void draw() const override;
private:
PlayerBullet Bullet[4][25];
void move();
void shot();
float _x, _y;
int cnt;
};
PlayerBullet.cpp
#include "PlayerBullet.h"
#include <DxLib.h>
#include "Pad.h"
#include "Define.h"
#include "Image.h"
const static float SPEED = 9.0;
PlayerBullet::PlayerBullet() :
_x((float)Define::CENTER_X),
_y((float)Define::OUT_H * 0.8f)
{
flag = 0;
speed = 25;
}
bool PlayerBullet::update()
{
return true;
}
void PlayerBullet::draw() const
{
DrawRotaGraphF(_x, _y, 1.0, 0.0, Image::getIns()->getPlayerBullet()[1], FALSE);
}
PlayerBulletCollection::PlayerBulletCollection() :
_x((float)Define::CENTER_X),
_y((float)Define::OUT_H * 0.8f)
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
Bullet[i][j].flag = false;
}
}
cnt = 0;
}
bool PlayerBulletCollection::update()
{
move();
shot();
cnt++;
return true;
}
void PlayerBulletCollection::draw() const
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == true)
{
Bullet[i][j].draw();
}
}
}
}
void PlayerBulletCollection::move() {
float moveX = 0, moveY = 0;
if (Pad::getIns()->get(ePad::left) > 0) { //左移動
moveX -= SPEED;
}
if (Pad::getIns()->get(ePad::right) > 0) { //右移動
moveX += SPEED;
}
if (Pad::getIns()->get(ePad::down) > 0) { //下移動
moveY += SPEED;
}
if (Pad::getIns()->get(ePad::up) > 0) { //上移動
moveY -= SPEED;
}
if (moveX && moveY) { //斜め移動
moveX /= (float)sqrt(2.0);
moveY /= (float)sqrt(2.0);
}
if (Pad::getIns()->get(ePad::slow) > 0) { //低速移動
moveX /= 3;
moveY /= 3;
}
if (moveX + _x < Define::IN_X) { //左枠より左なら
_x = (float)Define::IN_X; //左枠で止める
}
else if (moveX + _x > Define::IN_X + Define::IN_W) { //右枠より右なら
_x = (float)(Define::IN_X + Define::IN_W); //右枠で止める
}
else { //枠内なら
_x += moveX; //普通に移動
}
if (moveY + _y < Define::IN_Y) { //上枠より上なら
_y = (float)Define::IN_Y; //上枠で止める
}
else if (moveY + _y > Define::IN_Y + Define::IN_H) { //下枠より下なら
_y = (float)(Define::IN_Y + Define::IN_H); //下枠で止める
}
else { //枠内なら
_y += moveY; //普通に移動
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == true)
{
Bullet[i][j]._y -= Bullet[i][j].speed;
if (Bullet[i][j]._y <= Define::IN_Y)
{
Bullet[i][j].flag = false;
}
}
}
}
}
void PlayerBulletCollection::shot()
{
if (Pad::getIns()->get(ePad::shot) && cnt % 7 == 0) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < Define::PBULLET_NUM / 4; j++) {
if (Bullet[i][j].flag == false) {
if (Pad::getIns()->get(ePad::slow)) {
Bullet[i][j]._x = _x + Define::coption1pos_x[i];
Bullet[i][j]._y = _y + Define::coption1pos_y[i] - 20;
}
else
{
Bullet[i][j]._x = _x + Define::coption0pos_x[i];
Bullet[i][j]._y = _y + Define::coption0pos_y[i] - 20;
}
Bullet[i][j].flag = true;
break;
}
}
}
}
}
自分の質問に答えてくださったお二方にはとても感謝しております。
違う内容で行き詰ったときにまたお世話になるかもしれません。 それでは。