鱼C论坛

 找回密码
 立即注册
查看: 725|回复: 5

绘制子弹崩溃

[复制链接]
发表于 2023-5-4 18:50:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 猪猪虾 于 2023-5-4 18:52 编辑

(我感觉在出连续剧 ,一天更新一点。。。)
同样的方法,绘制飞机可以,绘制子弹就不行了
我先尝试简单的绘制一个子弹,只不过在绘制子弹的时候,子弹的位置是要用到飞机类,也就是要用到飞机的位置,所以在子弹类里面调用了飞机的位置,绘制飞机的位置在 GameMain。cpp的upwindow函数里面
捕获.PNG
#pragma once
#include<graphics.h>
#include<cstring>
#include<vector>

using namespace std;
class GameMain;
class MyPlane;

class Bullet 
{
public:
        Bullet(GameMain* gm, MyPlane* mp);  //  Bullet  类的构造函数中使用了 GameMain 类的指针  GM 。但是,你没有初始化这个指针
        static IMAGE getImage_Bullet();
        void Move();

        int Bullte_current_posiX;
        int Bullte_current_posiY;
        int width;
        int height;
        int Bullet_pace;
        bool BT_IsAlive;
private:
        static IMAGE imgBullet;  //static 成员变量属于类,不属于某个具体的对象,即使创建多个对象,也只为 static 成员变量分配一份内存,所有对象使用的都是这份内存中的数据。
        GameMain* GM;
        MyPlane* MP;
};

#pragma once
#include<graphics.h>
#include<cstring>
#include<vector>

#include "Bullet.h"
#include "GameMain.h"
#include "MyPlane.h"

//静态成员,需要在类外进行声明
IMAGE Bullet::imgBullet;  // 这一行为 imgMyplane 分配内存空间

Bullet::Bullet(GameMain* gm,MyPlane* mp):GM(gm),MP(mp)
{
        width = 5;
        height = 10;
        Bullet_pace = 20;
        BT_IsAlive = true;

        loadimage(&imgBullet, "E:/2022上/Leecode_April/plane/image/bullet1.png");

        //初始化飞机的位置在图像的正下方的中心
        Bullte_current_posiX = MP->My_current_posiX ;
        Bullte_current_posiY = MP->My_current_posiY - MP->height;
}


IMAGE Bullet::getImage_Bullet()
{
        return imgBullet;
}

void Bullet::Move()
{
        Bullte_current_posiY -= Bullet_pace;
        if (Bullte_current_posiY < 0) { BT_IsAlive = false; }
}
#pragma once
#include<graphics.h>
#include<cstring>
#include<vector>
//#include "GameMain.h"
using namespace std;
class GameMain;


class MyPlane
{
public:
        MyPlane(GameMain* gm);  //  MyPlane  类的构造函数中使用了 GameMain 类的指针  GM 。但是,你没有初始化这个指针
        //static IMAGE getImages();    //私有成员可以在public里面,通过函数来间接访问和修改
        void Move(int dx, int dy);
        static IMAGE getImage_Myplane();

        int My_current_posiX;
        int My_current_posiY;
        int width;
        int height;
        int pace;   //每次按键飞机移动的距离
private:
        static IMAGE imgMyplane;
        GameMain *GM;
};
#pragma once
#include<graphics.h>
#include<cstring>
#include<vector>
//#include<MyPlane.h> 如果这里这么用,会发现 当前.h文件和MyPlane.h文件的彼此头文件相互包含,会报错
class MyPlane;  //告诉编译器,需要这个类,其他功能结构都没变
class Bullet;
using namespace std;

class GameMain
{
public:
        //构造函数  用于初始化参数,游戏界面设置

        GameMain();

        //注意,你需要在  GameMain  类的析构函数中删除  MyPlane  
   //类的实例*以避免内存泄漏。在  GameMain  类中添加一个析构函数,并在其中删除  MP :GameMain.h文件
        ~GameMain();  // 添加析构函数
        //游戏界面初始化
        void init(); 
        void paly(); // 开始游戏
        //int* getBgSize();

        int rows;
        int cols;

private:
        void keyEvent();  //按键控制
        void updateWindow();  //渲染界面

private:
        bool update;

        // 添加这一行,这样其他地方调用这个类的时候,就不用每次都申明,不同地方申明,还是不同的对象,无法
        //实现同时操作一辆飞机
        MyPlane *MP;
        Bullet *BT;
        //背景图像参数
        IMAGE imgBg;  //背景图片

