鱼C论坛

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

[已解决]c++putimage函数使用,为啥在构造函数里初始化飞机位置无效

[复制链接]
发表于 2023-4-27 21:56:05 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 猪猪虾 于 2023-4-27 21:57 编辑

这个图是将下面这段程序放在void GameMain::updateWindow()函数里面的效果
        //初始化飞机的位置在图像的正下方的中心
        MyPlane mp;
        int* temp = mp.getMyPlaneSize();
        int MyPlaneWidth = temp[0];
        int MyPlaneHeight = temp[1];
        int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        int My_current_posiY = cols - MyPlaneHeight;
捕获.PNG

下面这个图是将下面这段程序放在GameMain::GameMain()构造函数里面的效果
        //初始化飞机的位置在图像的正下方的中心
        MyPlane mp;
        int* temp = mp.getMyPlaneSize();
        int MyPlaneWidth = temp[0];
        int MyPlaneHeight = temp[1];
        int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        int My_current_posiY = cols - MyPlaneHeight;
2.PNG

也就是说*****************************
那段设置起始位置的程序除了放在void GameMain::updateWindow()里面有效,放在其他函数里面都无效,我尝试过,但是我不想把这段程序放在updateWindow()里面,因为飞机的位置要实时改变,只能指定初始位置,如果放在updateWindow()里面,每次刷新都
回到初始位置,bug无疑了
#include "GameMain.h"
#include "MyPlane.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()
{
        //将游戏界面的宽度指定成背景图片的显示宽度
        rows = 438;
        cols = 675;

        //初始化飞机的位置在图像的正下方的中心
        //MyPlane mp;
        //int* temp = mp.getMyPlaneSize();
        //int MyPlaneWidth = temp[0];
        //int MyPlaneHeight = temp[1];
        //int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        //int My_current_posiY = cols - MyPlaneHeight;
}

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");
        loadimage(&imgMyplane, "E:/Leecode_April/plane/image/me1.png"); 
        loadimage(&imgBullet, "E:/Leecode_April/plane/image/bullet1.png");

        update = true;

}

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

        while (1)
        {
                BeginBatchDraw();
                //接收用户的输入
                keyEvent();

                //更新游戏画面
                updateWindow();
                system("pause");
                EndBatchDraw();
        }
}

IMAGE GameMain::getImage_Myplane()
{
        return imgMyplane;
}

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

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 = 1;
                                break;
                        case 80:
                                dy = -1;
                                break;
                        case 75:
                                dx = -1;
                                break;
                        case 77:
                                dx = 1;
                                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;
        int* temp = mp.getMyPlaneSize();
        int MyPlaneWidth = temp[0];
        int MyPlaneHeight = temp[1];
        int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        int My_current_posiY = cols - MyPlaneHeight;
        putimage(My_current_posiX, My_current_posiY, &imgMyplane);
        putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

        EndBatchDraw();
}
最佳答案
2023-4-28 00:47:30
[b]从你的代码来看,问题在于你在`GameMain`构造函数以及`updateWindow`函数中分别创建了不同的`MyPlane`对象。这些对象是独立的,每个对象的位置信息都是单独的。当你在`keyEvent`函数中移动飞机时,你也是在操作一个独立的`MyPlane`对象。由于`updateWindow`函数中的`MyPlane`对象没有被移动,因此每次更新画面时飞机的位置没有改变。

为了解决这个问题,你需要将飞机对象的创建放在`GameMain`类的成员变量中。这样,在整个`GameMain`类中,只有一个`MyPlane`对象,其位置信息将在各个函数间共享。

修改方法如下:

1. 在`GameMain.h`中添加一个成员变量`MyPlane mp;`,例如:
class GameMain
{
public:
    GameMain();
    void init();
    void paly();
    IMAGE getImage_Myplane();
    IMAGE getImage_Bullet();
    void keyEvent();
    void updateWindow();

private:
    int rows;
    int cols;
    MyPlane mp; // 添加这一行
    IMAGE imgBg;
    IMAGE imgMyplane;
    IMAGE imgBullet;
    bool update;
};

2. 将你想放入`GameMain`构造函数的初始化代码移到`GameMain::init()`函数中。这样,在构造函数中不再创建新的`MyPlane`对象,而是使用`init()`函数中的成员变量`mp`:
void GameMain::init()
{
    // 其他初始化代码...

    // 初始化飞机的位置在图像的正下方的中心
    int* temp = mp.getMyPlaneSize();
    int MyPlaneWidth = temp[0];
    int MyPlaneHeight = temp[1];
    int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
    int My_current_posiY = cols - MyPlaneHeight;

    // 其他初始化代码...
}

