Make sprite bounce back - c++

I'm playing a little around with DirectX 9.0 and want a object to bounce back when it hits the screen edges (top,bottom,right and left). The sprite is an image that is 128x128 pixels.
I manage to make it bounce back and forth, but this does not happend before the image is either half outside the screen, or too early. This is because the object it self is in the middle of the image, is there anyway to "remove" the background part so the program does not bounce back the sprite before the image part itself collides with the screen edge?
Do I have to modify the image manually? Like cropping it or something=
Here is some of the code I'm working with:
if(this->Textures[i].posision.x >= this->_screenWidth)
{
this->Textures[i].right = false;
}
else if(this->Textures[i].posision.x <= 0)
{
this->Textures[i].right = true;
}
if(!this->Textures[i].right)
this->Textures[i].posision.x -= 0.3f;
else
this->Textures[i].posision.x += 0.3f;
Thanks for any help!

well, if you're travelling with a left-ward vector, a collision would be qualified as:
if(this->Textures[i].posision.x - 128/2 <= 0)
{
this->Textures[i].right = true;
}
if your position.x and position.y refer to the centre of the image, then all you have to do is add/subtract half the image size to get the bounds of your image.
If your sprite isn't filling up your image, then you should probably crop some of it out.

Related

SFML sf::View::move inconstancy

UPDATE:
I couldn't figure out the exact problem, however I made a fix that's good enough for me: Whenever the player's X value is less then half the screen's width, I just snap the view back to the center (up left corner) using sf::View::setCenter().
So I'm working on a recreating of Zelda II to help learn SFML good enough so I can make my own game based off of Zelda II. The issue is the screen scrolling, for some reason, if link walks away from the wall and initiated the camera to follow him, and then move back toward the wall, the camera won't go all the way back to the end of the wall, which occurs on the other wall at the end of the scene/room. This can be done multiple times to keep making the said camera block get further away from the wall. This happens on both sides of the scene, and I have reason to believe it has something to do with me trying to make the game frame independent, here's an included GIF of my issue to help understand:
My camera function:
void Game::camera() {
if (this->player.getVar('x') >= this->WIDTH / 2 and this->player.getVar('x') < this->sceneWidth - this->WIDTH / 2) {
this->view.move(int(this->player.getVar('v') * this->player.dt * this->player.dtM), 0);
}
}
player.getVar() is a temporary function I'm using to get the players x position and x velocity, using the argument 'x' returns the players x position, and 'v' returns the x velocity. WIDTH is equal to 256, and sceneWidth equals 767, which is the image I'm using for the background's width. dt and dtM are variables for the frame independence I mentioned earlier, this is the deceleration:
sf::Clock sclock;
float dt = 0;
float dtM = 60;
int frame = 0;
void updateTime() {
dt = sclock.restart().asSeconds();
frame += 1 * dt * dtM;
}
updateTime() is called every frame, so dt is updated every frame as well. frame is just a frame counter for Link's animations, and isn't relevant to the question. Everything that moves and is rendered on the screen is multiplied by dt and dtM respectively.
There's a clear mismatch between the movement of the player and the one of the camera... You don't show the code to move the player, but if I guess you don't cast to int the movement there, as you are doing on the view.move call. That wouldn't be a problem if you were setting the absolute position of the camera, but as you are constantly moving it, the little offset accumulates each frame, causing your problem.
One possible solution on is to skip the cast, which is unnecessary because sf::View::move accepts float as arguments.
void Game::camera() {
if (this->player.getVar('x') >= this->WIDTH / 2 and this->player.getVar('x') < this->sceneWidth - this->WIDTH / 2) {
this->view.move(this->player.getVar('v') * this->player.dt * this->player.dtM, 0);
}
}
Or even better, not to use view.move but to directly set the position of the camera each frame. Something like:
void Game::camera() {
if (this->player.getVar('x') >= this->WIDTH / 2 and this->player.getVar('x') < this->sceneWidth - this->WIDTH / 2) {
this->view.setCenter(this->player.getVar('x'), this->view.getCenter().y);
}
}

Display win/lose picture after gameState changes (SFML Minesweeper)

So I wrote minesweeper game and made GUI with SFML, just have a problem with displaying picture of win/lose when player finishes the game or loses it. Game states are set well and they trigger at right moments, the problem is that pictures I want to display I think are too big and in the window, I can see only their background (like top left corner of the picture). Is there a way to scale the picture to the window and display it fully in the window?
Constructor:
minesweeperBoard* board;
sf::Texture t;
MSSFMLView::MSSFMLView(minesweeperBoard& board) {
this->board = &board;
t.loadFromFile("src/images/tiles.jpg");
window.create(sf::VideoMode(32*this->board->getBoardWidth(), 32*this->board->getBoardHeight()), "Minesweeper");
}
Gamestate if trigger in a game loop:
if(board->state == GameState::FINISHED_WIN){
t.loadFromFile("src/images/win.jpg");
sf::Sprite s(t);
s.scale(32*this->board->getBoardWidth(),32*this->board->getBoardHeight());
window.draw(s);
Sleep(1000);
window.clear();
}else if(board->state == GameState::FINISHED_LOSS){
t.loadFromFile("src/images/lose.jpg");
sf::Sprite s(t);
s.scale(32*this->board->getBoardWidth(),32*this->board->getBoardHeight());
window.draw(s);
Sleep(1000);
window.clear();
}
Those are the pictures I use: https://imgur.com/a/KVCuyab
256x256 size
When you call s.scale(32this->board->getBoardWidth(),32this->board->getBoardHeight());
what you are doing is increasing the size of the image by an amount in the x and y direction, in this case 32 times the board size. This will make the image too large to fit onto the screen.
Note that the scale function changes the size of a sf::Sprite by multiplying it, not by setting it.
So if you want to change the size of an image to fit your board, don't use
s.scale(32*this->board->getBoardWidth(),32*this->board->getBoardHeight());
because that is multiplying the size of the image, making it huge. Instead, scale it by the desired size divided by the actual size:
float desiredW = 32*this->board->getBoardWidth();
float desiredH = 32*this->board->getBoardHeight();
float currentW = s.getGlobalBounds().width;
float currentH = s.getGlobalBounds().height;
s.scale(desiredW / currentW, desiredH / currentH);

