I have a problem using sfml where it seems sf::Transforms get applied relative to the origin of whole coordinate system and not the origin of the sprite/thing being transformed.
For example in the two following example I expect the same behavior and it's not what happens.
(differences in bold, most of rest just serves to actually display a sfml window with a circle that gets scaled down when space is pressed)
First Example : here the circle is scaled down towards the top left corner of the window
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 800), "Example");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
shape.setPosition(400, 400);
sf::Transform t;
t.scale( 9/10.f , 9/10.f);
sf::Transform t_n;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed){
window.close();
}
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Space) {
t_n = t_n * t;
}
}
}
window.clear();
window.draw(shape, t_n);
window.display();
}
return 0;
}
Second Example : Here the circle is scaled down towards the top left corner of its bounding box : this is the kind of behavior I want to achieve but using Transforms
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 800), "Example");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
shape.setPosition(400, 400);
// no Transforms need declaring
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed){
window.close();
}
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Space) {
shape.scale(9/10.f, 9/10.f);
}
}
}
window.clear();
window.draw(shape);
window.display();
}
return 0;
}
note: this is a possible duplicate of Transformations igrnores sf::Sprite's origin , but the only answer to this thread is my own, and the solution I suggest is really not ideal.
Related
i am new to SFML and was wandering why my player will only move at a certain distance witch is a very small distance.
Here is my code:
game.cpp:
#include <SFML/Graphics.hpp>
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Game!");
while(window.isOpen()) {
sf::Event event;
while(window.pollEvent(event)) {
if(event.type == sf::Event::Closed)
window.close();
}
sf::Font font;
if(!font.loadFromFile("../resources/Lets Coffee.ttf"))
return EXIT_FAILURE;
sf::Text text("Use the WASD keys to move the player around", font, 20);
text.setPosition(5, 5);
// make a player sprite
sf::Texture *playerTexture;
playerTexture = new sf::Texture();
if(!playerTexture->loadFromFile("../resources/Bluey.png"))
return EXIT_FAILURE;
sf::RectangleShape player(sf::Vector2f(128, 128));
player.setPosition(400, 300);
player.setTexture(playerTexture);
player.setOutlineColor(sf::Color::Black);
player.setOutlineThickness(10);
// Here is my distance problem:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
player.move(0, -5);
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
player.move(0, 5);
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
player.move(-5, 0);
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
player.move(5, 0);
}
window.clear();
window.draw(text);
window.draw(player);
window.display();
}
return 0;
}
Could any of you help?, and am i doing something wrong?, if i am the please tell me!
Credit : Gerard0097
The issue is that your are creating the player object within your main loop, so each cycle you create a new object and that's why is seems like it's moving a short distance but it's just different objects moving once and then being destroyed
Credit : Me
Just create player and texture before main loop (game loop) :
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Game!");
sf::Font font;
if(!font.loadFromFile("../resources/Lets Coffee.ttf"))
return EXIT_FAILURE;
sf::Text text("Use the WASD keys to move the player around", font, 20);
text.setPosition(5, 5);
sf::Texture *playerTexture;
playerTexture = new sf::Texture();
if(!playerTexture->loadFromFile("../resources/Bluey.png"))
return EXIT_FAILURE;
sf::RectangleShape player(sf::Vector2f(128, 128));
player.setPosition(400, 300);
player.setTexture(playerTexture);
player.setOutlineColor(sf::Color::Black);
player.setOutlineThickness(10);
and then your game loop :
while (game.isOpen) {
// Your Game Logic, Event Handling and drawings
}
Here is my code:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "Sprites!");
sf::Texture playerTex;
playerTex.loadFromFile("Textures/player_ship.png");
sf::Sprite playerSprite;
playerSprite.setTexture(playerTex);
playerSprite.setScale(1.5, 1.5);
playerSprite.setPosition(100, 100);
playerSprite.setOrigin(32, 32);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(playerSprite);
window.display();
}
}
When I run this code, SFML opens a blank window (it should have a sprite) and when this window closes, it returns the error Failed to load image ".
I have the Textures folder located in multiple directories so it should be able to see it. I've already tried re-copying the textures and reinstalling SFML. How do I fix it??
I want create light blue background so I draw 2 rectangles (blue and white).
But when I execute program i see only black screen.Also my video adapter is fully loaded.
Code:
int main() {
srand(time(NULL));
RenderWindow window(sf::VideoMode(500, 500), "Fish!",sf::Style::Close|sf::Style::Resize);
RectangleShape water(Vector2f(500,500));
RectangleShape background(Vector2f(500,500));
background.setFillColor(Color(255,255,255,3));
water.setFillColor(Color(5,45,255,1));
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case (sf::Event::Resized):
break;
case (sf::Event::Closed):
window.close();
break;
}
}
window.clear();
window.draw(background);
window.draw(water);
window.display();
}
I need window.clear function because i want insert some object later on the screen!
In this code I have one view (white, zoom 2) and the original window, also one sprite for a car and one sprite for a wall...
#include <SFML/Graphics.hpp>
#include "collision.hpp"
#define windowWidth 1000
#define windowHeight 600
int main()
{
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "SFML Views");
sf::View view(sf::FloatRect(0,0, windowWidth, windowHeight));
view.zoom(2);
// car
sf::Texture imgCar;
Collision::CreateTextureAndBitmask(imgCar, "carro.png" );
sf::Sprite car;
car.setTexture(imgCar);
car.setPosition(0, (windowHeight - imgCar.getSize().y) / 2);
// wall
sf::Texture imgWall;
Collision::CreateTextureAndBitmask( imgWall, "barreira.png" );
sf::Sprite wall;
wall.setTexture(imgWall);
wall.setPosition(windowWidth - imgWall.getSize().x, 0);
sf::RectangleShape background (sf::Vector2f(windowWidth, windowHeight));
background.setFillColor(sf::Color::White);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
if (!Collision::PixelPerfectTest(car, wall))
car.move(0.1, 0);
window.clear();
window.setView(view);
window.draw(background);
window.setView(window.getDefaultView());
window.draw(car);
window.draw(wall);
window.display();
}
return 0;
}
... if both car and wall are related with the main window, I get a perfect car collision with the wall. (see image).
Now if I put the car inside the view ...
window.clear();
window.setView(view);
window.draw(background);
window.draw(car);
window.setView(window.getDefaultView());
window.draw(wall);
window.display();
... the collision is detected as if the wall were within the boundaries of the view (which is zoomed in) (see image).
How can I make the collision detection independent of the view?
I am writing a small program using SFML which draws a 5 x 5 rectangle at any point specified by clicking the mouse.
I am using mapPixelToCoords() to map the mouse coordinates to the pixels as recommended in the documentation, however I am still encountering a weird offset between the coordinates and the actual shape which is drawn.
The offset varies on different parts of the window (it is not a constant x,y value).
I would like the rectangle to be drawn precisely under the mouse pointer, how do I go about removing this offset?
This is the code I'm using to draw the rectangle on click:
Screenshot of offset in the window
int main(){
sf::RenderWindow window(sf::VideoMode(800, 720), "SFML window");
sf::Event event;
//Rectangle to be drawn on the screen
sf::RectangleShape someRect;
someRect.setFillColor(sf::Color(0, 0, 0));
someRect.setSize({ 5, 5 });
someRect.setPosition(100, 120);
while (window.isOpen())
{
if (!windowStarted) {
event.type = sf::Event::Closed;
}
while (window.pollEvent(event))
{
// Close window: exit
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.type == sf::Event::MouseButtonPressed) {
someRect.setPosition(window.mapPixelToCoords(sf::Mouse::getPosition(window)));
}
}
window.clear(sf::Color(255, 255, 255));
window.draw(someRect);
window.display();
}
return 0;
}