Getting sprite to follow mouse, weird glitch when using views - c++

I was wondering if anyone could help me. My sprite was following my mouse fine until i started using views i am just starting using SFML, to make the sprite follow my player i used this.
void player::rotateToMouse(sf::Sprite &sprite, sf::RenderWindow &window)
{
this->mouse = sf::Mouse::getPosition(window);
const float PI = 3.14159265;
float a = playerPosition.x - mouse.x;
float b = playerPosition.y - mouse.y;
mouseAngle = (atan2(b, a)) * 180 / PI;
playerSprite.setRotation(mouseAngle + 180);
}
I am adding this code in my update method, like so,
void player::update(sf::RenderWindow &window){
this->rotateToMouse(playerSprite, window);
this->followPlayer();
I am setting my views like this,
void player::followPlayer(){
view.reset(sf::FloatRect(0, 0, 32 + 10, 32 + 10));
view.zoom(15);
view.setCenter(playerSprite.getPosition());
}
and my movement code is this,
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)){
playerSprite.move(std::cos(3.14159265 * mouseAngle / 180.f) * speed *-1, std::sin(3.14159265 * mouseAngle / 180.f) * speed *-1);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)){ //Speed
playerSprite.move(std::cos(3.14159265 * mouseAngle / 180.f) * speed , std::sin(3.14159265 * mouseAngle / 180.f) * speed );
}
this->playerPosition = playerSprite.getPosition();
I can see the sprite is facing slightly off and after a while he starts to spin round randomly, i am quite a noob at c++ and if anyone could help me it would be appreciated.

You need to use sf::RenderTarget::mapPixelToCoords. Basically you need to change how you compute the mouse position from:
this->mouse = sf::Mouse::getPosition(window);
to
this->mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));

Related

Rotating a vector around a point

I've looked around here for some answers on this, I've found a few good ones, but when I implement them in my code, I get some unexpected results.
Here's my problem:
I'm creating a top down geometry shooter, and when an enemy is hit by a bullet, the enemy should explode into smaller clones, shooting out from the center of the enemy in a circular fashion, in even intervals around the enemy. I assumed I could accomplish this by getting an initial vector, coming straight out of the side of the enemy shape, then rotate that vector the appropriate amount of times. Here's my code:
void Game::spawnSmallEnemies(s_ptr<Entity> e)
{
int vertices = e->cShape->shape.getPointCount();
float angle = 360.f / vertices;
double conv = M_PI / 180.f;
double cs = cos(angle * (M_PI / 180));
double sn = sin(angle * (M_PI / 180));
// Radius of enemy shape
Vec2 velocity { e->cTransform->m_pos.m_x + m_enemyCfg.SR , e->cTransform->m_pos.m_y} ;
velocity = velocity.get_normal();
Vec2 origin {e->cTransform->m_pos};
for (int i = 0; i < vertices; i++)
{
auto small = m_entityMgr.addEntity("small");
small->cTransform = std::make_shared<CTransform>(origin, velocity * 3, 0);
small->cShape = std::make_shared<CShape>(m_enemyCfg.SR / 4, vertices,
e->cShape->shape.getFillColor(), e->cShape->shape.getOutlineColor(),
e->cShape->shape.getOutlineThickness(), small->cTransform->m_pos);
small->cCircleCollider = std::make_shared<CCircleCollider>(m_enemyCfg.SR / 4);
small->cLife = std::make_shared<CLifespan>(m_enemyCfg.L);
velocity.m_x = ((velocity.m_x - origin.m_x) * cs) - ((origin.m_y - velocity.m_y) * sn) + origin.m_x;
velocity.m_y = origin.m_y - ((origin.m_y - velocity.m_y) * cs) + ((velocity.m_x - origin.m_x) * sn);
}
}
I got the rotation code at the bottom from this post, however each of the smaller shapes only shoot toward the bottom right, all clumped together. I would assume my error is logic, however I have been unable to find a solution.

Skewed / Off-axis stereoscopic projection with glm::frustum flickering

