鱼C论坛

 找回密码
 立即注册
查看: 1540|回复: 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无疑了
  1. #include "GameMain.h"
  2. #include "MyPlane.h"
  3. #include<stdlib.h>
  4. #include <time.h>
  5. #include<graphics.h>
  6. #include <conio.h>
  7. #include"iostream"
  8. #include"string"
  9. #include "fstream"
  10. //音效
  11. #include<mmsystem.h>
  12. #pragma comment(lib,"winmm.lib")
  13. #pragma comment(lib,"WINMM.LIB")

  14. using namespace std;

  15. GameMain::GameMain()
  16. {
  17.         //将游戏界面的宽度指定成背景图片的显示宽度
  18.         rows = 438;
  19.         cols = 675;

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

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

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

  34.         //加载背景图片
  35.         loadimage(&imgBg, "E:/Leecode_April/plane/image/background.png");
  36.         loadimage(&imgMyplane, "E:/Leecode_April/plane/image/me1.png");
  37.         loadimage(&imgBullet, "E:/Leecode_April/plane/image/bullet1.png");

  38.         update = true;

  39. }

  40. void GameMain::paly()
  41. {
  42.         init();

  43.         while (1)
  44.         {
  45.                 BeginBatchDraw();
  46.                 //接收用户的输入
  47.                 keyEvent();

  48.                 //更新游戏画面
  49.                 updateWindow();
  50.                 system("pause");
  51.                 EndBatchDraw();
  52.         }
  53. }

  54. IMAGE GameMain::getImage_Myplane()
  55. {
  56.         return imgMyplane;
  57. }

  58. IMAGE GameMain::getImage_Bullet()
  59. {
  60.         return imgBullet;
  61. }

  62. void GameMain::keyEvent()
  63. {
  64.         unsigned char ch;
  65.         int dx = 0;
  66.         int dy = 0;

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

  70.                 //按下字母,返回的就是字母,按下的是方向键
  71.                 //上,先后返回: 224 72  下:224 80   左:75 224,75  右:224 77
  72.                 if (ch == 224) {
  73.                         ch = _getch();
  74.                         switch (ch) {
  75.                         case 72:
  76.                                 dy = 1;
  77.                                 break;
  78.                         case 80:
  79.                                 dy = -1;
  80.                                 break;
  81.                         case 75:
  82.                                 dx = -1;
  83.                                 break;
  84.                         case 77:
  85.                                 dx = 1;
  86.                                 break;
  87.                         default:
  88.                                 break;
  89.                         }
  90.                 }
  91.         }
  92.         if (dx != 0 || dy != 0)  //左右移动
  93.         {
  94.                 MyPlane mp;
  95.                 mp.Move(dx,dy);
  96.                 update = true;
  97.         }
  98. }

  99. void GameMain::updateWindow()
  100. {
  101.         putimage(0, 0, &imgBg);

  102.         BeginBatchDraw();
  103.         //初始化飞机的位置在图像的正下方的中心
  104.         MyPlane mp;
  105.         int* temp = mp.getMyPlaneSize();
  106.         int MyPlaneWidth = temp[0];
  107.         int MyPlaneHeight = temp[1];
  108.         int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
  109.         int My_current_posiY = cols - MyPlaneHeight;
  110.         putimage(My_current_posiX, My_current_posiY, &imgMyplane);
  111.         putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

  112.         EndBatchDraw();
  113. }

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

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

修改方法如下:

1. 在`GameMain.h`中添加一个成员变量`MyPlane mp;`,例如:

  1. class GameMain
  2. {
  3. public:
  4.     GameMain();
  5.     void init();
  6.     void paly();
  7.     IMAGE getImage_Myplane();
  8.     IMAGE getImage_Bullet();
  9.     void keyEvent();
  10.     void updateWindow();

  11. private:
  12.     int rows;
  13.     int cols;
  14.     MyPlane mp; // 添加这一行
  15.     IMAGE imgBg;
  16.     IMAGE imgMyplane;
  17.     IMAGE imgBullet;
  18.     bool update;
  19. };
复制代码


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

  1. void GameMain::init()
  2. {
  3.     // 其他初始化代码...

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

  10.     // 其他初始化代码...
  11. }
复制代码