        //创建一个动态数组bullets,里面的元素都是一个个Bullet对象
        //std::vector<Bullet> bullets;  // 添加子弹容器
};


#include "GameMain.h"
#include "MyPlane.h"
#include "Bullet.h"
#include<stdlib.h>
#include <time.h>
#include<graphics.h>
#include <conio.h>
#include"iostream"
#include"string"
#include "fstream"
//音效
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"WINMM.LIB")

using namespace std;

GameMain::GameMain()
{
        update = true;
        rows = 438;
        cols = 675;
        MP = new MyPlane(this);  // 在创建 MyPlane 实例时传递 GameMain 类的指针
        BT = new Bullet(this, MP);
        // 为 MyPlane 类对象的指针 MP 分配内存空间
        //MP = new MyPlane();
        //将游戏界面的宽度指定成背景图片的显示宽度

}

//析构函数主要作用就是释放资源, 避免内存泄漏
GameMain::~GameMain()
{
        delete MP;  // 删除 MyPlane 实例
        delete BT;
}

void GameMain::init()
{
        //播放背景音乐
        mciSendString("play E:/res/bg.mp3 repeat", 0, 0, 0); 

        //创建游戏窗口
        *initgraph(rows, cols);

        //加载背景图片
        loadimage(&imgBg, "E:/Leecode_April/plane/image/background.png");

        
}

void GameMain::paly()
{
        init();

        update = true;
        while (1)
        {
                //BeginBatchDraw();

                //接收用户的输入
                keyEvent();
                if (update == true) {
                        //更新游戏画面
                        updateWindow();
                }
                
                //system("pause");
                //EndBatchDraw();
        }
}

//int* GameMain::getBgSize()
//{
//        int num[] = { rows ,cols };
//        int* ptr = new int[2];
//        for (int i = 0; i < 2; i++) {
//                ptr[i] = num[i];
//        }
//        return ptr;
//}


void GameMain::keyEvent()
{
        unsigned char ch;
        int dx = 0;
        int dy = 0;

        //判断当前有没有按键输入,如果他没有按键输入,程序正常执行
        if (_kbhit()) {
                ch = _getch();

                //按下字母,返回的就是字母,按下的是方向键
                //上,先后返回: 224 72  下:224 80   左:75 224,75  右:224 77
                if (ch == 224) {
                        ch = _getch();
                        switch (ch) {
                        case 72:
                                dy = -MP->pace;
                                break;
                        case 80:
                                dy = MP->pace;
                                break;
                        case 75:
                                dx = -MP->pace;
                                break;
                        case 77:
                                dx = MP->pace;
                                break;
                        default:
                                break;
                        }
                }
        }
        if (dx != 0 || dy != 0)  //左右移动
        {
//                MyPlane MP;
                MP->Move(dx,dy);
                update = true;
        }
}

void GameMain::updateWindow()
{
        putimage(0, 0, &imgBg);
        BeginBatchDraw();

        //绘制我方飞机
        //MyPlane MP;
        IMAGE TEMP_my;
        TEMP_my = MP->getImage_Myplane();
        putimage(MP->My_current_posiX, MP->My_current_posiY, &TEMP_my);

        /*绘制子弹
        Bullet BT;*/
        //IMAGE TEMP_BT;
        //TEMP_BT = BT.getImage_Bullet();
        //putimage(MP->My_current_posiX, MP->My_current_posiY, &TEMP_BT);
        //for (Bullet& bullet : bullets) {
        //        bullet.update();  // 更新子弹位置
        //        IMAGE TEMP_BT;
        //        TEMP_BT = bullet.getImage_Bullet();
        //        putimage(bullet.getPosX(), bullet.getPosY(), &TEMP_BT);
        //}

   //绘制子弹
        IMAGE TEMP_BT;
        TEMP_BT = BT->getImage_Bullet();
        putimage(BT->Bullte_current_posiX, BT->Bullte_current_posiY, &TEMP_BT);

        EndBatchDraw();
}

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-4 19:03:33 | 显示全部楼层
在子弹类里面调用了飞机的位置,可能是因为未正确初始化 MyPlane 对象,导致子弹无法获取到正确的飞机位置。建议将 MyPlane 对象的初始化代码移动到 GameMain 类的构造函数中,并在 Bullet 类中传入 GameMain 对象和 MyPlane 对象的引用,以便子弹类能够正确获取飞机位置并进行绘制。同时,也需要在 GameMain::updateWindow() 中根据子弹对象的当前位置来更新子弹的绘制位置。以下是示例代码:
// GameMain.h

class GameMain
{
public:
    GameMain();
    ~GameMain();