I have a 3d, stereoscopic rendering application that currently uses parallel stereoscopy by just moving (shifting) the camera to the side for each Left and Right views. It does work, but recently I felt it could be much improved if I had the off-axis option. I got a semi-working algorithm for glm::frustum() to allow for this but am having some troubles immediately when I switch to it over glm::perspective().
I followed the only GL guide I could find, Simple, Low-Cost Stereographics, that which said to replace my existing glm::perspective() with (2 calls
//OFF-AXIS STEREO
if (myAbj.stereoOffsetAxis) {
glm::vec3 targ0_stored = i->targO;
if (myAbj.stereoLR == 0)
{
float sgn = -1.f * (float)myAbj.stereoSwitchLR;
float eyeSep = myAbj.stereoSep;
float focalLength = 50.f;
float eyeOff = (sgn * (eyeSep / 2.f) * (myAbj.selCamLi->nearClip->val_f / focalLength));
float top = myAbj.selCamLi->nearClip->val_f * tan(myAbj.selCamLi->fov->val_f / 2.f);
float right = myAbj.aspect * top;
myAbj.selCamLi->PM = glm::frustum(-right - eyeOff, right - eyeOff, -top, top, myAbj.selCamLi->nearClip->val_f, myAbj.selCamLi->farClip->val_f);
i->targO += myAbj.selCamLi->rightO * myAbj.stereoSep * (float)myAbj.stereoSwitchLR;
VMup(i);
i->targO = targ0_stored;
}
if (myAbj.stereoLR == 1)
{
float sgn = 1.f * (float)myAbj.stereoSwitchLR;
float eyeSep = myAbj.stereoSep;
float focalLength = 50.f;
float eyeOff = (sgn * (eyeSep / 2.f) * (myAbj.selCamLi->nearClip->val_f / focalLength));
float top = myAbj.selCamLi->nearClip->val_f * tan(myAbj.selCamLi->fov->val_f / 2.f);
float right = myAbj.aspect * top;
myAbj.selCamLi->PM = glm::frustum(-right - eyeOff, right - eyeOff, -top, top, myAbj.selCamLi->nearClip->val_f, myAbj.selCamLi->farClip->val_f);
i->targO += myAbj.selCamLi->rightO * -myAbj.stereoSep * (float)myAbj.stereoSwitchLR;
VMup(i);
i->targO = targ0_stored;
}
}
Using this equation, my View Matrix is rotated 180 degrees on the Z axis. However, the bigger issue is a large amount of black dots and flickering on my objects. When I move the camera to a close enough point the flickering stops. Even when I minimize the scene, the issue is still there.
Why is this flickering happening and what can I do to prevent it? It is ruining my scenes.
My near clip was causing the problem. It couldnt be set to the same low value that glm::perspective() was using - it needed a little bit more.

How to check if two circles drawn on an Adafruit TFT screen are touching eachother?

im making (or rather, trying to make, lol) a snake game on a Adafruit TFT 1.8 screen. Then i ofcourse need the snakehead to know when it hits the "point", and therefore i need to know when the two circles which are of even size are touching eachother. However, my function for this is not working (in other words printing "NOT TOUCHING").
Im trying to follow this formula:
(sqrt(dx2 + dy2))
The radius of both circles are 3, and i get the center for the formula from adding the screen position x and y of the circles together (am i even getting the centers correctly?).
void pointCondition() {
double centerPoint = pointPositionX + pointPositionY;
double centerSnakeHead = positionX + positionY;
int distanceBetweenCenter = (sqrt(centerPoint * 3 + centerSnakeHead * 3));
int weight = 3 / 2;
if (distanceBetweenCenter < weight) {
Serial.println("TOUCHING");
} else {
Serial.println("NOT TOUCHING");
}
}
Can you see what i am doing wrong?
You need something like this:
double dx = pointPositionX - positionX,
dy = pointPositionY - positionY,
d = sqrt(dx * dx + dy * dy);
bool touching = d <= 3;

OpenGL flight simulator styled camera rotations not working

I am trying to create a camera thats works like a flight-simulator (because I'm making a flight simulator) camera - I want to be able to perform pitch, yaw and roll, as well as translations. The translations work perfectly, but the rotations are causing me a very big headache.
The rotations are calculated using quaternions, using GLM, like so:
// Fuck quaternions
glm::fquat pitchQuat(cos(TO_RADIANS(pitch / 2.0f)), m_rightVector * (float)sin(TO_RADIANS(pitch / 2.0f)));
glm::fquat yawQuat(cos(TO_RADIANS(yaw / 2.0f)), m_upVector * (float)sin(TO_RADIANS(yaw / 2.0f)));
glm::fquat rollQuat(cos(TO_RADIANS(roll / 2.0f)), m_direction * (float)sin(TO_RADIANS(roll / 2.0f)));
m_rotation = yawQuat * pitchQuat * rollQuat;
m_direction = m_rotation * m_direction * glm::conjugate(m_rotation);
m_upVector = m_rotation * m_upVector * glm::conjugate(m_rotation);
m_rightVector = glm::cross(m_direction, m_upVector);
If I calculate pitch or roll or yaw alone, everything works fine, however, as soon as I introduce another rotation everything goes wrong. This video should be enough to show you what is going wrong:
https://www.youtube.com/watch?v=jlklem6t68I&feature=youtu.be
The translations work fine, the rotations not such much. When I move the mouse in a circular motion - which is yaw and pitch rotations - the house slowly begins the flip upside-down. You may have noticed in the video that rotating causes the house to stretch, which is also unwanted.
I cannot figure out what is wrong. Can anyone explain how I can create a camera with pitch, yaw and roll working?
If it is of any help the view matrix is calculated using:
m_viewMatrix = glm::lookAt(m_position, m_position + m_direction, m_upVector);
And the projection matrix is calculated using:
float t = tan(fov * 3.14159 / 360.0) * nPlane;
float r = aspectRatio * t;
float l = aspectRatio * -t;
m_projectionMatrix[0][0] = (2 * nPlane) / (r - l);
m_projectionMatrix[0][2] = (r + l) / (r - l);
m_projectionMatrix[1][1] = (2 * nPlane) / (t + t);
m_projectionMatrix[1][2] = (t - t) / (t + t);
m_projectionMatrix[2][2] = (nPlane + fPlane) / (nPlane - fPlane);
m_projectionMatrix[2][3] = (2 * fPlane * nPlane) / (nPlane - fPlane);
m_projectionMatrix[3][2] = -1;
If you would like to see all my code for the camera class you can find it in my Google Drive:
http://goo.gl/FFMPa0
What you're experiencing is normal for a quaternion camera. If you want to avoid the problem, simply use a fixed up-vector when yawing, but beware, that there's going to be an exception when you look straight up. You might want to handle that explicitly. And always reconstruct your view matrix, by crossing view with this static up.
EDIT:
Here's a step-by-step:
First, calculate your rotation around the static up-vector, while your direction is extracted from the view as usual (and right being the cross):
// Quaternions
glm::fquat pitchQuat(cos(TO_RADIANS(pitch / 2.0f)), cross(m_direction,vec3(0,1,0) * (float)sin(TO_RADIANS(pitch / 2.0f)));
glm::fquat yawQuat(cos(TO_RADIANS(yaw / 2.0f)), vec3(0,1,0) * (float)sin(TO_RADIANS(yaw / 2.0f)));
glm::fquat rollQuat(cos(TO_RADIANS(roll / 2.0f)), m_direction * (float)sin(TO_RADIANS(roll / 2.0f)));
m_rotation = yawQuat * pitchQuat * rollQuat;
Then reconstruct your view by using the quaternion, as shown in here (lm::lookAt will do too).
And, of course - repeat step every frame.

How to get a change in mouse position difference using Cocoa?

I'm using opengl and trying to create a first person camera. All examples use GLUT and I need to get the mouse differential in cocoa. But I'm running into issues which appers to be tied with mouseMoved being called as soon as the mouse is moved (which is to be expected). Is there a way to make this mroe accurate? Or a simialer function like GLUTS glutMouseFunc?
Current attempt:
-(void)mouseMoved:(NSEvent *)event{
static bool wrap = false;
if(!wrap){
NSPoint eventLocation = [event locationInWindow];
float centerX = self.frame.size.width/2 + [self window].frame.origin.x;
float centerY = self.frame.size.height/2 + [self window].frame.origin.y;
CGPoint mousePointCenter = CGPointMake(centerX, centerY);
CGWarpMouseCursorPosition(mousePointCenter);
int dx = eventLocation.x - self.frame.size.width/2 ;
int dy = eventLocation.y - self.frame.size.height/2 ;
const float mousespeed = 0.001;
angles.x += dx * mousespeed;
angles.y += dy * mousespeed;
if(angles.x < -M_PI)
angles.x += M_PI * 2;
else if(angles.x > M_PI)
angles.x -= M_PI * 2;
if(angles.y < -M_PI / 2)
angles.y = -M_PI / 2;
if(angles.y > M_PI / 2)
angles.y = M_PI / 2;
lookat.x = sinf(angles.x) * cosf(angles.y);
lookat.y = sinf(angles.y);
lookat.z = cosf(angles.x) * cosf(angles.y);
CGWarpMouseCursorPosition(mousePointCenter);
[self setNeedsDisplay:YES];
}
else{
wrap = true;
}
}
I'm not sure I followed what your code is supposed to be doing, but repeatedly warping the mouse cursor to a center point is rarely the right thing to do.
First, you can use the deltaX and deltaY values of the NSEvent.
Perhaps you want to do CGAssociateMouseAndMouseCursorPosition(false) to disassociate the mouse from the cursor position. When you do that, the on-screen cursor no longer moves with the mouse. You can hide it or reposition it (yes, you'd warp it once in this case). Also, events no longer have changes in their absolute position. But they do still carry delta movement values which reflect the mouse movements.