3. 在`keyEvent`函数和`updateWindow`函数中,去掉局部的`MyPlane`对象创建,直接使用`GameMain`类的成员变量`mp`,例如:

  1. void GameMain::keyEvent()
  2. {
  3.     // 其他代码...
  4.     if (dx != 0 || dy != 0)  //左右移动
  5.     {
  6.         mp.Move(dx,dy); // 修改这一行
  7.         update = true;
  8.     }
  9. }

  10. void GameMain::updateWindow()
  11. {
  12.     putimage(0, 0, &imgBg);

  13.     BeginBatchDraw();
  14.     int* temp = mp.getMyPlaneSize();
  15.     int MyPlaneWidth = temp[0];
  16.     int MyPlaneHeight = temp[1];
  17.     int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
  18.     int My_current_posiY = cols - MyPlaneHeight;
  19.     putimage(My_current_posiX, My_current_posiY, &imgMyplane);
  20.     putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

  21.     EndBatchDraw();
  22. }
复制代码


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

这里是修改后的完整`GameMain`类的实现:

  1. #include "GameMain.h"
  2. #include "MyPlane.h"
  3. #include<stdlib.h>
  4. #include <time.h>
  5. #include<graphics.h>
  6. #include <conio.h>
  7. #include"iostream"
  8. #include"string"
  9. #include "fstream"
  10. //音效
  11. #include<mmsystem.h>
  12. #pragma comment(lib,"winmm.lib")
  13. #pragma comment(lib,"WINMM.LIB")

  14. using namespace std;

  15. GameMain::GameMain()
  16. {
  17.         //将游戏界面的宽度指定成背景图片的显示宽度
  18.         rows = 438;
  19.         cols = 675;
  20. }

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

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

  27.         //加载背景图片
  28.         loadimage(&imgBg, "E:/Leecode_April/plane/image/background.png");
  29.         loadimage(&imgMyplane, "E:/Leecode_April/plane/image/me1.png");
  30.         loadimage(&imgBullet, "E:/Leecode_April/plane/image/bullet1.png");

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

  37.         update = true;
  38. }

  39. void GameMain::paly()
  40. {
  41.         init();

  42.         while (1)
  43.         {
  44.                 BeginBatchDraw();
  45.                 //接收用户的输入
  46.                 keyEvent();

  47.                 //更新游戏画面
  48.                 updateWindow();
  49.                 system("pause");
  50.                 EndBatchDraw();
  51.         }
  52. }

  53. IMAGE GameMain::getImage_Myplane()
  54. {
  55.         return imgMyplane;
  56. }

  57. IMAGE GameMain::getImage_Bullet()
  58. {
  59.         return imgBullet;
  60. }

  61. void GameMain::keyEvent()
  62. {
  63.         unsigned char ch;
  64.         int dx = 0;
  65.         int dy = 0;

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

  69.                 //按下字母,返回的就是字母,按下的是方向键
  70.                 //上,先后返回: 224 72  下:224 80   左:75 224,75  右:224 77
  71.                 if (ch == 224) {
  72.                         ch = _getch();
  73.                         switch (ch) {
  74.                         case 72:
  75.                                 dy = 1;
  76.                                 break;
  77.                         case 80:
  78.                                 dy = -1;
  79.                                 break;
  80.                         case 75:
  81.                                 dx = -1;
  82.                                 break;
  83.                         case 77:
  84.                                 dx = 1;
  85.                                 break;
  86.                         default:
  87.                                 break;
  88.                         }
  89.                 }
  90.         }
  91.         if (dx != 0 || dy != 0)  // 左右移动
  92.         {
  93.                 mp.Move(dx,dy); // 使用成员变量mp
  94.                 update = true;
  95.         }
  96. }

  97. void GameMain::updateWindow()
  98. {
  99.         putimage(0, 0, &imgBg);

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

  108.         EndBatchDraw();
  109. }
复制代码


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

使用道具 举报

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

使用道具 举报

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

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

修改方法如下:

1. 在`GameMain.h`中添加一个成员变量`MyPlane mp;`,例如:

  1. class GameMain
  2. {
  3. public:
  4.     GameMain();
  5.     void init();
  6.     void paly();
  7.     IMAGE getImage_Myplane();
  8.     IMAGE getImage_Bullet();
  9.     void keyEvent();
  10.     void updateWindow();

  11. private:
  12.     int rows;
  13.     int cols;
  14.     MyPlane mp; // 添加这一行
  15.     IMAGE imgBg;
  16.     IMAGE imgMyplane;
  17.     IMAGE imgBullet;
  18.     bool update;
  19. };
