I've got an issue while rendering 2d images with my own simple 2D camera object. First my setup:
- a star initial position 0,0
- a planet circles the star initial position 300, 300, moves at a radius of 300 and an angle of 10.5
- a playership inital position 512, 384 [half screen size]
Every object the camera is attached to should be rendered centered on the screen.
When I attach my camera to my player ship everything is rendered as expected. Even when I move my ship everything looks fine.
It's getting weird when I attach my camera to my moveing planet. Then it looks like that it's no longer orbiting the star. It looks like he's orbiting my playership.
I'm just a hobby gamedev so any advice would be good. Following is my code of interesst (I think):
rendering of active objects orders are Star, Planet then PlayerShip
void GameObjects::Galaxy::OnDraw(irr::IrrlichtDevice *irrlichtDevice)
{
INT64 sectorX = std::get<0>(m_activeSector);
INT64 sectorY = std::get<1>(m_activeSector);
for (std::list<GameObjects::PTR_BODY>::iterator itObject = this->m_renderableObjects[sectorX][sectorY].begin(); itObject != this->m_renderableObjects[sectorX][sectorY].end(); itObject++)
{
if ((*itObject)->IsInPlayerView(this->m_camera->GetPosition(), this->m_camera->GetRenderRadius()))
{
// draw all objects, except the one the camera is attached to. thats drawn by the camera
if ((*itObject).get() != this->m_camera->GetAttachedObject().get())
{
irr::core::vector2df posToRender = (*itObject)->Position() - this->m_camera->GetPosition();
(*itObject)->OnDraw(irrlichtDevice, posToRender);
}
}
}
}
Camera class
Camera2D::Camera2D() : m_screenWidth(0), m_screenHeight(0)
{
}
Camera2D::Camera2D(INT32 screenWidth, INT32 screenHeight) : m_screenWidth(screenWidth), m_screenHeight(screenHeight)
{
m_screenCenterX = screenWidth / 2;
m_screenCenterY = screenHeight / 2;
}
Camera2D::~Camera2D()
{
}
void Camera2D::OnUpdate(DOUBLE timeElapsed)
{
if (this->m_objectToFollow.get() != nullptr)
{
this->SetPosition(this->m_objectToFollow->Position());
}
//else
//{
// this->SetPosition(irr::core::vector2df(0, 0));
//}
}
void Camera2D::OnDraw(irr::IrrlichtDevice *irrlichtDevice)
{
irr::core::vector2df screenCenter(this->m_screenCenterX, this->m_screenCenterY);
this->m_objectToFollow->OnDraw(irrlichtDevice, screenCenter);
}
void Camera2D::AttachToObject(GameObjects::PTR_BODY objectToFollow)
{
this->m_objectToFollow = objectToFollow;
}
star rendering
void GameObjects::Star::OnDraw(irr::IrrlichtDevice *irrlichtDevice, irr::core::vector2df &relativPos)
{
INT32 halfSpriteWidth = this->m_sprite->getSize().Width / 2;
INT32 halSpriteHeight = this->m_sprite->getSize().Height / 2;
int screenX = relativPos.X -halfSpriteWidth;
int screenY = relativPos.Y -halSpriteHeight;
irrlichtDevice->getVideoDriver()->draw2DImage(this->m_sprite, irr::core::vector2d<INT32>(screenX, screenY));
}
star update
void GameObjects::Star::OnUpdate(DOUBLE timeElapsed)
{
// update planets
for (std::list<boost::shared_ptr<Planet>>::iterator itPlanet = this->m_planets.begin(); itPlanet != this->m_planets.end(); itPlanet++)
{
(*itPlanet)->OnUpdate(timeElapsed);
}
// update asteroids
for (std::list<boost::shared_ptr<Asteroid>>::iterator itAsteroid = this->m_asteroids.begin(); itAsteroid != this->m_asteroids.end(); itAsteroid++)
{
(*itAsteroid)->OnUpdate(timeElapsed);
}
}
Planet rendering
void GameObjects::Planet::OnDraw(irr::IrrlichtDevice *irrlichtDevice, irr::core::vector2df &relativPos)
{
INT32 halfSpriteWidth = this->m_sprite->getSize().Width / 2;
INT32 halSpriteHeight = this->m_sprite->getSize().Height / 2;
int screenX = relativPos.X - halfSpriteWidth;
int screenY = relativPos.Y - halSpriteHeight;
irrlichtDevice->getVideoDriver()->draw2DImage(this->m_sprite, irr::core::vector2d<INT32>(screenX, screenY));
}
planet update
void GameObjects::Planet::OnUpdate(DOUBLE timeElapsed)
{
if (this->GetParent()->GetType() == GameObjects::GameObjectTypeStar)
{
PTR_STAR pStar = boost::dynamic_pointer_cast<Star>(this->GetParent());
FLOAT angle = (this->GetOrbitingAngle() * timeElapsed) * (M_PI / 180);
FLOAT rotatedX = cos(angle) * (this->Position().X - pStar->Position().X) - sin(angle) * (this->Position().Y - pStar->Position().Y) + pStar->Position().X;
FLOAT rotatedY = sin(angle) * (this->Position().X - pStar->Position().X) + cos(angle) * (this->Position().Y - pStar->Position().Y) + pStar->Position().Y;
this->SetPosition(irr::core::vector2df(rotatedX, rotatedY));
}
}
Ship rendering
void GameObjects::Ship::OnDraw(irr::IrrlichtDevice *irrlichtDevice, irr::core::vector2df &relativPos)
{
INT32 halfSpriteWidth = this->m_sprite->getSize().Width / 2;
INT32 halSpriteHeight = this->m_sprite->getSize().Height / 2;
int screenX = relativPos.X - halfSpriteWidth;
int screenY = relativPos.Y - halSpriteHeight;
irrlichtDevice->getVideoDriver()->draw2DImage(this->GetSprite(), irr::core::vector2d<INT32>(screenX, screenY));
}
ship update
void GameObjects::Ship::OnUpdate(DOUBLE timeElapsed)
{
FLOAT velocityX, velocityY;
velocityX = ::cos( ((ANGLE_ADJUSTMENT + this->GetAngle()) / 180) * M_PI) * (this->GetActualSpeed() * timeElapsed);
velocityY = ::sin( ((ANGLE_ADJUSTMENT + this->GetAngle()) / 180) * M_PI) * (this->GetActualSpeed() * timeElapsed);
this->SetVelocity(irr::core::vector2df(velocityX, velocityY));
FLOAT newPosX = this->Position().X + this->Velocity().X;
FLOAT newPosY = this->Position().Y + this->Velocity().Y;
this->SetPosition(irr::core::vector2df(newPosX, newPosY));
irr::video::ITexture * rotatedImage = Helper::IrrlichtHelper::GetInstance()->RotateImage(this->m_sprite, this->m_angle);
this->UpdateSprite(rotatedImage);
}
Can someone give me a hint what I'am doing wrong or what do I have to change? I though my camera would work always when I just get a relative pos like I'm doing in my Galaxy::OnDraw(...) method.
Files are to big, to upload them here. :/ Links to *.gif
CameraAttachedToMovingShip
https://i.imgur.com/H6pc5BQ.gif
CameraAttachedToMovingPlanet