猪猪虾 发表于 2023-4-27 21:56:05

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

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

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


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


也就是说*****************************
那段设置起始位置的程序除了放在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;
        //int MyPlaneHeight = temp;
        //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;
        int MyPlaneHeight = temp;
        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();
}

ba21 发表于 2023-4-27 23:01:05

构造函数 是初始化,只执行一次
updateWindow() 是实时执行,刷新窗体是时时咳咳都在进行的。

isdkz 发表于 2023-4-28 00:47:30

从你的代码来看,问题在于你在`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;
    int MyPlaneHeight = temp;
    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;
    int MyPlaneHeight = temp;
    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;
      int MyPlaneHeight = temp;
      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;
      int MyPlaneHeight = temp;
      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()`函数将正确显示飞机的当前位置,而不会每次刷新都回到初始位置。这样,你可以实现飞机在游戏中的实时移动。

猪猪虾 发表于 2023-4-28 13:59:38

isdkz 发表于 2023-4-28 00:47
从你的代码来看,问题在于你在`GameMain`构造函数以及`updateWindow`函数中分别创建了不同的`MyPlane`对象 ...

谢谢大哥

yinda_peng 发表于 2023-4-28 16:19:57

猪猪虾 发表于 2023-4-28 13:59
谢谢大哥

是xie xie gpt
页: [1]
查看完整版本: c++putimage函数使用,为啥在构造函数里初始化飞机位置无效