复制代码


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

  1. void GameMain::init()
  2. {
  3.     // 其他初始化代码...

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

  10.     // 其他初始化代码...
  11. }
复制代码


3. 在`keyEvent`函数和`updateWindow`函数中,去掉局部的`MyPlane`对象创建,直接使用`GameMain`类的成员变量`mp`,例如:

  1. void GameMain::keyEvent()
  2. {
  3.     // 其他代码...
  4.     if (dx != 0 || dy != 0)  //左右移动
  5.     {
  6.         mp.Move(dx,dy); // 修改这一行
  7.         update = true;
  8.     }
  9. }

  10. void GameMain::updateWindow()
  11. {
  12.     putimage(0, 0, &imgBg);

  13.     BeginBatchDraw();
  14.     int* temp = mp.getMyPlaneSize();
  15.     int MyPlaneWidth = temp[0];
  16.     int MyPlaneHeight = temp[1];
  17.     int My_current_posiX = rows / 2 - MyPlaneWidth / 2;
  18.     int My_current_posiY = cols - MyPlaneHeight;
  19.     putimage(My_current_posiX, My_current_posiY, &imgMyplane);
  20.     putimage(My_current_posiX+50, My_current_posiY-50, &imgBullet);

  21.     EndBatchDraw();
  22. }
复制代码


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

这里是修改后的完整`GameMain`类的实现:

  1. #include "GameMain.h"
  2. #include "MyPlane.h"
  3. #include<stdlib.h>
  4. #include <time.h>
  5. #include<graphics.h>
  6. #include <conio.h>
  7. #include"iostream"
  8. #include"string"
  9. #include "fstream"
  10. //音效
  11. #include<mmsystem.h>
  12. #pragma comment(lib,"winmm.lib")
  13. #pragma comment(lib,"WINMM.LIB")

  14. using namespace std;

  15. GameMain::GameMain()
  16. {
  17.         //将游戏界面的宽度指定成背景图片的显示宽度
  18.         rows = 438;
  19.         cols = 675;
  20. }

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

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

  27.         //加载背景图片
  28.         loadimage(&imgBg, "E:/Leecode_April/plane/image/background.png");
  29.         loadimage(&imgMyplane, "E:/Leecode_April/plane/image/me1.png");
  30.         loadimage(&imgBullet, "E:/Leecode_April/plane/image/bullet1.png");

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

  37.         update = true;
  38. }

  39. void GameMain::paly()
  40. {
  41.         init();

  42.         while (1)
  43.         {
  44.                 BeginBatchDraw();
  45.                 //接收用户的输入
  46.                 keyEvent();

  47.                 //更新游戏画面
  48.                 updateWindow();
  49.                 system("pause");
  50.                 EndBatchDraw();
  51.         }
  52. }

  53. IMAGE GameMain::getImage_Myplane()
  54. {
  55.         return imgMyplane;
  56. }

  57. IMAGE GameMain::getImage_Bullet()
  58. {
  59.         return imgBullet;
  60. }

  61. void GameMain::keyEvent()
  62. {
  63.         unsigned char ch;
  64.         int dx = 0;
  65.         int dy = 0;

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

  69.                 //按下字母,返回的就是字母,按下的是方向键
  70.                 //上,先后返回: 224 72  下:224 80   左:75 224,75  右:224 77
  71.                 if (ch == 224) {
  72.                         ch = _getch();
  73.                         switch (ch) {
  74.                         case 72:
  75.                                 dy = 1;
  76.                                 break;
  77.                         case 80:
  78.                                 dy = -1;
  79.                                 break;
  80.                         case 75:
  81.                                 dx = -1;
  82.                                 break;
  83.                         case 77:
  84.                                 dx = 1;
  85.                                 break;
  86.                         default:
  87.                                 break;
  88.                         }
  89.                 }
  90.         }
  91.         if (dx != 0 || dy != 0)  // 左右移动
  92.         {
  93.                 mp.Move(dx,dy); // 使用成员变量mp
  94.                 update = true;
  95.         }
  96. }

  97. void GameMain::updateWindow()
  98. {
  99.         putimage(0, 0, &imgBg);

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

  108.         EndBatchDraw();
  109. }
复制代码


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

使用道具 举报

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

谢谢大哥
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

是xie xie gpt

点评

我很赞同!: 5.0
我很赞同!: 5
……  发表于 2023-4-29 00:11
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-10 09:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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