Strange behaviour when drawing convex shape figure in SFML - c++

I'm drawing a convex shape figure using SFML library:
#include <SFML/Graphics.hpp>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(400, 400), "SFML window");
ConvexShape convex;
convex.setPointCount(8);
convex.setPoint(0, sf::Vector2f(0, 0));
convex.setPoint(1, sf::Vector2f(180, 0));
convex.setPoint(2, sf::Vector2f(180, 90));
convex.setPoint(3, sf::Vector2f(100, 90));
convex.setPoint(4, sf::Vector2f(100, 180));
convex.setPoint(5, sf::Vector2f(30, 180));
convex.setPoint(6, sf::Vector2f(30, 90));
convex.setPoint(7, sf::Vector2f(0, 90));
convex.setPosition(100, 100);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(convex);
window.display();
}
return EXIT_SUCCESS;
}
The points defined in clockwise order and everything is ok!
convex1
But when I change two coordinates a little bit I'm getting something that I really don't expect:
#include <SFML/Graphics.hpp>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(400, 400), "SFML window");
ConvexShape convex;
convex.setPointCount(8);
convex.setPoint(0, sf::Vector2f(0, 0));
convex.setPoint(1, sf::Vector2f(180, 0));
convex.setPoint(2, sf::Vector2f(180, 90));
convex.setPoint(3, sf::Vector2f(100, 90));
convex.setPoint(4, sf::Vector2f(100, 200)); // CHANGED 180 to 200
convex.setPoint(5, sf::Vector2f(30, 200)); // CHANGED 180 to 200
convex.setPoint(6, sf::Vector2f(30, 90));
convex.setPoint(7, sf::Vector2f(0, 90));
convex.setPosition(50, 50);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(convex);
window.display();
}
return EXIT_SUCCESS;
}
I'm getting the following window:
convex2
Why this situation take place?

These coordinates are related to the points in your Convex shape, you should use those only to change the format of the object. In order to move your entire object you should use this:
convex.move(x Position, y Position);

Related

Compile error in SFML 2.5.1 sample code in Linux

Compile error
I was looking at a configuration video in yt for linux mint but it doesn't give me the same results in arch.
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
window.display();
}
return 0;
}
As the error message indicate, there is no constructor for sf::VideoMode which takes two int input for width and height. The constructor expect an argument of type Vector2u.
Create the Window as follows:
sf::RenderWindow window(sf::VideoMode({200, 200}), "SFML works!");

Rectangle in sdl2 sets colour for entire screen

I know there are already questions like this on SO but I am new to SDL2 and I have had a look at some tutorials to draw a rectangle and I have had a look at some questions here as well. With the current code below I cannot draw a rectanlge onto the window as it doesn't appear I have also tried to clear the window after the rectangle is meant to be drawn this just sets the entire window to that colour.
#include <iostream>
#include <SDL2\SDL.h>
int main(int argc, char** argv){
SDL_Window* window;
window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* render;
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
bool close = false;
SDL_Event event;
while (close == false){
while (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT){
close = true;
}
}
//set colour
SDL_SetRenderDrawColor(render, 255, 0, 0, 255);
SDL_RenderClear(render);
SDL_Rect rect;
rect.x, rect.y, rect.h, rect.w = 50, 50, 50, 50;
SDL_SetRenderDrawColor(render, 0, 0, 255, 255);
SDL_RenderFillRect(render, &rect);
//SDL_RenderClear(render); <-- If this is uncommented it clears the screen to blue.
SDL_RenderPresent(render);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(render);
SDL_Quit();
}
This is mean't to draw a blue rectangle onto a red window but I only get the red window and clearing the renderer only set's the window blue. Why does this rectangle not draw? If it is drawing then how come the colour of it ahsnt changed so it doesn't blend in with the background.
I have used these questions to help me get this far:
How to draw a rectangle in SDL 2 and what exactly is a renderer
SDL2 Wont draw Rectangles Correctly
https://dev.to/noah11012/using-sdl2-drawing-rectangles-3hc2
Your issue seems to be with the rect.x, rect.y, rect.h, rect.w = 50, 50, 50, 50;
When I changed it to
rect.x = 50;
rect.y = 50;
rect.h = 50;
rect.w = 50;
The program worked

SDL_FINGERDOWN not registering correctly

