После просмотра предоставленного вами кода я вижу несколько проблем или проблем с дизайном кода: я разобью его и объясню некоторые вещи, которые, как я вижу, могут улучшить качество вашего кода.Я начну с вашего main.cpp, затем перейду к вашему классу Engine.
У вас изначально есть это:
#include "engine.h"
#include <iomanip>
Engine eng;
int main() {
while (eng.isRunning) {
eng.getInput();
std::cout << std::setw(5);
std::cout << "\r X = " << eng.playerX;
std::cout << "| Y = " << eng.playerY;
std::cout << "| KEY = " << eng.keyPressed;
Sleep(100);
}
return 0;
}
Первая основная проблема, которую я вижу, эточто вы объявили Engine eng
на глобальном уровне.Мы можем исправить это с помощью
#include "engine.h"
#include <iostream>
#include <iomanip>
int main() {
Engine eng; // declare it here as the first object in main; now it has local
// scope within main's function and is now in Automatic Storage
// instead of Global Storage.
while( ... ) {
// ....
}
return 0;
};
Следующая проблема начинается с условного выражения while в основной функции.В настоящее время у вас есть:
while( engine.isRunning ) { //... }
Это нормально, но это скорее проблема с вашим Engine class's
дизайном.Здесь вы предоставляете public member
, доступ к которому может получить каждый.Итак, давайте посмотрим на объявление / определение вашего класса;в настоящее время у вас есть:
#ifndef ENGINE_H
#define ENGINE_H
#include <iostream>
#include <Windows.h>
#include <string>
class Engine {
public:
// Game
bool isRunning = true;
bool gettingInput = true;
// Player
int playerX = 1;
int playerY = 1;
char playerModel = 'P';
// Test / Debug
std::string keyPressed;
// Functions
char getInput() { // ... }
};
#endif
Здесь вы должны защитить свои элементы данных и иметь функции модификаторов доступа к ним:
#ifndef ENGINE_H
#define ENGINE_H
#include <iostream>
#include <Windows.h>
#include <string>
class Engine {
private:
bool isRunning;
bool gettingInput;
// Player
int playerX;
int playerY;
char playerModel;
// Test / Debug
std::string keyPressed;
public:
Engine() :
isRunning( false ),
isGettingInput( false ),
playerX( 1 ),
playerY( 1 ),
playerModel( 'P' )
{}
void run() { isRunning = true; // set or call other things here... }
// Since we protected our members variables by making them private,
// we now need some access functions to retrieve and modify them.
bool isActive() const { return isRunning; } // make this const so it doesn't change anything
void toggleIsActive() { isRunning = !isRunning; }
bool retrievingInput() const { return isGettingInput; }
void toggleRetrievingInput() { isGettingInput = !isGettingInput; }
int getPlayerX() const { return playerX; }
void setPlayerX( int newX ) { playerX = newX; }
int getPlayerY() const { return playerY; }
void setPlayerY( int newY ) { playerY = newY; }
// set both in one function call
void setPlayerPosition( int newX, int newY ) {
playerX = newX;
playerY = newY;
}
char getPlayerModel() const { return playerModel; }
// don't know if you want to change this: uncomment if you do
// void setPlayerModel( char c ) { playerModel = c; }
std::string& getPressedKey() const { return keyPressed; }
char getInput() { // ... }
};
Это должно исправить дизайн интерфейсатвой класс.Единственным существенным отличием здесь является то, что я установил переменные-члены Boolean
на false
по умолчанию, потому что обычно, когда вы впервые запускаете Engine
, он в данный момент еще не запущен.Таким образом, чтобы исправить это, мы можем вызвать публичную функцию запуска, которая вызовет это.Вместо этого main будет выглядеть так:
int main () {
Engine eng;
eng.run(); // this now starts the engine sets the flag to true
while (...) { //... }
return 0;
}
Однако я также видел несколько проблем в вашей функции Engine's
getInput()
, поэтому давайте рассмотрим ее.
char getInput() {
// Gets arrow keys states
while (this->gettingInput) {
this->keyPressed = "";
if (GetAsyncKeyState(VK_RIGHT)) {
// Right arrow key
this->playerX++;
this->keyPressed = "Right arrow";
break;
}
else if (GetAsyncKeyState(VK_LEFT)) {
// Left arrow key
this->playerX--;
this->keyPressed = "Left arrow";
break;
}
else if (GetAsyncKeyState(VK_UP)) {
// Up arrow key
this->playerY++;
this->keyPressed = "Up arrow";
break;
}
else if (GetAsyncKeyState(VK_DOWN)) {
// Down arrow key
this->playerY--;
this->keyPressed = "Down arrow";
break;
}
else if (GetAsyncKeyState(VK_END)) {
exit(0);
}
Sleep(255);
}
}
Первая часть - это оператор условия while loop's
и член вашего класса.Первоначально у вас установлено значение по умолчанию true
, но нигде в коде я не видел, чтобы это значение обновлялось.Нам не нужно это менять, но исправить это просто, теперь у нас есть способ изменить этого члена через вызов открытого интерфейса.Так как я сделал ваш isGettingInput
false
по умолчанию;Теперь вы можете установить это в этой функции, прежде чем войти в цикл while.Единственная последняя проблема, которую я вижу, - это когда эта функция вызывается обратно в main's
while;эта функция никогда не возвращает значение, а возвращаемое значение никогда не используется.
Что касается вашей реальной проблемы с ошибкой для cout
пользователя: 1201programalarm уже почти ответил на этот вопрос для вас.Просто подумал, что помогу тебе немного больше с твоим кодом.