How do I flip an image and point a gun at the mouse at the same time? (SFML)

I'm making a shooter where the player can shoot at the mouse, so I got the guns to point at the mouse, but I can't figure out how to correctly flip the image once it's turned left. I mean, I did flip the image but it's not aligned right. I'm not really sure how to explain it, here's my code.
void PortalGun::update(Vector2i mPos) {
float pi = 3.14159265359;
float rotation = atan2(sprite.getGlobalBounds().top - mPos.y,sprite.getGlobalBounds().left - mPos.x) * 180 / pi;
int x = player->sprite.getGlobalBounds().left + 16;
int y = player->sprite.getGlobalBounds().top;
if (rotation > -90 && rotation < 90) {
player->dir = -1;
sprite.setTextureRect(IntRect(0, 32, 64, -32));
} else {
player->dir = 1;
sprite.setTextureRect(IntRect(0, 0, 64, 32));
}
sprite.setPosition(x, y + 15);
sprite.setRotation(rotation + 170);
}
When the mouse is to the left of the gun, it flips the image but keeps rotating upwards so the mouse is 20 ish pixels higher. I can't just change the position when rotating, so what do I do? Sorry for sounding a bit cryptic, it's a bit hard to explain.
First of all, you should set your sprite's origin to the point where you'd like to rotate the gun (typically the handle or mounting point). To do this, use sf::Sprite::setOrigin(). The passed coordinates are relative to the top left corner of the sprite.
To get or set your sprite's position in the world (where your origin is), you can use sf::Sprite::getPosition() and sf::Sprite::setPosition().
Your rotation can stay as it is. It will rotate around your set origin.
To mirror your sprite, just scale (sf::Sprite::setScale()) it using a negative factor: sprite.setScale(-1, 1); The negative factor will mirror/flip the image at the set origin, without forcing you to update the texture coordinates.

Flipping Sprite In The Update Loop

I've got a bird sprite that I want to bounce around the screen. So when it reaches the bounds of the screen, the bird will travel back and forth. This is working but I'm not able to flip the sprite each time.It works the first time it moves right and hits the right edge of the screen, and when it comes back and hits the left side, the sprite does not flip. Here's what I'm trying to do
- (void)update:(ccTime)dt
{
if (bird_x > 1550 || bird_x < 0)
{
flip *= -1;
self.bird.flipX = YES;
}
bird_x = bird_x + 10 * flip;
_bird.position = ccp(bird_x, 1000);
}
What am I doing wrong?
Thanks in advance.
It's because the flip is only an on/off state. Replace your self.bird.flipX = YES; line with self.bird.flipX = !self.bird.flipX; and try again.

Can I make CCFollow follow more naturally?

I want to build a platform game with cocos2d/Box2D. I use CCFollow to follow the player sprite but CCFollow constantly puts it in the center of the screen. I want CCFollow to follow more naturally, like a human turning a camcorder with an acceptable lag, a small overshoot ...etc.
Here is a method of mine that didn't work: I attached (via a distance joint) a small physics body to the player that doesn't collide with anything, represented by a transparent sprite. I CCFollow'ed the transparent sprite. I was hoping this ghost body would act like a balloon attached to the player, hence a smooth shift in view. The problem is distance joint breaks with too heavy - too light objects. The balloon moves around randomly, and of course, it pulls the player back a little no matter how light it is.
What is a better way of following a moving sprite smoothly?
Try add this to CCActions in cocos2d libs.
-(void) step:(ccTime) dt
{
#define CLAMP(x,y,z) MIN(MAX(x,y),z)
CGPoint pos;
if(boundarySet)
{
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(boundaryFullyCovered) return;
CGPoint tempPos = ccpSub(halfScreenSize, followedNode_.position);
pos = ccp(CLAMP(tempPos.x,leftBoundary,rightBoundary), CLAMP(tempPos.y,bottomBoundary,topBoundary));
}
else {
// pos = ccpSub( halfScreenSize, followedNode_.position );
CCNode *n = (CCNode*)target_;
float s = n.scale;
pos = ccpSub( halfScreenSize, followedNode_.position );
pos.x *= s;
pos.y *= s;
}
CGPoint moveVect;
CGPoint oldPos = [target_ position];
double dist = ccpDistance(pos, oldPos);
if (dist > 1){
moveVect = ccpMult(ccpSub(pos,oldPos),0.05); //0.05 is the smooth constant.
oldPos = ccpAdd(oldPos, moveVect);
[target_ setPosition:oldPos];
}
#undef CLAMP
}
i get this from cocos2d forums.
Perhaps this http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:actions_ease can help you get an "acceleration" effect with CCFollow.