I don't why SDL_FINGERDOWN records
even simple touch event. It should register on Sliding finger down as name says, right? I use android N for testing.
Here is my code
#include "SDL.h"
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
int r, g, b;
r = g = b = 0;
SDL_Window *window;
window = SDL_CreateWindow("S", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 720, 1320, SDL_WINDOW_RESIZABLE);
SDL_Surface *screen = SDL_GetWindowSurface(window);
Uint32 white = SDL_MapRGB(screen->format, 255, 255, 255);
SDL_FillRect(screen, NULL, white);
SDL_UpdateWindowSurface(window);
SDL_Event event;
bool running = true;
while (running)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_FINGERDOWN)
{
running = false;
break;
}
//end if
} //end inner while
}
SDL_DestroyWindow(window);
SDL_Quit();
}
You have misunderstood meaning of SDL_FINGERDOWN and SDL_FINGERUP.
When you land your finger on touch screen then that's event of type SDL_FINGERDOWN.When you lift up your finger from touch screen then that's event of type SDL_FINGERUP.

Rotate an axis aligned rectangle by a 90 degrees

I have rectangle object (sf::IntRect) , with attributes: left, top, width and height on a 2D plane. I want to rotate it by a multiple of 90 degrees (that is 90, 180 or 270), around point (0,0). Thus I am writing a function like this:
void rotateRect(sf::IntRect& rect, int rot)
{
//code I need
}
the rotation is either 0 (0), 1 (90), 2 (180) or 3 (270).
How can I achieve this as simply as possible.
Here is a basic solution using sf::Tranform on sf::FloatRect:
constexpr auto rotationAngle(int rot) { return rot * 90.f; }
void rotateRect(sf::IntRect& rect, int rot)
{
auto deg = rotationAngle(rot);
auto transform = sf::Transform();
transform.rotate(deg);
// Would be better if rect was a FloatRect...
auto rectf = sf::FloatRect(rect);
rectf = transform.transformRect(rectf);
rect = static_cast<sf::IntRect>(rectf);
}
However, I personally would slightly change the signature of your function to use float rects and a more compact notation:
sf::FloatRect rotateRect(sf::FloatRect const& rect, int rot)
{
return sf::Transform().rotate(rotationAngle(rot)).transformRect(rect);
}
And below a full example showing how it behaves.
#include <SFML/Graphics.hpp>
constexpr auto rotationAngle(int rot) { return rot * 90.f; }
sf::FloatRect rotateRect(sf::FloatRect const& rect, int rot)
{
return sf::Transform().rotate(rotationAngle(rot)).transformRect(rect);
}
void updateShape(sf::RectangleShape& shape, sf::FloatRect const& rect)
{
shape.setPosition(rect.left, rect.top);
shape.setSize({ static_cast<float>(rect.width), static_cast<float>(rect.height) });
}
int main(int, char const**)
{
sf::RenderWindow window(sf::VideoMode(500, 500), "rotate");
auto rect = sf::FloatRect(0, 0, 100, 50);
auto shape = sf::RectangleShape();
shape.setFillColor(sf::Color::Red);
updateShape(shape, rect);
auto view = window.getView();
view.move({ -250, -250 });
window.setView(view);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::R)
{
rect = rotateRect(rect, 1);
updateShape(shape, rect);
}
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::N)
{
rect = sf::FloatRect(50, 50, 100, 50);
updateShape(shape, rect);
}
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::M)
{
rect = sf::FloatRect(0, 0, 100, 50);
updateShape(shape, rect);
}
}
window.clear();
window.draw(shape);
window.display();
}
return EXIT_SUCCESS;
}
NB: I used a few trick from C++14 but I'm sure you can convert that code to C++11/C++98 if you need to.

Repeating texture to fit certain size in SFML

I have a file that contains textures. I load it to sf::Texture and split into sprites with setTextureRect.
Now lets say one sprite contains part of texture that is 20 pixels wide. How can I render it to fit width of e.g. 213 pixels. The only way I can think about is to render it to sf::RenderTexture and crop it with another sprite.
Is there a better way to do this?
You can use sf::Texture::setRepeated to do that.
However, you'll need to copy that part of your bigger image into an independant texture.
Here is an example:
#include <SFML/Graphics.hpp>
int main(int, char const**)
{
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
sf::Image img;
img.create(20, 20);
for (auto i = 0; i < 20; ++i) {
for (auto j = 0; j < 20; ++j) {
img.setPixel(i, j, sf::Color(255 * i / 20, 255 * j / 20, 255 * i / 20 * j / 20));
}
}
sf::Texture texture;
texture.loadFromImage(img);
texture.setRepeated(true);
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect({ 0, 0, 800, 600 });
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
window.close();
}
}
window.clear();
window.draw(sprite);
window.display();
}
return EXIT_SUCCESS;
}