3. 在`keyEvent`函数和`updateWindow`函数中,去掉局部的`MyPlane`对象创建,直接使用`GameMain`类的成员变量`mp`,例如:
void GameMain::keyEvent()
{
    // 其他代码...
    if (dx != 0 || dy != 0)  //左右移动
    {
        mp.Move(dx,dy); // 修改这一行
        update = true;
    }
}

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

    BeginBatchDraw();
    int* temp = mp.getMyPlaneSize();
    int MyPlaneWidth = temp[0];
    int MyPlaneHeight = temp[1];
    int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
    int My_current_posiY = cols - MyPlaneHeight;
    putimage(My_current_posiX, My_current_posiY, &imgMyplane);
    putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

    EndBatchDraw();
}

这样修改后,你的飞机对象`mp`将在`GameMain`类中各个函数之间共享,你可以在`GameMain::init()`函数中设置飞机的初始位置,并在`keyEvent`函数中实现飞机的移动。`updateWindow`函数将正确显示飞机的当前位置,而不会每次刷新都回到初始位置。

这里是修改后的完整`GameMain`类的实现:
#include "GameMain.h"
#include "MyPlane.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()
{
        //将游戏界面的宽度指定成背景图片的显示宽度
        rows = 438;
        cols = 675;
}

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");
        loadimage(&imgMyplane, "E:/Leecode_April/plane/image/me1.png"); 
        loadimage(&imgBullet, "E:/Leecode_April/plane/image/bullet1.png");

        // 初始化飞机的位置在图像的正下方的中心
        int* temp = mp.getMyPlaneSize();
        int MyPlaneWidth = temp[0];
        int MyPlaneHeight = temp[1];
        int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        int My_current_posiY = cols - MyPlaneHeight;

        update = true;
}

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

        while (1)
        {
                BeginBatchDraw();
                //接收用户的输入
                keyEvent();

                //更新游戏画面
                updateWindow();
                system("pause");
                EndBatchDraw();
        }
}

IMAGE GameMain::getImage_Myplane()
{
        return imgMyplane;
}

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

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 = 1;
                                break;
                        case 80:
                                dy = -1;
                                break;
                        case 75:
                                dx = -1;
                                break;
                        case 77:
                                dx = 1;
                                break;
                        default:
                                break;
                        }
                }
        }
        if (dx != 0 || dy != 0)  // 左右移动
        {
                mp.Move(dx,dy); // 使用成员变量mp
                update = true;
        }
}

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

        BeginBatchDraw();
        int* temp = mp.getMyPlaneSize(); // 使用成员变量mp
        int MyPlaneWidth = temp[0];
        int MyPlaneHeight = temp[1];
        int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        int My_current_posiY = cols - MyPlaneHeight;
        putimage(My_current_posiX, My_current_posiY, &imgMyplane);
        putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

        EndBatchDraw();
}

现在,你的代码应该可以正常工作。飞机的初始位置将在`GameMain::init()`函数中设置,而且当飞机移动时,`GameMain::keyEvent()`函数将更新飞机的位置。`GameMain::updateWindow()`函数将正确显示飞机的当前位置,而不会每次刷新都回到初始位置。这样,你可以实现飞机在游戏中的实时移动。
[/b]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-27 23:01:05 | 显示全部楼层
构造函数 是初始化,只执行一次
updateWindow() 是实时执行,刷新窗体是时时咳咳都在进行的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-28 00:47:30 | 显示全部楼层    本楼为最佳答案   
[b]从你的代码来看,问题在于你在`GameMain`构造函数以及`updateWindow`函数中分别创建了不同的`MyPlane`对象。这些对象是独立的,每个对象的位置信息都是单独的。当你在`keyEvent`函数中移动飞机时,你也是在操作一个独立的`MyPlane`对象。由于`updateWindow`函数中的`MyPlane`对象没有被移动,因此每次更新画面时飞机的位置没有改变。

为了解决这个问题,你需要将飞机对象的创建放在`GameMain`类的成员变量中。这样,在整个`GameMain`类中,只有一个`MyPlane`对象,其位置信息将在各个函数间共享。

修改方法如下:

1. 在`GameMain.h`中添加一个成员变量`MyPlane mp;`,例如:
class GameMain
{
public:
    GameMain();
    void init();
    void paly();
    IMAGE getImage_Myplane();
    IMAGE getImage_Bullet();
    void keyEvent();
    void updateWindow();

private:
    int rows;
    int cols;
    MyPlane mp; // 添加这一行
    IMAGE imgBg;
    IMAGE imgMyplane;
    IMAGE imgBullet;
    bool update;
};

