So I've started using DirectX C++ and have a base game with is a bunch of asteroids which you can shoot using the mouse. It also has a drawn crosshair sprite which follows the mouses location.
I have decided that I would like to change input to support Xbox 360 controllers. I have managed to program the shoot button to the A button on the gamepad however I am having some issues changing to movement of the crosshair from mouse to the analog sticks on the controller.
The following is the code which is used for determining the mouses location and getting its position for use:
virtual void Update()
{
POINT mousePosition;
D3DXVECTOR3 position, currentPosition;
DirectInput::Get().ProcessMouse();
mousePosition = DirectInput::Get().GetCurrentMousePosition();
position.x = (float) mousePosition.x;
position.y = (float) mousePosition.y;
position.z = 0.0f;
currentPosition = m_pCrossHairs->GetSpritePosition();
position.x -= currentPosition.x;
position.y -= currentPosition.y;
position.x = position.x/2.0f;
position.y = position.y/2.0f;
m_pCrossHairs->SetTranslationMatrix(position);
m_pCrossHairs->CheckBoundary();
m_pCrossHairs->Update();
}
And here is what I've changed it to for use with an Xbox Controller Instead:
virtual void Update()
{
POINT crosshairPosition;
D3DXVECTOR3 position, currentPosition;
crosshairPosition.x = XBox360Controller::Get().RightJoyStickX();
crosshairPosition.y =- XBox360Controller::Get().RightJoyStickY();
position.x = crosshairPosition.x;
position.y = crosshairPosition.y;
position.z = 0.0f;
currentPosition = m_pCrossHairs->GetSpritePosition();
position.x -= currentPosition.x;
position.y -= currentPosition.y;
position.x = position.x/2.0f;
position.y = position.y/2.0f;
m_pCrossHairs->SetTranslationMatrix(position);
m_pCrossHairs->CheckBoundary();
m_pCrossHairs->Update();
}
On a positive note what I have done kind of works. The Crosshair does move when I move the analog stick, however it is stuck in the top right hand corner and can only move within a range of about 1 square inch on the screen. I'm a bit stuck as to why this is and therefore would appreciate any kind of input. Sorry if I'm lacking any important info that I may have missed, a bit of a late post however would really love to get it working!
On a side note - I'm getting an error on the following giving me a warning about conversion from long to float or something (should I be worried about this)?
crosshairPosition.x = XBox360Controller::Get().RightJoyStickX();
crosshairPosition.y =- XBox360Controller::Get().RightJoyStickY();
Once again thank you in advance.
Billy
Edit:
Code for XBox360Controller::Get().
XBox360Controller& XBox360Controller::Get()
{
if (s_pXBox360Controller == NULL)
s_pXBox360Controller = new XBox360Controller();
return *s_pXBox360Controller;
}
Code for Right analog stick X-Axis
float XBox360Controller::RightJoyStickX()
{
float joyStickX = GetState().Gamepad.sThumbRX;
// Make sure there has been movement, as joystick does return different values even if no movement.
if ( joyStickX< XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
joyStickX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
return 0;
else
return joyStickX/DynamicRange;
}
Code for Right analog stick Y-Axis
float XBox360Controller::RightJoyStickY()
{
float joyStickY = GetState().Gamepad.sThumbRY;
// Make sure there has been movement, as joystick does return different values even if no movement.
if ( joyStickY< XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
joyStickY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
return 0;
else
return joyStickY/DynamicRange;
}
EDIT SOLVED:
Added a new translation matrix and it's fixed the issue, thanks for the help.
Related
So I'm making this FPS game where I want to move forward, backward, left and right with keyboard input and look around with the camera like in a real FPS-game like Battlefield. The camera movement in combination with the keyboard input works great, but now my camera can fly around. And I just want to be able to stay on the "ground" and move forward, backward, left and right while looking up or down like in a game like battlefield without flying around (like no-clip does). Now If I look down or up and press forward on my keyboard I can "fly", but I don't want this to happen.
A friend of my suggested to use something like this to go forward.
Position += glm::vec3(glm::cos(Yaw), glm::sin(Yaw), 0) * velocity
instead of:
Position += Front * velocity;
But I don't fully understand how this would work?
This is the current keyboard input code:
void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime)
{
float velocity = MovementSpeed * deltaTime;
if (direction == FORWARD)
Position += Front * velocity;
if (direction == BACKWARD)
Position -= Front * velocity;
if (direction == LEFT)
Position -= Right * velocity;
if (direction == RIGHT)
Position += Right * velocity;
}
Tips or help would be appreciated!
Yes this code comes from LearnOpenGL.com
What we are doing here is trying to simulate movement by moving all objects in the scene in the reverse direction, giving the illusion that we are moving.
To make the camera stay on the ground, simply don't move it up and down.
Yeah, the part where the camera moves up and down? You're the one who wrote that code. Delete it.
You didn't say where this Front vector comes from. It comes from a place that is taking pitch and yaw into account. Delete the pitch part.
Your friend's suggestion glm::vec3(glm::cos(Yaw), glm::sin(Yaw), 0) is a way to calculate Front using only yaw.
As your game gets more advanced you may also implement jumping and gravity, so the player can go up and down to a limited extent.
I want to thank everyone for helping me out! I understand better how everything works now. I want to move in the x-z plane and y must be zero (yes I chose the Y-axis as "up" or "the sky"), because I don't want the camera to move up or down. So when I go forward I only want to change the x and z parameter of the glm vector!
void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime)
{
float velocity = MovementSpeed * deltaTime;
if (direction == FORWARD) {
// glm::vec3(X,Y,Z)!!! we only want to change the X-Z position
Position += glm::vec3(glm::cos(glm::radians(Yaw)), 0, glm::sin(glm::radians(Yaw))) * velocity; //Y is not affected, Y is looking up
}
if (direction == BACKWARD) {
// glm::vec3(X,Y,Z)!!! we only want to change the X-Z position
Position -= glm::vec3(glm::cos(glm::radians(Yaw)), 0, glm::sin(glm::radians(Yaw))) * velocity; //Y is not affected, Y is looking up
}
if (direction == LEFT) {
Position -= Right * velocity;
}
if (direction == RIGHT) {
Position += Right * velocity;
}
}
Now everything works great!
I am a beginner in C++ and know SFML. I have read a lot of articles about Sprite rotation towards Mouse and have been able to calculate proper angle of rotation of Sprite using this code:
void Player::changeAngle(double Mx, double My) { // This is for making Player point towards Mouse
double dX = x - Mx; // x and y are global Varibales declared outside
double dY = y - My;
double magnitude = sqrt((dX*dX) + (dY*dY));
double normalizedX = dX / magnitude;
double normalizedY = dY / magnitude;
// This part is for Making Player move to Mouse
Xvelocity = normalizedX * speed; // Xvelocity, Yvelocity and speed are global variables
Yvelocity = normalizedY * speed;
// Rotate towards the Mouse
double angle = ( atan2(dY, dX) ) * 180 / M_PI;
entity.setRotation(angle); // entity is a sf::RectangleShape
}
And, this bit actually worked and the Sprite was rotating properly only before a few days. Now the Sprite is just frozen on the screen, nothing happens. I had not made any changes in that code but I had added a View from the main.cpp.
So here is how I call changeAngle() from the main.cpp :
case Event::MouseMoved : {
Vector2f worldPos = window.mapPixelToCoords(Mouse::getPosition(window), view);
double x = worldPos.x;
double y = worldPos.y;
player.changeAngle(x, y);
break;
}
I tried running the debugger and stepped through the code. I found that the angle is properly calculated and my mouse coordinates are also right. And, to my surprise, the sprite was Rotating now !
I could not understand why, but every time its in debugging mode, the Sprite will rotate. But, it won't rotate while running normally.
Can anyone tell me why and how to fix it so it rotates every time ? Tell me if there is any problem with my code.
Thanks !
I've successfully implemented dragging a sprite on the screen, by simply remembering touch position on touchbegan and translating sprite by currentTouchPoint - startingTouchPoint, which gives me nice dragging. But now I want to sprite track my finger instead so it also should rotate. This would give me an advantage of making user able to rotate sprite as well as drag it around with just one finger.
I was getting unexpected results, but I've ran into this code:
http://www.freeactionscript.com/2011/01/mouse-follow-with-easing-smooth-rotation-v2/
There's a demo so you could try it on the browser.
It's pretty much the same I need except sprite should be a lot faster (near the finger all the time) and stop after reaching it's destination instead of orbiting around (while holding touch). I've tried to port it to cocos2d-x, but it doesn't work the same. Well, updatePosition() looks good, sprite is going where it should be pretty much, but updateRotation() is a total mess. It's rotating in strange directions and sometimes even makes a full very fast circle in opposite direction.
onTouchBegan:
//check if any sprite is touched and then assign it to draggedItem
onTouchMove:
_destinationX = touchPoint.x;
_destinationY = touchPoint.y;
onTouchEnd:
//make draggedItem nullptr
void CreatorScene::update(float delta){
if(draggedItem != nullptr){
updateItemPosition();
updateItemRotation();
}
}
void CreatorScene::updateItemRotation()
{
// calculate rotation
_dx = draggedItem->getPositionX() - _destinationX;
_dy = draggedItem->getPositionY() - _destinationY;
// which way to rotate
float rad = atan2(_dy, _dx);
if(_dy < 0) rad += 2 * M_PI;
float rotateTo = CC_RADIANS_TO_DEGREES(rad);
// keep rotation positive, between 0 and 360 degrees
if (rotateTo > draggedItem->getRotation() + 180) rotateTo -= 360;
if (rotateTo < draggedItem->getRotation() - 180) rotateTo += 360;
// ease rotation
_trueRotation = (rotateTo - draggedItem->getRotation()) / ROTATE_SPEED_MAX;
// update rotation
draggedItem->setRotation(draggedItem->getRotation() + _trueRotation);
}
void CreatorScene::updateItemPosition()
{
// check if mouse is down
// if (_isActive)
// {
// update destination
// _destinationX = stage.mouseX;
// _destinationY = stage.mouseY;
// update velocity
_vx += (_destinationX - draggedItem->getPositionX()) / MOVE_SPEED_MAX;
_vy += (_destinationY - draggedItem->getPositionY()) / MOVE_SPEED_MAX;
// }
// else
// {
// // when mouse is not down, update velocity half of normal speed
// _vx += (_destinationX - _player.x) / _moveSpeedMax * .25;
// _vy += (_destinationY - _player.y) / _moveSpeedMax * .25;
// }
// apply decay (drag)
_vx *= DECAY;
_vy *= DECAY;
// if close to target, slow down turn speed
if (sqrtf((_dx*_dx)+(_dy*_dy)) < 50)
{
_trueRotation *= .5;
}
// update position
draggedItem->setPosition(draggedItem->getPosition() + Point(_vx, _vy));
}
What's wrong here? How can I achieve such a smooth movement?
Edit:
Functionality that I want to exactly achieve is here:
https://www.youtube.com/watch?v=RZouMyyNGG8
You can see it on 2:10.
EDIT: I CHANGED THE QUESTION WHEN I REALIZED THAT I ACTUALLY NEEDED TO MOVE THE CAMERA AND NOT THE POLYGON. MY BAD, EVERYONE.
So I'm taking a class on OpenGL and need to define a path that the camera can automatically traverse.
How can I make my camera move around my world by hitting the F1 key?
Just to clarify,
I know how to use keyboard functions that use constants such as GLUT_KEY_F1.
I'm trying something new and am clueless.
Is this as simple as incrementing (with a loop) the values in the parameters of gluLookAt() ?
Here is the code that I have now:
if(key == GLUT_KEY_F1)
{
float x;
collisionKey = GLUT_KEY_F1;
for(x = 0.0; x < 3600.0;)
{
x += .01;
gluLookAt(200 + x, cameraY, 400 + cameraZ, 200 + studentX, 250 + studentY, studentZ, 0, 1, 0);
}
}
glutPostRedisplay();
Let me know if you have any questions!
I am totally stumped on this one. I'm using C++ and SFML 1.6 for a game I'm developing, and I have no bloody idea. How do I make projectiles (like bullets)? I just don't understand it. It could be my lack of sleep but I don't know.
So my question is how do I create a Sprite that moves in a definite direction based on where the mouse is? (Think of a top down shooter with mouse aiming)
Easiest solution:
If the mouse is at Mx,My and the ship is at Sx,Sy then calculate the direction from the ship to the mouse:
Dx=Sx-Mx
Dy=Sy-My
Now normalise D (this means scale it so that it's length is one):
DLen=sqrt(Dx*Dx + Dy*Dy)
Dx/=DLen;
Dy/=DLen;
Now Dx is the distance you want to move the bullet on the x axis in order to get bullet speed of 1.
Thus each frame you move the bullet like so (position of bullet: Bx,By Speed of bullet: Bs [in pixels per millisec] Frame time Ft[in millisec])
Bx=Bx+Dx*Bs*Ft
By=By+Dy*Bs*Ft
This give you a bullet that moves towards the mouse position at a speed independent of the direction of the mouse or framerate of the game.
EDIT: As #MSalters says you need to check for the DLen==0 case when the mouse is directly above the ship to avoid division by zero errors on the normalise
One way to do it is to make the bullet face the mouse and then move it across the x and y axis by using trigonometry to find the hypotinuse from the angle. I don't think i explained this very well, so here the code to make a sprite move from its rotation:
void sMove(sf::Sprite& input,float toMove, int rotation){
bool negY = false;
bool negX = false;
int newRot = rotation;
if (rotation <= 90){
negY = true;
}
else if (rotation <= 180){
//newRot -= 90;
negY = true;
}
else if (rotation <= 360){
newRot -= 270;
negY = true;
negX = true;
}
float y = toMove*cos(newRot*PI/180);
float x = toMove*sin(newRot*PI/180);
if (negY){
y = y*-1;
}
if (negX){
x = x*-1
}
input.move(x, y);
}