I have simple code:
#include <SFML\Graphics.hpp>
sf::RenderWindow *mainWindow;
void changeMainWindowParameters()
{
while(mainWindow->isOpen())
{
sf::Event event;
while (mainWindow->pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
mainWindow->close();
return;
}
}
mainWindow->clear();
mainWindow->draw(sf::CircleShape(50.0F, 30));
mainWindow->display();
}
}
int main()
{
mainWindow = new sf::RenderWindow(
sf::VideoMode(100, 100), "Window");
changeMainWindowParameters();
}
But if I want to do it with threads, it does not work as in previous example:
#include <SFML\Graphics.hpp>
sf::RenderWindow *mainWindow;
void changeMainWindowParameters()
{
while(mainWindow->isOpen())
{
sf::Event event;
while (mainWindow->pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
mainWindow->close();
return;
}
}
mainWindow->clear();
mainWindow->draw(sf::CircleShape(50.0F, 30));
mainWindow->display();
}
}
int main()
{
mainWindow = new sf::RenderWindow(
sf::VideoMode(100, 100), "Window");
sf::Thread th(changeMainWindowParameters);
th.launch();
//code
th.wait();
}
I can't close the window/move it etc.
I want the program to do something (drawing images on this window etc.) and so I could close/move this window.
Where is wrong?
I solve this problem:
#include <SFML\Graphics.hpp>
#include <thread>
#include <iostream>
sf::RenderWindow *mainWindow = nullptr;
void changeMainWindowParameters()
{
if (mainWindow == nullptr)
mainWindow = new sf::RenderWindow(sf::VideoMode(100, 100), "Window");
while(mainWindow->isOpen())
{
sf::Event event;
while (mainWindow->pollEvent(event))
{
if(event.type == sf::Event::Closed)
{
mainWindow->close();
return;
}
}
mainWindow->clear();
mainWindow->draw(sf::CircleShape(50.0F, 30));
mainWindow->display();
}
}
int main()
{
sf::Thread th(changeMainWindowParameters);
th.launch();
for(;;)
std::cout << '.';
th.wait();
}
We must remember that the event loop (more precisely, the pollEvent or waitEvent function) must be called in the same thread that created the window.
Related
When I call sprite.getPosition() on my sprites I can clearly see that each of them has a different position, but when I draw my sprites every single one of them renders on top of each other?
Here is the full source code thus far:
(I was planning to just pick out the relevant bits, but after 5 minutes of trimming I realized I'd be including 95% of it anyway, so it ends up shorter if I just don't trim it at all)
#include <array>
#include <cassert>
#include <iostream>
#include <vector>
#include <SFML/Graphics.hpp>
sf::Texture spritesheet{};
namespace TextureRects {
std::array<std::array<sf::IntRect,2>, 3> aliens{{
{sf::IntRect{0,0,12,8}, sf::IntRect{36,0,12,8}},
{sf::IntRect{12,0,12,8}, sf::IntRect{48,0,12,8}},
{sf::IntRect{24,0,12,8}, sf::IntRect{60,0,12,8}}
}};
}
class Alien {
public:
enum class Type {
one,
two,
three,
max
};
private:
enum class AnimationState {
in,
out
};
sf::Vector2f m_position{};
Type m_type{};
sf::Sprite m_sprite{};
bool m_alive{ true };
sf::IntRect getTextureRect(AnimationState animationState) const {
return TextureRects::aliens[static_cast<std::size_t>(m_type)][static_cast<std::size_t>(animationState)];
}
void swapTexture() {
static AnimationState s_animationState{ AnimationState::in };
m_sprite.setTextureRect(getTextureRect(s_animationState));
s_animationState = static_cast<AnimationState>(!static_cast<bool>(s_animationState));// in -> out, out -> in
}
void initializeTexture() {
m_sprite.setTexture(spritesheet);
swapTexture();
}
public:
Alien() = default;
Alien(Type type) : m_type{ type } {
initializeTexture();
}
void setPosition(sf::Vector2f position) {
m_sprite.setPosition(position);
m_position = position;
std::cout << m_sprite.getPosition().x << "\n";
std::cout << m_sprite.getPosition().y << "\n";
}
void draw(sf::RenderWindow& window) const{
if (m_alive) {
window.draw(m_sprite);
}
}
void reset() {
m_alive = true;
}
};
class Swarm {
std::vector<Alien> m_aliens{};
void init() {
m_aliens.resize(55);
for (int y{ 0 }; y < 5; ++y) {
for (int x{ 0 }; x < 11; ++x) {
if (y == 0) {
m_aliens.push_back(Alien{ Alien::Type::three });
} else if (y < 3) {
m_aliens.push_back(Alien{ Alien::Type::two });
}else {
m_aliens.push_back(Alien{ Alien::Type::one });
}
}
}
reset();
}
public:
Swarm() {
init();
};
void reset() {
for (std::size_t y{ 0 }; y < 5;++y) {
for (std::size_t x{ 0 }; x < 11;++x) {
auto& alien{ m_aliens[y * 11 + x] };
alien.setPosition({ x * 20.0f, y * 20.0f });
alien.reset();
}
}
}
void draw(sf::RenderWindow& window) const{
for (const auto& alien : m_aliens) {
alien.draw(window);
}
}
};
int main() {
spritesheet.loadFromFile("spritesheet.png");
sf::RenderWindow window{sf::VideoMode{448, 512}, "Space Invaders"};// 224x256 * 2x2.5
sf::View view1{ sf::FloatRect{0,0,224,256} };
window.setView(view1);
Swarm swarm{};
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
}
}
window.clear();
swarm.draw(window);
window.display();
}
return 0;
}
Notice that the std::cout << m_sprite.getPosition().x << "\n"; and std::cout << m_sprite.getPosition().y << "\n"; lines print out unique positions for each sprite, yet the output shows every sprite crammed into the upper left corner...
(I know the spritesheet won't load, hopefully it doesn't need to in order for the stack of white squares to be obvious.)
Here's a screenshot of the output in case it saves someone some time:
Why isn't my code working??? What does this error mean? FYI: I wanted to create a top down shooter game. all my code was basically just copied from different sources(some I just solved on my own).
I intended to put the player class in the game loop or game class. here's the code:
game.cpp
#include "Player.h"
//Private Functions
void game::intVariables()
{
this->window = nullptr;
this->points = 0;
this->enemySpawnTimerMax = 1000.f;
this->enemySpawnTimer = this->enemySpawnTimerMax;
this->maxEnemies = 8;
}
void game::intWindow()
{
this->videoMode.height = 1080;
this->videoMode.width = 1780;
this->window = new sf::RenderWindow(this->videoMode, "Top Down Shooter", sf::Style::Close | sf::Style::Titlebar);
this->window->setFramerateLimit(60);
this->window->setKeyRepeatEnabled(true);
Player player("player.png");
}
void game::intEnemies()
{
this->enemy.setPosition(30.f, 30.f);
this->enemy.setSize(sf::Vector2f(50.f, 50.f));
this->enemy.setFillColor(sf::Color(0, 128, 128));
this->enemy.setOutlineColor(sf::Color::Black);
this->enemy.setOutlineThickness(-4.f);
}
//Constructors or Destructors
game::game()
{
this->intVariables();
this->intWindow();
this->intEnemies();
}
//prevents memory leak
game::~game()
{
delete this->window;
}
//Accessors
const bool game::running() const
{
return this->window->isOpen();
}
//functions
void game::player1()
{
player.drawPlayer(*this->window);
}
void game::spawnEnemy()
{
/*
#return void
Spawns enemies and sets their color and positions.
- select random position
- select random color
- add enemy to vector
*/
this->enemy.setPosition(
static_cast<float>(rand() % static_cast<int>(this->window->getSize().x - this->enemy.getSize().x)),
static_cast<float>(rand() % static_cast<int>(this->window->getSize().y - this->enemy.getSize().y))
);
this->enemy.setFillColor(sf::Color(0, 128, 128));
//spawns the enemy
this->enemies.push_back(this->enemy);
}
void game::pollEvents()
{
//event polling
while (this->window->pollEvent(this->evnt))
{
switch (this->evnt.type)
{
case sf::Event::Closed:
this->window->close();
break;
case sf::Event::KeyPressed:
if (this->evnt.key.code == sf::Keyboard::Escape)
this->window->close();
break;
}
}
}
void game::updateEnemies()
{
/*
#return void
updates the enemy spawn timer and spawns enemies
when the total amount of enemies is smaller than the maximum.
removes the enemies at the edge of the screen. //to do
*/
//Updating the timer for enemy spawning
if (this->enemies.size() < this->maxEnemies)
{
if (this->enemySpawnTimer >= this->enemySpawnTimerMax)
{
//spawn the enemy and reset the timer
this->spawnEnemy();
this->enemySpawnTimer = 0.f;
}
else
this->enemySpawnTimer += 1.f;
}
// Move the enemies
for (auto &e : this->enemies)
{
e.move(0.f, 1.f);
}
}
void game::update()
{
this->pollEvents();
this->updateMousePositions();
this->updateEnemies();
}
void game::renderEnemies()
{
for (auto &e : this->enemies)
{
this->window->draw(e);
}
}
void game::render()
{
/*
- clears old frame
- renders objects
- display frames on window
renders game objects.
*/
this->window->clear(sf::Color(128, 128, 128));
//draw game objects
this->renderEnemies();
this->player1();
this->window->display();
}
void game::updateMousePositions()
{
/*
#return void
updates the mouse position
*mouse postion relative to window (vector2i)*
*/
this->mousePosWindow = sf::Mouse::getPosition(*this->window);
}
game.h
#include <iostream>
#include <vector>
#include <ctime>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>
/* class acts as the game engine
wrapper class.
*/
class game
{
protected:
//variables
//window
sf::RenderWindow* window;
sf::VideoMode videoMode;
sf::Event evnt;
//mouse positions
sf::Vector2i mousePosWindow;
//game logic
int points;
float enemySpawnTimer;
float enemySpawnTimerMax;
int maxEnemies;
//game objects
std::vector<sf::RectangleShape> enemies;
sf::RectangleShape enemy;
Player player;
// Private Functions
void intVariables();
void intWindow();
void intEnemies();
public:
// Constructors or Destructors
game();
virtual ~game();
// Accessors
const bool running() const;
// Functions
void player1();
void spawnEnemy();
void pollEvents();
void updateEnemies();
void update();
void renderEnemies();
void render();
void updateMousePositions();
};
Player.h
#include <iostream>
#include <SFML/Graphics.hpp>
#include "game.h"
class Player
{
public:
Player() {
//default
}
Player(std::string imgDirectory) {
if (!playerTexture.loadFromFile(imgDirectory)) {
std::cerr << "Error\n";
}
playerSprite.setTexture(playerTexture);
}
void drawPlayer(sf::RenderWindow& window) {
window.draw(playerSprite);
}
void movePlayer(char direction, float moveSpeed) {
if (direction == 'u')
{
playerSprite.move(0, -moveSpeed);
}
else if (direction == 'd')
{
playerSprite.move(0, -moveSpeed);
}
else if (direction == 'l')
{
playerSprite.move(-moveSpeed, 0);
}
else if (direction == 'r')
{
playerSprite.move(moveSpeed, 0);
}
}
private:
sf::Texture playerTexture;
sf::Sprite playerSprite;
};
Thank you to see:When Dialog has hide, the QPixmap is empty,why???
and This way is too inefficient...help me
、、、
#include "webKitDialog.h"
#include "ui_webKitDialog.h"
#include <QWebEngineView>
#include <QWebEnginePage>
#include "HiWebEnginePage.h"
#include <QTimer>
#include <QThread>
#include <QScreen>
#include <QGuiApplication>
#include <QPixmap>
webKitDialog::webKitDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::webKitDialog)
{
ui->setupUi(this);
m_view = new QWebEngineView(this);
m_page = new HiWebEnginePage(m_view);
m_view->setPage(m_page);
ui->lineEdit->setText("http://www.youku.com");
ui->verticalLayout->addWidget(m_view, 1);
on_lineEdit_editingFinished();
QTimer *time = new QTimer;
connect(time, &QTimer::timeout, this, &webKitDialog::onTimeOut);
//
time->start(1000);
}
webKitDialog::~webKitDialog()
{
delete ui;
}
void webKitDialog::showEvent(QShowEvent *event)
{
m_view->reload();
m_view->show();
QDialog::showEvent(event);
}
void webKitDialog::onTimeOut()
{
emit onImageUpdate(createThumbnail(m_view->size()));
}
void webKitDialog::on_pushButton_close_clicked()
{
this->hide();
m_view->showNormal();
}
void webKitDialog::on_pushButton_max_clicked()
{
qreal factor = m_view->zoomFactor();
factor += 0.25;
if(factor > 5)
{
factor = 5;
}
m_page->setZoomFactor(factor);
}
void webKitDialog::on_pushButton_refresh_clicked()
{
m_view->reload();
}
void webKitDialog::on_lineEdit_editingFinished()
{
QString strUrl = ui->lineEdit->text();
m_page->load(QUrl(strUrl));
}
void webKitDialog::on_pushButton_zoonout_clicked()
{
qreal factor = m_view->zoomFactor();
factor -= 0.25;
if(factor < 0.25)
{
factor = 0.25;
}
m_page->setZoomFactor(factor);
}
QPixmap webKitDialog::createThumbnail(const QSize &size)
{
QPixmap pixMap(size);
qDebug() << "size" << size << endl;
QRegion rg(0, 0, size.width(), size.height());
QPainter painter(&pixMap);
m_view->page()->view()->render(&painter, QPoint(), rg);
painter.end();
return pixMap;
}
、、、
I just merely want to emit 2 signal and a Qtimer timeout on button click from a GUI.
Although 2 SIGNAL/SLOT WORKS the QTimer's SIGNAL/SLOT is not working, the whentimeout SLOT never works.
There is no error even.
GUI(DIALOG.CPP)
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
fduthread = new fdustatus(this);
connect(fduthread,SIGNAL(NumberChanged(int)),this,SLOT(onNumberChanged(int)));
connect(fduthread,SIGNAL(nameChange(QString)),this,SLOT(onNameChanged(QString)));
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::onNumberChanged(int number)
{
ui->label->setText(QString::number(number));
}
void Dialog::onNameChanged(QString s)
{
ui->label_2->setText(s);
}
void Dialog::on_pushButton_clicked()
{
fduthread->start();
fduthread->stop=false;
}
void Dialog::on_pushButton_2_clicked()
{
ui->label_2->setText("");
fduthread->stop=true;
}
THAT IS MY THREAD
#include "fdustatus.h"
#include<QMutex>
#include<QTimer>
#include<QDebug>
fdustatus::fdustatus(QObject *parent):QThread(parent)
{
}
void fdustatus::run()
{
mytimer = new QTimer();
mytimer->setInterval(10);
connect( mytimer,SIGNAL(timeout()),this,SLOT(whentimeout()));
mytimer->start();
for(int i =0;i<100;i++)
{
QMutex mutex;
mutex.lock();
if(this->stop)break;
mutex.unlock();
emit NumberChanged(i*10);
emit nameChange(getstring());
this->msleep(100);
}
}
QString fdustatus::getstring()
{
QString networkport;
networkport.append("Alarm Active");
return networkport;
}
void fdustatus::whentimeout()
{
qDebug() << "timer ended from thread..";
}
Having some trouble with SFML (version 2.1).
Trying to create two instances of sf::RenderWindow on two separate threads. Application works for some time (amount of time is not constant) and then eventually will crash due to assertion:
testapp: ../../src/xcb_conn.c:186: write_vec: Assertion `!c->out.queue_len' failed.
Test piece of code:
#include <iostream>
#include <thread>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <X11/Xlib.h>
void WindowOne ()
{
sf::RenderWindow* wnd = new sf::RenderWindow (sf::VideoMode(800,600),
"Window 1");
while (wnd->isOpen())
{
sf::Event event;
while (wnd->pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
wnd->close();
break;
default:
break;
}
}
wnd->clear(sf::Color::White);
wnd->display();
}
delete wnd;
}
void WindowTwo ()
{
sf::RenderWindow* wnd = new sf::RenderWindow (sf::VideoMode(800,600),
"Window 2");
while (wnd->isOpen())
{
sf::Event event;
while (wnd->pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
wnd->close();
break;
default:
break;
}
}
wnd->clear(sf::Color::White);
wnd->display();
}
delete wnd;
}
int main(int argc, char** argv) {
XInitThreads();
std::thread thread1 (WindowOne);
std::thread thread2 (WindowTwo);
thread1.join();
thread2.join();
return 0;
}
Please, help me to find out, what am I doing wrong, or can I even do such things.
Edit:
Forgot to mention that it crashes at:
wnd->display();