2. 将你想放入`GameMain`构造函数的初始化代码移到`GameMain::init()`函数中。这样,在构造函数中不再创建新的`MyPlane`对象,而是使用`init()`函数中的成员变量`mp`:
void GameMain::init()
{
    // 其他初始化代码...

    // 初始化飞机的位置在图像的正下方的中心
    int* temp = mp.getMyPlaneSize();
    int MyPlaneWidth = temp[0];
    int MyPlaneHeight = temp[1];
    int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
    int My_current_posiY = cols - MyPlaneHeight;

    // 其他初始化代码...
}

3. 在`keyEvent`函数和`updateWindow`函数中,去掉局部的`MyPlane`对象创建,直接使用`GameMain`类的成员变量`mp`,例如:
void GameMain::keyEvent()
{
    // 其他代码...
    if (dx != 0 || dy != 0)  //左右移动
    {
        mp.Move(dx,dy); // 修改这一行
        update = true;
    }
}

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

    BeginBatchDraw();
    int* temp = mp.getMyPlaneSize();
    int MyPlaneWidth = temp[0];
    int MyPlaneHeight = temp[1];
    int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
    int My_current_posiY = cols - MyPlaneHeight;
    putimage(My_current_posiX, My_current_posiY, &imgMyplane);
    putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

    EndBatchDraw();
}

这样修改后,你的飞机对象`mp`将在`GameMain`类中各个函数之间共享,你可以在`GameMain::init()`函数中设置飞机的初始位置,并在`keyEvent`函数中实现飞机的移动。`updateWindow`函数将正确显示飞机的当前位置,而不会每次刷新都回到初始位置。

这里是修改后的完整`GameMain`类的实现:
#include "GameMain.h"
#include "MyPlane.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()
{
        //将游戏界面的宽度指定成背景图片的显示宽度
        rows = 438;
        cols = 675;
}

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");
        loadimage(&imgMyplane, "E:/Leecode_April/plane/image/me1.png"); 
        loadimage(&imgBullet, "E:/Leecode_April/plane/image/bullet1.png");

        // 初始化飞机的位置在图像的正下方的中心
        int* temp = mp.getMyPlaneSize();
        int MyPlaneWidth = temp[0];
        int MyPlaneHeight = temp[1];
        int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        int My_current_posiY = cols - MyPlaneHeight;

        update = true;
}

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

        while (1)
        {
                BeginBatchDraw();
                //接收用户的输入
                keyEvent();

                //更新游戏画面
                updateWindow();
                system("pause");
                EndBatchDraw();
        }
}

IMAGE GameMain::getImage_Myplane()
{
        return imgMyplane;
}

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

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 = 1;
                                break;
                        case 80:
                                dy = -1;
                                break;
                        case 75:
                                dx = -1;
                                break;
                        case 77:
                                dx = 1;
                                break;
                        default:
                                break;
                        }
                }
        }
        if (dx != 0 || dy != 0)  // 左右移动
        {
                mp.Move(dx,dy); // 使用成员变量mp
                update = true;
        }
}

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

        BeginBatchDraw();
        int* temp = mp.getMyPlaneSize(); // 使用成员变量mp
        int MyPlaneWidth = temp[0];
        int MyPlaneHeight = temp[1];
        int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
        int My_current_posiY = cols - MyPlaneHeight;
        putimage(My_current_posiX, My_current_posiY, &imgMyplane);
        putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

        EndBatchDraw();
}

现在,你的代码应该可以正常工作。飞机的初始位置将在`GameMain::init()`函数中设置,而且当飞机移动时,`GameMain::keyEvent()`函数将更新飞机的位置。`GameMain::updateWindow()`函数将正确显示飞机的当前位置,而不会每次刷新都回到初始位置。这样,你可以实现飞机在游戏中的实时移动。
[/b]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-28 13:59:38 | 显示全部楼层
isdkz 发表于 2023-4-28 00:47
从你的代码来看,问题在于你在`GameMain`构造函数以及`updateWindow`函数中分别创建了不同的`MyPlane`对象 ...

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

使用道具 举报

发表于 2023-4-28 16:19:57 | 显示全部楼层

是xie xie gpt

点评

我很赞同!: 5.0
我很赞同!: 5
……  发表于 2023-4-29 00:11
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-10-7 15:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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