最近我在 C++ 中开始了一个关于 OpenGL 的项目,但我遇到了一个障碍。播放器是一个立方体,尺寸为 32x32,平台尺寸为 32x32。当重力到位时,玩家会按照应有的方式下落,撞击平台,并不断上下弹跳。
无论如何,这是我的 C++ 代码:
播放器.h:
typedef void *(*ccallbackv)(void);
typedef void *(*ccallbackc)(const std::string);
const float g_gravity = 0.52f;
class Player :
public CBaseObject
{
// Variables
int m_health, m_stealth, m_maxHealth, m_maxStamina;
float jumpForce;
bool mEnabled;
ccallbackv* c_damageCallback;
ccallbackc* c_killedCallback;
bool m_isOnGround;
// Movement Variables
Vector2f velocity;
BoundingBox2D<float>* m_tilePosition, *m_oldTilePosition;
GLuint m_texture;
Level* level;
public:
Player(void);
virtual ~Player(void);
virtual void SetDamageCallbackFunc(ccallbackv* func) { this->c_damageCallback = func; }
virtual void SetKilledCallbackFunc(ccallbackc* func) { this->c_killedCallback = func; }
virtual void Kill(CBaseObject* killer = NULL);
virtual void Reset();
virtual void Tick();
virtual void Render();
virtual void KeyPress(char);
virtual void Enabled(bool v) { this->mEnabled = v; }
virtual bool isEnabled() { return this->mEnabled; }
virtual void Collision();
virtual bool OnGround(bool r) { if(r != m_isOnGround) { m_isOnGround = r; } return m_isOnGround; }
virtual void SetLevel(Level* level) { this->level = level; }
virtual Level* GetLevel() { return level; }
virtual Vector2f* getPosition(){
return &this->m_tilePosition->getVector();
}
virtual BoundingBox2D<float>* getBoundries() { return this->m_tilePosition; }
virtual void setPosition(const Vector2f position){
return this->m_tilePosition->setVector(position);
}
virtual bool IsAlive(){
return m_health > 0;
}
virtual bool HasStamina(){
return m_stealth > 0;
}
virtual void SetJumpForce(float force){ this->jumpForce = force; }
virtual float getJumpForce() { return this->jumpForce; }
};
播放器.cpp:
int movement_position = 0;
float old_y = 0;
Player::Player(void)
{
this->SetTypeString("PLAYER_NON_NPC");
m_texture = ImportTexture("Player.png");
this->velocity = Vector2f(0,0);
this->m_tilePosition = new BoundingBox2D<float>(64,0,32,32);
this->mEnabled = true;
this->OnGround(false);
old_y = -5;
}
Player::~Player(void)
{
}
void Player::Kill(CBaseObject* killer){
if( this->c_killedCallback != NULL )
(*this->c_killedCallback)( std::string( "Player was killed by entity " + ( !killer->GetTypeString().empty() ) ? killer->GetTypeString()
: "unknown."));
this->m_health = 0;
}
void Player::Reset(){
this->m_health = 100;
this->m_stealth = 100;
}
void Player::Tick()
{
if(!this->mEnabled) return;
float ticks = std::toFloat(Time::getSystemTicksSeconds());
m_oldTilePosition = this->m_tilePosition;
if( GLOBALS::pressedKey == 'd' ){
velocity.setX(clamp<float>(velocity.getX() + (1.0f / 10000) * ticks, -0.05f, 0.05f));
}
else if( GLOBALS::pressedKey == 'a' ){
velocity.setX(clamp<float>(velocity.getX() - (1.0f / 10000) * ticks, -0.05f, 0.05f));
}
else {
velocity.setX(0);
}
this->Collision();
if( !m_isOnGround OR ( old_y != this->getBoundries()->getY() ) ){
velocity.addY(clamp<float>(0.0001f * ticks, -0.005f, 0.005f));
}
if(m_oldTilePosition != this->m_tilePosition)
glutPostRedisplay();
if( ( old_y == this->getBoundries()->getY() ) ) {
this->m_tilePosition->setY(old_y);
velocity.setY(0);
}
this->m_tilePosition->addVector(this->velocity);
}
void Player::KeyPress(char i){
}
void Player::Collision(){
if( this->level == NULL ) return;
float old_yc = 0;
std::vector<Tile*> mapData = this->level->GetMap();
OnGround(false);
for(unsigned int i = 0; i < mapData.size(); ++i){
BoundingBox2D<float>* source = this->getBoundries();
BoundingBox2D<float>* mapTile = mapData.at(i)->getBoundries();
Vector2f mapTileVector = mapTile->getIntersectionDepth(source);
Vector2f abs = mapTileVector.Absolute();
if( mapTileVector != Vector2f(0,0) && mapTile->IntersectsWith(source)){
if( abs.getX() > abs.getY() ){
if( old_y <= mapTile->top() )
OnGround(true);
if(m_isOnGround){
this->getBoundries()->setVector(Vector2f(this->m_tilePosition->getX(), this->m_tilePosition->getY() + mapTileVector.getY()));
old_yc = this->getBoundries()->getVector().getY();
}
}
}
}
old_y = old_yc;
}
void Player::Render()
{
if( this->m_texture == 0x0 ) return;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, this->m_texture);
glBegin(GL_QUADS);
::glTexCoord2f(0.0f, 0.0f); ::glVertex2f(this->m_tilePosition->getX(),this->m_tilePosition->getY());
::glTexCoord2f(0.0f, 1.0f); ::glVertex2f(this->m_tilePosition->getX(),this->m_tilePosition->getY() + this->m_tilePosition->getH());
::glTexCoord2f(1.0f, 1.0f); ::glVertex2f(this->m_tilePosition->getX() + this->m_tilePosition->getW(),this->m_tilePosition->getY() + this->m_tilePosition->getH());
::glTexCoord2f(1.0f, 0.0f); ::glVertex2f(this->m_tilePosition->getX() + this->m_tilePosition->getW(),this->m_tilePosition->getY());
glEnd();
glDisable(GL_TEXTURE_2D);
}