    // ...

private:
    MyPlane MP;
    Bullet BT;

    // ...
};

// Bullet.h

#include "GameMain.h"
#include "MyPlane.h"

class Bullet {
public:
    Bullet(GameMain& game, MyPlane& plane);
    ~Bullet();

    void update();
    IMAGE getImage_Bullet();

private:
    GameMain& m_game; // 引用 GameMain 对象
    MyPlane& m_plane; // 引用 MyPlane 对象

    int Bullte_width=8;
    int Bullte_height=24;
    int Bullte_current_posiX;
    int Bullte_current_posiY;
    IMAGE img_DM_bullet;
};

// Bullet.cpp

Bullet::Bullet(GameMain& game, MyPlane& plane)
    : m_game(game), m_plane(plane)
{
    Bullte_current_posiX = m_plane.My_current_posiX + m_plane.width / 2 - Bullte_width / 2;
    Bullte_current_posiY = m_plane.My_current_posiY - Bullte_height;
    loadimage(&img_DM_bullet, "E:/cpp_proj/plane/image/bullet.png");
}

void Bullet::update()
{
    Bullte_current_posiY -= 10; // 子弹向上移动
    if (Bullte_current_posiY < 0) // 当子弹飞出屏幕时,重置子弹位置
    {
        Bullte_current_posiX = m_plane.My_current_posiX + m_plane.width / 2 - Bullte_width
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-4 19:45:02 | 显示全部楼层
sfqxx 发表于 2023-5-4 19:03
在子弹类里面调用了飞机的位置,可能是因为未正确初始化 MyPlane 对象,导致子弹无法获取到正确的飞机位置 ...

在class GameMain.h里面定义   这种MyPlane MP而不是这种 MyPlane *MP;我这边会显示使用没有定义的class,我一开始就想不用指针的形式,后来没办法才用的指针
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-4 19:49:24 | 显示全部楼层
猪猪虾 发表于 2023-5-4 19:45
在class GameMain.h里面定义   这种MyPlane MP而不是这种 MyPlane *MP;我这边会显示使用没有定义的class ...

然后呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-4 20:19:38 | 显示全部楼层
看起来你的代码想要实现一个飞机发射子弹的游戏。你可以成功地绘制飞机,但在绘制子弹时出现了问题。这是因为你在子弹类中使用了飞机的位置来初始化子弹的位置。在你的GameMain类中,你已经创建了一个MyPlane实例(MP)和一个Bullet实例(BT)。

要解决这个问题:

首先,在GameMain类中,添加一个表示子弹列表的向量成员:
vector<Bullet*> bullets;

接着,在 keyEvent 函数中,当按下空格键时创建新的Bullet实例并添加到子弹列表中:
if (_kbhit()) {
    ch = _getch();
    // 添加以下代码来处理空格键按下
    if (ch == 32) { 
        Bullet* newBullet = new Bullet(this, MP);
        bullets.push_back(newBullet);
    } else if (ch == 224) {
    ...
}

为了避免内存泄漏,记得在GameMain的析构函数删除bullets向量中所有创建的Bullet实例:
GameMain::~GameMain() {
    delete MP;

    for (Bullet* bullet : bullets){
        delete bullet;
    }
}

最后,在 updateWindow 函数中,遍历bullets向量中的每一个bullet,并更新它们的位置,然后绘制它们:
for (Bullet* bullet : bullets) {
    bullet->Move();
    IMAGE TEMP_BT;
    TEMP_BT = bullet->getImage_Bullet();
    putimage(bullet->Bullte_current_posiX, bullet->Bullte_current_posiY, &TEMP_BT);
}

现在,当你按下空格键时,子弹应该会从飞机的位置创建并向上移动。请注意,上述更改可能无法解决所有问题,你可能需要调整一些其他部分以确保游戏按预期工作。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-5 16:12:36 | 显示全部楼层
本帖最后由 猪猪虾 于 2023-5-5 16:15 编辑
isdkz 发表于 2023-5-4 20:19
看起来你的代码想要实现一个飞机发射子弹的游戏。你可以成功地绘制飞机,但在绘制子弹时出现了问题。这是因 ...


这是因为你在子弹类中使用了飞机的位置来初始化子弹的位置。这个理论上也没啥毛病吧,问题的本质是啥呢,我断点进入子弹的构造函数,子弹的位置是被赋予了的,一直执行到绘图的时候才崩溃

您提供的修改是绘图方式的不同,我那个可能就一次只绘制了一颗子弹
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-28 01:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表