试图吸引我的球员并移动他
Trying to draw my player and move him
我正在做一个小项目,我试图让一个玩家进入我的 2D 视图(实际上是一个圆圈)并让他从左到右、上下完美地移动,我也希望能够按下2 个键让他侧身移动或类似的东西。
我还希望能够在项目的后期状态中与玩家一起朝某个方向射击(这对现在来说可能很重要)
我做这个项目是因为我想了解 C++ OOP 的工作原理。
我心中的结构很简单:
Main > (Creates) > GameWindow
Main > (creates) > EntityManager > (creates) > Player
Player > (creates via) > EnitityManager > Gun
Gun > (Creates via) > EntityManager > Bullet
玩家可以:
步行 up/down/left/right
射击.
所以要获取代码,这就是我 FirstGame.cpp
中的内容
#include "stdafx.h"
#include "GameWindow.h"
#include "EntityManager.h"
int main()
{
// Create an entity manager
EntityManager::Instance();
// Display the window
GameWindow::Instance().Run();
}
在我的 GameWindow.h 我有 :
#pragma once
#include <SFML/Graphics.hpp>
using namespace sf;
class GameWindow
{
public:
static GameWindow& Instance()
{
static GameWindow instance;
return instance;
}
RenderWindow& GetRenderWindow();
void Run();
private:
static const int DEF_WIDTH = 1366;
static const int DEF_HEIGHT = 720;
GameWindow();
GameWindow(const GameWindow&);
GameWindow& operator=(const GameWindow&);
~GameWindow();
string windowTitle;
int windowWidth;
int windowHeight;
void Initialize();
void DisplayWindow();
void CheckWindowEvent();
};
在我的 GameWindow.cpp
#include "StdAfx.h"
#include "GameWindow.h"
#include "Player.h"
#include "SFML\Graphics.hpp"
RenderWindow renderWindow;
Event eventSF;
GameWindow::GameWindow()
{
Initialize();
}
GameWindow::~GameWindow()
{
}
void GameWindow::Initialize()
{
// Set width & height to default settings
windowWidth = DEF_WIDTH;
windowHeight = DEF_HEIGHT;
// Create the render window
renderWindow.create(VideoMode(windowWidth, windowHeight), windowTitle, Style::Titlebar | Style::Close | Style::Resize);
Cmd::WriteLine("GameWindow Initialized!");
}
RenderWindow& GameWindow::GetRenderWindow()
{
return renderWindow;
}
void GameWindow::Run()
{
// Loop until window has closed
while (renderWindow.isOpen())
{
// Check current window events
CheckWindowEvent();
// Display window
DisplayWindow();
}
}
void GameWindow::DisplayWindow()
{
// Display the render window
renderWindow.clear();
renderWindow.display();
}
void GameWindow::CheckWindowEvent()
{
Event _event;
while (renderWindow.pollEvent(_event))
{
// Request for closing the window
if (_event.type == Event::Closed)
renderWindow.close();
}
}
在我的 EntityManager.h 中我得到了:
#pragma once
#include "Entity.h"
#include "Player.h"
class EntityManager
{
public:
static EntityManager& Instance()
{
static EntityManager instance = EntityManager();
return instance;
}
private:
EntityManager();
~EntityManager();
void Initialize();
};
和我的EntityManager.cpp
#include "StdAfx.h"
#include "EntityManager.h"
#include "GameWindow.h"
#include "Player.h"
EntityManager::EntityManager()
{
Initialize();
}
EntityManager::~EntityManager()
{
}
void EntityManager::Initialize()
{
Player::Create();
}
现在 Player.h
#pragma once
#include <SFML/Graphics.hpp>
#include "Entity.h"
using namespace sf;
class Player: Entity
{
public:
Player();
~Player();
void GotDamage(int damage);
static void Create();
void Draw();
void Shoot();
void Move(float x, float y);
void Controls(Event _eventSF);
private:
string name;
int health;
Event eventSF;
CircleShape playerVisual;
protected:
void Initialize() override;
};
最后 Player.cpp
#include "StdAfx.h"
#include "Player.h"
#include "GameWindow.h"
#include <SFML/Graphics.hpp>
Player::Player()
{
}
Player::~Player()
{
}
void Player::Create()
{
Player player;
player.Initialize();
player.Draw();
player.Controls(player.eventSF);
}
void Player::Initialize()
{
CircleShape playerVisual(50);
playerVisual.setPosition(800, 450);
playerVisual.setFillColor(sf::Color(100, 250, 50));
Entity::Initialize();
}
void Player::Controls(sf::Event _eventSF)
{
while(GameWindow::Instance().GetRenderWindow().isOpen())
{
while(GameWindow::Instance().GetRenderWindow().pollEvent(_eventSF))
{
switch(_eventSF.type)
{
case sf::Event::KeyPressed:
if (_eventSF.key.code == sf::Keyboard::Up)
{
Move(0,-1);
}
if (_eventSF.key.code == sf::Keyboard::Down)
{
Move(0,1);
}
if (_eventSF.key.code == sf::Keyboard::Left)
{
Move(-1,0);
}
if (_eventSF.key.code == sf::Keyboard::Right)
{
Move(1,0);
}
if (_eventSF.key.code == sf::Keyboard::BackSpace)
{
GotDamage(20);
}
break;
}
}
}
cout << " Checking Controls " << endl;
}
void Player::Move(float _x, float _y)
{
cout << "Move Player " << endl;
playerVisual.move(_x, _y);
Draw();
}
void Player::GotDamage(int _damage)
{
//for some reason health is -858993460
cout << "Your current health is " << Player::health << " you received " << _damage << " damage now you have " << Player::health - _damage << " health left. " << endl;
health -= _damage;
}
void Player::Draw()
{
cout << "Draw Player" << endl;
CircleShape visual(50);
playerVisual.setPosition(800, 450);
playerVisual.setFillColor(sf::Color(100, 250, 50));
GameWindow::Instance().GetRenderWindow().draw(visual);
}
我知道很多,但我希望有人能帮助我。
重复我的目标:
我试图让我的球员被吸引到屏幕上,让他向侧面移动,如果可能的话对角移动。
提前致谢!
你不应该绘制 playerVisual 而不是本地存在于 Player::Draw() 函数内部的 visual 吗?
您也不应该在 GameWindow::Run() 中调用 Player::Draw(),因为您调用 GameWindow::DisplayWindow() 会更新屏幕。在 Player::Move() 中调用 Player::Draw() 将精灵的绘制限制在它移动时。这样做的结果将是精灵仅存在于它移动的帧中,否则为空 canvas.
添加到 KeyHeart 的答案中。
我对你的代码进行了一些修改并设法让它工作。
记住变量的范围。 Player::Initialize() 中有一个 CircleShape playerVisual(50),它是一个局部变量,但是 Player.h 中已经有一个 CircleShape playerVisual!所以前者是不必要的。同样,在 Player::Create() 中,您创建了一个本地播放器对象。
我没有您的代码的完整副本,所以我假设您打算做的是让 EntityManager 处理所有现有实体,例如播放器。因此,您应该在 EntityManager 的头文件中声明 Player 播放器。因此调用了构造函数,我从 Player::Create() 中获取了所有内容并将其放入 Player::Player() 中。并且此播放器将在 EntityManager 的生命周期内存在。
您应该更新缓冲区的顺序是:
renderWindow.clear()
renderWindow.draw()
renderWindow.display()
正如您现在所拥有的那样,您 draw() 然后 clear() 有效地不显示任何内容。
有很多方法,但最简单的方法是在 GameWindow::DisplayWindow() 中添加对 Player::Draw() 的调用。尽管 GameWindow 需要玩家对象来调用 Draw()。
关于移动播放器。 Player::Controls 包含某种意义上的无限循环。只要 window 打开,while (GameWindow::Instance().GetRenderWindow().isOpen()) 行将继续循环,因此可以阻止任何其他更新,例如绘图。
我正在做一个小项目,我试图让一个玩家进入我的 2D 视图(实际上是一个圆圈)并让他从左到右、上下完美地移动,我也希望能够按下2 个键让他侧身移动或类似的东西。
我还希望能够在项目的后期状态中与玩家一起朝某个方向射击(这对现在来说可能很重要)
我做这个项目是因为我想了解 C++ OOP 的工作原理。 我心中的结构很简单:
Main > (Creates) > GameWindow
Main > (creates) > EntityManager > (creates) > Player
Player > (creates via) > EnitityManager > Gun
Gun > (Creates via) > EntityManager > Bullet
玩家可以: 步行 up/down/left/right 射击.
所以要获取代码,这就是我 FirstGame.cpp
中的内容#include "stdafx.h"
#include "GameWindow.h"
#include "EntityManager.h"
int main()
{
// Create an entity manager
EntityManager::Instance();
// Display the window
GameWindow::Instance().Run();
}
在我的 GameWindow.h 我有 :
#pragma once
#include <SFML/Graphics.hpp>
using namespace sf;
class GameWindow
{
public:
static GameWindow& Instance()
{
static GameWindow instance;
return instance;
}
RenderWindow& GetRenderWindow();
void Run();
private:
static const int DEF_WIDTH = 1366;
static const int DEF_HEIGHT = 720;
GameWindow();
GameWindow(const GameWindow&);
GameWindow& operator=(const GameWindow&);
~GameWindow();
string windowTitle;
int windowWidth;
int windowHeight;
void Initialize();
void DisplayWindow();
void CheckWindowEvent();
};
在我的 GameWindow.cpp
#include "StdAfx.h"
#include "GameWindow.h"
#include "Player.h"
#include "SFML\Graphics.hpp"
RenderWindow renderWindow;
Event eventSF;
GameWindow::GameWindow()
{
Initialize();
}
GameWindow::~GameWindow()
{
}
void GameWindow::Initialize()
{
// Set width & height to default settings
windowWidth = DEF_WIDTH;
windowHeight = DEF_HEIGHT;
// Create the render window
renderWindow.create(VideoMode(windowWidth, windowHeight), windowTitle, Style::Titlebar | Style::Close | Style::Resize);
Cmd::WriteLine("GameWindow Initialized!");
}
RenderWindow& GameWindow::GetRenderWindow()
{
return renderWindow;
}
void GameWindow::Run()
{
// Loop until window has closed
while (renderWindow.isOpen())
{
// Check current window events
CheckWindowEvent();
// Display window
DisplayWindow();
}
}
void GameWindow::DisplayWindow()
{
// Display the render window
renderWindow.clear();
renderWindow.display();
}
void GameWindow::CheckWindowEvent()
{
Event _event;
while (renderWindow.pollEvent(_event))
{
// Request for closing the window
if (_event.type == Event::Closed)
renderWindow.close();
}
}
在我的 EntityManager.h 中我得到了:
#pragma once
#include "Entity.h"
#include "Player.h"
class EntityManager
{
public:
static EntityManager& Instance()
{
static EntityManager instance = EntityManager();
return instance;
}
private:
EntityManager();
~EntityManager();
void Initialize();
};
和我的EntityManager.cpp
#include "StdAfx.h"
#include "EntityManager.h"
#include "GameWindow.h"
#include "Player.h"
EntityManager::EntityManager()
{
Initialize();
}
EntityManager::~EntityManager()
{
}
void EntityManager::Initialize()
{
Player::Create();
}
现在 Player.h
#pragma once
#include <SFML/Graphics.hpp>
#include "Entity.h"
using namespace sf;
class Player: Entity
{
public:
Player();
~Player();
void GotDamage(int damage);
static void Create();
void Draw();
void Shoot();
void Move(float x, float y);
void Controls(Event _eventSF);
private:
string name;
int health;
Event eventSF;
CircleShape playerVisual;
protected:
void Initialize() override;
};
最后 Player.cpp
#include "StdAfx.h"
#include "Player.h"
#include "GameWindow.h"
#include <SFML/Graphics.hpp>
Player::Player()
{
}
Player::~Player()
{
}
void Player::Create()
{
Player player;
player.Initialize();
player.Draw();
player.Controls(player.eventSF);
}
void Player::Initialize()
{
CircleShape playerVisual(50);
playerVisual.setPosition(800, 450);
playerVisual.setFillColor(sf::Color(100, 250, 50));
Entity::Initialize();
}
void Player::Controls(sf::Event _eventSF)
{
while(GameWindow::Instance().GetRenderWindow().isOpen())
{
while(GameWindow::Instance().GetRenderWindow().pollEvent(_eventSF))
{
switch(_eventSF.type)
{
case sf::Event::KeyPressed:
if (_eventSF.key.code == sf::Keyboard::Up)
{
Move(0,-1);
}
if (_eventSF.key.code == sf::Keyboard::Down)
{
Move(0,1);
}
if (_eventSF.key.code == sf::Keyboard::Left)
{
Move(-1,0);
}
if (_eventSF.key.code == sf::Keyboard::Right)
{
Move(1,0);
}
if (_eventSF.key.code == sf::Keyboard::BackSpace)
{
GotDamage(20);
}
break;
}
}
}
cout << " Checking Controls " << endl;
}
void Player::Move(float _x, float _y)
{
cout << "Move Player " << endl;
playerVisual.move(_x, _y);
Draw();
}
void Player::GotDamage(int _damage)
{
//for some reason health is -858993460
cout << "Your current health is " << Player::health << " you received " << _damage << " damage now you have " << Player::health - _damage << " health left. " << endl;
health -= _damage;
}
void Player::Draw()
{
cout << "Draw Player" << endl;
CircleShape visual(50);
playerVisual.setPosition(800, 450);
playerVisual.setFillColor(sf::Color(100, 250, 50));
GameWindow::Instance().GetRenderWindow().draw(visual);
}
我知道很多,但我希望有人能帮助我。
重复我的目标: 我试图让我的球员被吸引到屏幕上,让他向侧面移动,如果可能的话对角移动。
提前致谢!
你不应该绘制 playerVisual 而不是本地存在于 Player::Draw() 函数内部的 visual 吗?
您也不应该在 GameWindow::Run() 中调用 Player::Draw(),因为您调用 GameWindow::DisplayWindow() 会更新屏幕。在 Player::Move() 中调用 Player::Draw() 将精灵的绘制限制在它移动时。这样做的结果将是精灵仅存在于它移动的帧中,否则为空 canvas.
添加到 KeyHeart 的答案中。
我对你的代码进行了一些修改并设法让它工作。
记住变量的范围。 Player::Initialize() 中有一个 CircleShape playerVisual(50),它是一个局部变量,但是 Player.h 中已经有一个 CircleShape playerVisual!所以前者是不必要的。同样,在 Player::Create() 中,您创建了一个本地播放器对象。
我没有您的代码的完整副本,所以我假设您打算做的是让 EntityManager 处理所有现有实体,例如播放器。因此,您应该在 EntityManager 的头文件中声明 Player 播放器。因此调用了构造函数,我从 Player::Create() 中获取了所有内容并将其放入 Player::Player() 中。并且此播放器将在 EntityManager 的生命周期内存在。
您应该更新缓冲区的顺序是:
renderWindow.clear()
renderWindow.draw()
renderWindow.display()
正如您现在所拥有的那样,您 draw() 然后 clear() 有效地不显示任何内容。 有很多方法,但最简单的方法是在 GameWindow::DisplayWindow() 中添加对 Player::Draw() 的调用。尽管 GameWindow 需要玩家对象来调用 Draw()。
关于移动播放器。 Player::Controls 包含某种意义上的无限循环。只要 window 打开,while (GameWindow::Instance().GetRenderWindow().isOpen()) 行将继续循环,因此可以阻止任何其他更新,例如绘图。