试图吸引我的球员并移动他

Trying to draw my player and move him

本文关键字:移动 我的      更新时间:2023-10-16

我正在做一个小项目,我试图让一个玩家在我的 2D 视图(实际上是一个圆圈)中,让他从左到右、上下完美地移动,我也希望能够按下 2 个键,以便他侧身移动或类似的东西。

此外,我希望能够在项目的后期状态下与玩家一起朝某个方向拍摄(到目前为止可能很重要)

我正在做这个项目,因为我想了解 OOP 的工作原理C++。我脑海中的结构很简单:

Main > (Creates) > GameWindow
Main > (creates) > EntityManager > (creates) > Player 
Player > (creates via) > EnitityManager > Gun
Gun > (Creates via) > EntityManager > Bullet

玩家可以 :向上/向下/向左/向右行走射。

所以为了进入代码,这就是我在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();
}

在我的游戏窗口中,我有:

#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();
};

在我的游戏窗口中.cpp

#include "StdAfx.h"
#include "GameWindow.h"
#include "Player.h"
#include "SFMLGraphics.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(); 
    }
}

在我的实体管理器.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();
};

和我的实体经理.cpp

#include "StdAfx.h"
#include "EntityManager.h"
#include "GameWindow.h"
#include "Player.h"
EntityManager::EntityManager()
{
    Initialize();
}
EntityManager::~EntityManager()
{
}
void EntityManager::Initialize()
{
    Player::Create();
}

现在是玩家。

#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;
};

最后是玩家.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);
}

我知道这很多,但我希望有人可以帮助我。

重复我的目标:我试图让我的球员在屏幕上画画,让他横向移动,如果可能的话,对角线。

提前感谢!

补充一下KeyHeart的答案。

我破解了你的代码并设法让它工作。

请记住变量的范围。在 Player::Initialize() 中有 CircleShape playerVisual(50),它是一个局部变量,但你在 Player.h 中已经有一个 CircleShape playerVisual!所以前者是不必要的。同样,在 Player::Create() 中,您可以创建一个本地播放器对象。

我没有您的代码的完整副本,因此我假设您计划做的是让 EntityManager 处理所有现有实体,例如播放器。因此,您应该在实体管理器的头文件中声明玩家播放器。因此调用构造函数,我从 Player::Create() 中获取了所有内容并将其放入 Player::P layer() 中。这个播放器将在实体管理器的生命周期内存在。

更新缓冲区的顺序为:

renderWindow.clear()
renderWindow.draw()
renderWindow.display()

就像你现在一样,你绘制()然后clear()有效地不显示任何东西。有很多方法,但最简单的方法是在 GameWindow::D isplayWindow() 中添加对 Player::D raw() 的调用。虽然GameWindow需要一个玩家对象来调用Draw()。

关于移动播放器。玩家::控件包含某种意义上可能是无限循环的内容。行 while (GameWindow::Instance()。只要窗口打开,GetRenderWindow().isOpen()) 就会继续循环,因此可以阻止其他任何内容更新,例如绘图。

你不应该绘制 playerVisual 而不是本地存在于 Player::D raw() 函数中的视觉吗?

也不应该在 GameWindow::Run() 中调用 Player::D

raw(),因为您调用 GameWindow::D isplayWindow() 会更新屏幕。在玩家::移动()中调用玩家::D raw() 将精灵的绘制限制为仅在它移动时。这样做的结果是,精灵只存在于它移动的框架中,否则就是一个空的画布。