警告:大帖,小问题
我试图使用SFML 2.3.2制作游戏,事情进展顺利。我有移动平台,一个可移动,跳跃,碰撞的玩家角色(尽管是一个盒子)。而且我也会根据时间的推移移动距离,而不是根据锁定的帧速率,但似乎我搞砸了。
问题:
我添加的实体越多(我的玩家角色碰撞和移动平台的框)玩家移动越慢,他跳越低,尽管使用(deltaTime *移动速度)计算(移动平台似乎是一致的)但在他们的动作中,无论实体的数量如何)
这是我迄今为止所做的最大项目,所以我会尽力提供所有相关信息。
首先,我将展示项目中所有文件的结构,这样,如果我需要的代码,我就可以问我"嘿,那里有什么?"。除此之外,我将复制我认为与此问题相关的代码。哪个是引擎代码(一个基本的代码),Player和VelocityModule
项目文件:
.h =仅限头文件
.cpp =仅限源文件
.h / .cpp =标题和源文件
Dutchtilities:
实体:
模块:
系统:
我认为问题集中在VelocityModule及其更新方式
相关代码:
Engine.h
#ifndef ENGINE_H
#define ENGINE_H
// Forward Declaration
class Level;
#include "Reader.h"
class Engine
{
public:
// Functions - System
bool update();
void initWindow();
// Functions - Time
sf::Time getLastFrameTime();
void resetLastFrameTime();
// Functions - Camera
void updateCamera();
void setCameraTransform( TransformModule* transform );
void setCameraOffset( sf::Vector2f &offset );
void setCameraOffset( float x, float y );
sf::Vector2f getCameraOffset();
// Functions - Window
void setWindowName( const std::string &name );
void setWindowDimensions( sf::Vector2u &widthHeight );
void setWindowDimensions( unsigned width, unsigned height );
sf::Vector2u getWindowDimensions();
// Functions - Levels
void loadLevel( Level* level );
// Variables - Camera
sf::View camera;
// Variables - Time
sf::Clock clock;
sf::Time deltaTime;
// Variables - Window
sf::RenderWindow window;
// Variables - Reader
Reader fileReader;
// Structors
Engine();
protected:
// Variables - Level
Level* m_level;
// Variables - Camera
sheepPtr<TransformModule> m_cameraTarget;
sf::Vector2f m_cameraOffset;
// Variables - Time
float m_frameTime;
// Variables - Window
sf::Event m_eventHandler;
std::string m_windowName;
sf::Vector2u m_windowDimensions;
// Variables - Game Loop
bool m_paused;
};
#endif
引擎包含3个我认为重要的功能:
引擎::更新()
bool Engine::update()
{
this->resetLastFrameTime();
bool isRunning = true;
// if the window is open...
if( this->window.isOpen() )
{
// Shortcuts
Level &level = *(this->m_level);
// LOOK AT WINDOW EVENTS ////////////////////////////////////////////////////////////////////////////////////////////////
// Keyboard Events
while( window.pollEvent( this->m_eventHandler ) )
{
// Stop program when X is pressed
switch( this->m_eventHandler.type )
{
case sf::Event::Closed:
this->window.close();
isRunning = false;
break;
}
// Pause/Resume game when escape is pressed
if( this->m_eventHandler.type == sf::Event::KeyReleased &&
this->m_eventHandler.key.code == sf::Keyboard::Escape)
{
this->m_paused = !m_paused;
std::string line = (m_paused) ? "Game has paused\n" : "Game has unpaused\n";
std::cout << line;
}
}
// The main game loop
if( this->window.hasFocus() &&
m_paused == false )
{
// UPDATE ENTITY HITBOXES ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
level.hitboxUpdateEntities();
// APPLY VELOCITIES TO TRANSFORMS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
level.updateVelocities();
// DETECT COLLISIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
level.resetCollisionLists();
level.createCollisionLists();
// APPLY EFFECTS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
level.updateEntities();
// ADJUST FOR COLLISION ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
level.adjustHitboxes();
// DRAW STUFF /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
level.updateDraws();
this->updateCamera();
this->window.display();
this->window.clear();
}
}
// Otherwise the window has closed
else
isRunning = false;
return isRunning;
}
引擎:: getLastFrameTime()
sf::Time Engine::getLastFrameTime()
{
return this->deltaTime;
}
引擎:: resetLastFrameTime()
void Engine::resetLastFrameTime()
{
this->deltaTime = clock.getElapsedTime();
this->clock.restart();
}
Player.h
#ifndef PLAYER_H
#define PLAYER_H
class Player : public Entity
{
public:
void virtual update() final;
void virtual hitboxUpdate() final;
short health;
float movementSpeed;
float jumpingPower;
Player();
~Player();
private:
// Modules
sheepPtr<TransformModule> transform;
sheepPtr<DrawModule> draw;
sheepPtr<HitboxModule> collisionHitbox;
sheepPtr<HitboxModule> jumpHitbox;
sheepPtr<VelocityModule> velocity;
bool m_grounded;
};
#endif // PLAYER_H
我认为重要的功能:
播放器:: hitboxUpdate()
void Player::hitboxUpdate()
{
// Calculate the distance the player will move this update
float distance = (this->movementSpeed * this->m_pEngine->getLastFrameTime().asSeconds() );
// Jumping (Up)
if( sf::Keyboard::isKeyPressed(sf::Keyboard::Space) &&
this->m_grounded == true)
{
this->velocity->addVelocity( sf::Vector2f( 0, -(this->jumpingPower) ));
}
// Left
if( sf::Keyboard::isKeyPressed(sf::Keyboard::A) )
this->velocity->addVelocity( sf::Vector2f( -distance, 0 ));
// Right
else if( sf::Keyboard::isKeyPressed(sf::Keyboard::D) )
this->velocity->addVelocity( sf::Vector2f( distance, 0 ));
}
VelocityModule.h
#ifndef VELOCITYMODULE_H
#define VELOCITYMODULE_H
class VelocityModule : public Module
{
public:
// Functions - System
void update();
// Functions - Velocity
void addVelocity( sf::Vector2f &velocity);
sf::Vector2f getVelocity();
void setVelocity( sf::Vector2f velocity );
void applyVelocity();
void setMaxVelocity( float maxVelocity );
float getMaxVelocity();
void setMinVelocity( float minVelovity );
float getMinVelocity();
// Functions - Drag
void setDrag( float dragForce );
float getDrag();
void setApplyDrag( bool trueOrFalse );
bool getApplyDrag();
// Functions - Gravity
void setGravity( float gravity );
float getGravity();
void setApplyGravity( bool trueOrFalse );
bool getApplyGravity();
// Functions - Transform
void setTargetTransform( TransformModule* transform );
TransformModule* getTargetTransform();
// Structors
VelocityModule();
~VelocityModule();
private:
// Variables - Velocity
sf::Vector2f m_velocity;
float m_minVelocity;
float m_maxVelocity;
// Variables - Drag
float m_dragForce;
bool m_applyingDrag;
static const float MAX_DRAG;
static const float MIN_DRAG;
// Variables - Gravity
float m_gravityForce;
bool m_applyingGravity;
// Variables - Transform
sheepPtr<TransformModule> m_targetTransform;
};
#endif // VELOCITYMODULE_H
VelocityModule函数我相信是相关的:
applyVelocity()
void VelocityModule :: update() {
// Shortcut frametime
float seconds = this->m_pParentEntity->getLinkedEngine()->getLastFrameTime().asSeconds();
// Apply Gravity, if it's enabled
this->m_velocity.y += ( this->m_applyingGravity ) ? (this->m_gravityForce * seconds) : 0 ;
// Apply drag, if it's enabled
this->m_velocity *= ( this->m_applyingDrag ) ? pow( 1 - (m_dragForce/100), seconds ) : 1 ;
// Shortcutting via calculations
sf::Vector2f absoluteVelocity = sf::Vector2f(abs(this->m_velocity.x), abs(this->m_velocity.y));
float maxFrameVel = this->m_maxVelocity * seconds;
float minFrameVel = this->m_minVelocity * seconds;
// Change velocities according to maximum and minimum barriers
this->m_velocity.x = ( absoluteVelocity.x < minFrameVel ) ? 0 :
( absoluteVelocity.x > maxFrameVel && m_velocity.x < 0 ) ? -maxFrameVel :
( absoluteVelocity.x > maxFrameVel && m_velocity.x > 0 ) ? maxFrameVel :
m_velocity.x;
this->m_velocity.y = ( absoluteVelocity.y < minFrameVel ) ? 0 :
( absoluteVelocity.y > maxFrameVel && m_velocity.y < 0 ) ? -maxFrameVel :
( absoluteVelocity.y > maxFrameVel && m_velocity.y > 0 ) ? maxFrameVel :
m_velocity.y;
this->applyVelocity();
}
VelocityModule :: addVelocity()
void VelocityModule::addVelocity( sf::Vector2f &velocity)
{
this->m_velocity += velocity;
}
VelocityModule :: applyVelocity()
void VelocityModule::applyVelocity()
{
if( m_targetTransform.ptr != nullptr )
{
// Shortcutting
this->m_targetTransform->move( this->m_velocity );
}
}