All my sprites are stuck in the upper left corner? - sprite

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:

Related

define dynamic array inside a struct without causing a segmentation fault

I'm new to c++ and I have to work with dynamic arrays:| I need to define a few dynamic arrays inside my header file and access them from main. The problem is that when I'm defining the arrays inside the structs, I get segmentation faults and don't know how to fix them.
Below is my header file.
I'm aware that there are lots of problems with my code and I could use your help. I'm really stuck here.
Thanks in advance.
I expect this code to work fine with dynamic arrays just like it does with vectors. But it's not.
`
#pragma once
#include <iostream>
#include <functional>
#include <algorithm>
#define children_link_Size 149
#define row 15
#define col 100
using namespace std;
int itemListIndex = 0;
int freqIdx = 0;
int childIdx = 0;
int linkIdx = 0;
namespace std {
template <typename T> T* begin(std::pair<T*, T*> const& p)
{
return p.first;
}
template <typename T> T* end(std::pair<T*, T*> const& p)
{
return p.second;
}
}
struct Node
{
int itemValue{};
int order{ 0 };
int freq{ 0 };
Node* parent{ nullptr };
Node* children{};
Node* links{};
Node() {
children = new Node[children_link_Size];
links = new Node[children_link_Size];
}
explicit Node(int const& p_value, int p_order = 0) :itemValue(p_value), order(p_order)
{
++freq;
cout << " + " << itemValue << " (" << order << ")" << endl;
}
bool operator ==(Node const& p_node) const
{
return itemValue == p_node.itemValue;
}
~Node() {
delete[] children;
delete[] links;
}
};
/*struct mySet {
Node* OrderedItems;
mySet()
{
OrderedItems = new Node[uniqueSize];
}
void insert(Node item)
{
for (int i = 0; i < uniqueSize; i++)
{
for (int j = 0; j < i; j++)
{
if (item == OrderedItems[j])
{
break;
}
else
{
OrderedItems[i] = item;
}
}
}
}
~mySet()
{
delete[] OrderedItems;
}
};*/
struct ItemSupport
{
explicit ItemSupport(int p_minSup) { ItemSupport::minSup = p_minSup; }
Node* Itemset = new (nothrow) Node[row];
Node* OrderedItems = new (nothrow) Node[row];
ItemSupport& operator<<(int const& p_itemValue)
{
static int order = 0;
auto inode = find_if(Itemset, Itemset + row, [&p_itemValue](Node const& p_node)
{
return p_node.itemValue == p_itemValue;
});
if (inode == Itemset + row)
{
Node node(p_itemValue, order);
Itemset[itemListIndex] = node;
itemListIndex++;
++order;
}
else
{
auto& node = (*inode);
++node.freq;
}
return *this;
}
friend ostream& operator<<(ostream& p_os, ItemSupport const& p_itemSupport)
{
ItemSupport* NoDe = {0};
if (NoDe)
{
NoDe->OrderedItems = p_itemSupport.getFrequentItems();
for (Node node : std::make_pair(NoDe->OrderedItems, NoDe->OrderedItems + row))
{
p_os << node.itemValue << ": support " << node.freq << ", order " << node.order << endl;
}
return p_os;
}
}
Node* getItem(int const& p_itemValue)
{
auto inode = find_if(Itemset, Itemset + row, [&p_itemValue](Node const& p_node)
{
return p_node.itemValue == p_itemValue;
});
if (inode != Itemset + row)
{
Node* node = const_cast<Node*>(&(*inode));
return node;
}
return nullptr;
}
static int getMinSup()
{
return minSup;
}
static int minSup;
private:
Node* getFrequentItems() const
{
int j = 0;
for (int i = 0; i < row; i++)
{
if (Itemset[i].freq >= minSup)
OrderedItems[j++] = Itemset[i];
}
return OrderedItems;
}
Node* getUnfrequentItems() const
{
int j = 0;
for (int i = 0; i < row; i++)
{
if (Itemset[i].freq <= minSup)
OrderedItems[j++] = Itemset[i];
}
return OrderedItems;
}
/*~ItemSupport() {
//delete[] Itemset;
//delete[] OrderedItems;
}*/
};
int ItemSupport::minSup = 0;
struct FP_Tree
{
explicit FP_Tree(ItemSupport& p_itemSupport, const int& p_rootValue = int()) :_headItemSupport(p_itemSupport)
{
_root = new Node(p_rootValue);
}
//void construct(Transaction const& p_itemValues)
void construct(int *p_itemValues)
{
// A. Order items into transaction
ItemSupport* ordered = {0};
for (int const& itemValue : std::make_pair(p_itemValues, p_itemValues + row))
{
Node* pNode = _headItemSupport.getItem(itemValue);
if (pNode && pNode->freq >= ItemSupport::getMinSup())
{
if (ordered)
{
ordered->OrderedItems[freqIdx] = *pNode;
freqIdx++;
}
}
}
// B. Create FP_TREE
Node* actualNode = _root;
bool here = true;
string tab;
if (ordered)
{
for (Node const& node : std::make_pair(ordered->OrderedItems, ordered->OrderedItems + row))
{
tab += "\t-";
auto it = actualNode->children;
if (here)
{
auto it = find_if(actualNode->children,
actualNode->children + children_link_Size,
[&node](Node const& nodeTmp) {
return node == (nodeTmp);
});
here &= it != actualNode->children + children_link_Size;
}
if (here)
{
actualNode = it;
++actualNode->freq;
}
else
{
Node* pNode = new Node(node.itemValue);
actualNode->children[childIdx++] = *pNode;
pNode->parent = actualNode;
Node* pNodeHead = _headItemSupport.getItem(node.itemValue);
pNodeHead->links[linkIdx++] = *pNode;
actualNode = pNode;
delete pNode;
}
//cout << tab << actualNode->_itemValue << "(" << actualNode->_freq << ")" << endl;
}
}
//cout << endl;
}
ItemSupport& headItemSupport() const
{
return _headItemSupport;
}
public:
Node* root() const
{
return _root;
}
private:
ItemSupport& _headItemSupport;
Node* _root;
};
`
I expect this code to work fine with dynamic arrays just like it does with vectors
Since you are using C++, do use std::vector -- it will save you a lot of trouble and there is no reason not to.

Incorrect checksum for freed object in c++/sfml application

I am trying to create a multiplayer game where players can use voice chat to communicate.
I am using C++ and SFML-3.0 for everything.
Here is the GitHub page for the whole project: https://github.com/iwannabespace/test
First of all, here are some of the classes that I am using:
AudioCapturer.hpp
class AudioCapturer : public sf::SoundStream
{
public:
AudioCapturer(Client& client);
void receiveLoop(sf::Packet& packet);
private:
bool onGetData(sf::SoundStream::Chunk& data) override;
void onSeek(sf::Time timeOffset) override;
private:
std::recursive_mutex mutex;
std::vector<std::int16_t> samples;
std::vector<std::int16_t> tempbuffer;
size_t offset;
Client& client;
};
AudioCapturer.cpp
AudioCapturer::AudioCapturer(Client& client)
: offset(0), client(client)
{
initialize(1, 44100);
}
bool AudioCapturer::onGetData(sf::SoundStream::Chunk& data)
{
while (offset >= samples.size())
sf::sleep(sf::milliseconds(10));
{
std::scoped_lock lock(mutex);
tempbuffer.assign(samples.begin() + static_cast<std::vector<std::int64_t>::difference_type>(offset),
samples.end());
std::cout << "Tempbuffer address: " << &tempbuffer << std::endl;
}
data.samples = tempbuffer.data();
data.sampleCount = tempbuffer.size();
offset += tempbuffer.size();
return true;
}
void AudioCapturer::onSeek(sf::Time timeOffset)
{
offset = static_cast<std::size_t>(timeOffset.asMilliseconds()) * getSampleRate() * getChannelCount() / 1000;
}
void AudioCapturer::receiveLoop(sf::Packet& packet)
{
while (true)
{
if (client.receivedAudio)
{
sf::Packet copy = packet;
std::uint8_t command;
if (copy >> command)
{
std::size_t sampleCount = (copy.getDataSize() - 1) / sizeof(std::int16_t);
{
std::scoped_lock lock(mutex);
std::size_t oldSize = samples.size();
samples.resize(oldSize + sampleCount);
std::cout << "Samples address: " << &samples << std::endl;
std::cout << "Last item address: " << &samples[oldSize] << std::endl;
std::memcpy(&(samples[oldSize]),
static_cast<const char*>(copy.getData()) + 1,
sampleCount * sizeof(std::int16_t));
}
client.receivedAudio = false;
}
}
}
}
Client.hpp
class Client
{
public:
Client(const sf::IpAddress& ip, int port);
~Client();
bool connect();
void disconnect();
bool send(sf::Packet& packet);
bool receivePacket(sf::Packet& packet, std::unordered_map<std::uint32_t, Player>& players, std::uint32_t& thisPlayer);
public:
bool receivedAudio;
bool receivedPosition;
private:
int port;
sf::IpAddress ip;
sf::TcpSocket socket;
};
Client.cpp
Client::Client(const sf::IpAddress& ip, int port)
: ip(ip), port(port), receivedAudio(false), receivedPosition(false)
{
}
Client::~Client()
{
}
bool Client::connect()
{
if (socket.connect(ip, port) != sf::Socket::Done)
return false;
return true;
}
void Client::disconnect()
{
socket.disconnect();
}
bool Client::send(sf::Packet& packet)
{
if (socket.send(packet) != sf::Socket::Done)
return false;
return true;
}
bool Client::receivePacket(sf::Packet& packet, std::unordered_map<std::uint32_t, Player>& players, std::uint32_t& thisPlayer)
{
sf::Packet recv;
sf::Packet copy;
while (true)
{
if (socket.receive(recv) != sf::Socket::Done)
return false;
if (receivedAudio)
std::cout << "Data is not used!" << std::endl;
std::uint8_t command;
std::uint32_t id;
copy = recv;
if (copy >> command)
{
switch (command)
{
case ServerCommand::ADD_PLAYER:
copy >> id;
if (thisPlayer == 0)
{
thisPlayer = id;
std::cout << "My id is " << thisPlayer << std::endl;
}
players[id] = Player(5.f, id);
std::cout << "Player joined!" << std::endl;
break;
case ServerCommand::ADD_PLAYERS:
while (copy >> id)
players[id] = Player(5.f, id);
break;
case ServerCommand::RECEIVE_AUDIO:
receivedAudio = true;
packet = recv;
break;
case ServerCommand::RECEIVE_POSITION:
receivedPosition = true;
packet = recv;
break;
default:
break;
}
}
}
return true;
}
AudioRecorder.hpp
class AudioRecorder : public sf::SoundRecorder
{
public:
AudioRecorder(Client& client);
~AudioRecorder() override;
void activeness();
void setActive(bool active);
bool isActive() const;
private:
bool onStart() override;
bool onProcessSamples(const std::int16_t* samples, std::size_t sampleCount) override;
void onStop() override;
private:
Client& client;
bool active;
std::mutex mutex;
};
AudioRecorder.cpp
AudioRecorder::AudioRecorder(Client& client)
: client(client), active(false)
{
}
AudioRecorder::~AudioRecorder()
{
stop();
}
void AudioRecorder::activeness()
{
while (true)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && !active)
{
std::scoped_lock lock(mutex);
active = true;
if (start()) {}
}
if (!sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && active)
{
std::scoped_lock lock(mutex);
stop();
active = false;
}
}
}
void AudioRecorder::setActive(bool active)
{
this->active = active;
}
bool AudioRecorder::isActive() const
{
return active;
}
bool AudioRecorder::onStart()
{
std::cout << "Started!" << std::endl;
return true;
}
bool AudioRecorder::onProcessSamples(const std::int16_t* samples, std::size_t sampleCount)
{
sf::Packet packet;
packet << ServerCommand::RECEIVE_AUDIO;
packet.append(samples, sampleCount * sizeof(std::int16_t));
return client.send(packet);
}
void AudioRecorder::onStop()
{
std::cout << "Stopped!" << std::endl;
}
main.cpp
int main()
{
std::srand(std::time(0));
Client client("127.0.0.1", 4242);
if (client.connect())
{
std::cout << "Connected to server!" << std::endl;
sf::RenderWindow window(sf::VideoMode({ 1280, 720 }), "Multiplayer Game", sf::Style::Default);
window.setVerticalSyncEnabled(true);
sf::View view;
view.setCenter({ 640, 360 });
view.setSize(sf::Vector2f(window.getSize()));
sf::Packet packet;
std::unordered_map<std::uint32_t, Player> players;
std::uint32_t thisPlayer = 0;
StartScreen startscreen(window, sf::Color(172, 192, 146));
AudioRecorder recorder(client);
AudioCapturer capturer(client);
capturer.play();
std::thread receivePacket;
std::thread receiverloop;
std::thread activeness;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::Resized:
if (startscreen)
{
view.setCenter({
static_cast<float>(window.getSize().x) / 2,
static_cast<float>(window.getSize().y) / 2
});
view.setSize(sf::Vector2f(window.getSize()));
startscreen.updateOnResize();
}
break;
}
}
if (!receivePacket.joinable())
receivePacket = std::thread(&Client::receivePacket, std::ref(client), std::ref(packet), std::ref(players), std::ref(thisPlayer));
if (!receiverloop.joinable())
receiverloop = std::thread(&AudioCapturer::receiveLoop, std::ref(capturer), std::ref(packet));
if (!activeness.joinable())
activeness = std::thread(&AudioRecorder::activeness, std::ref(recorder));
if (client.receivedPosition)
{
sf::Packet copy = packet;
std::uint8_t command;
if (copy >> command)
{
float x, y;
std::uint32_t id;
copy >> id >> x >> y;
for (auto& player : players)
if (player.first == id)
player.second.setPosition({ x, y });
client.receivedPosition = false;
}
}
if (window.hasFocus())
players[thisPlayer].move(client);
window.clear(sf::Color::White);
window.setView(view);
for (const auto& player : players)
window.draw(player.second);
window.display();
}
client.disconnect();
std::terminate();
}
return 0;
}
I know it's a lot of code and I am sorry that I have to share too much.
I believe the problem is with the AudioCapturer class. For some reason when sending audio data, after a while client that receives it stops the execution and prompts this problem with different addresses:
a.out(60911,0x16b47b000) malloc: Incorrect checksum for freed object 0x12a80a400: probably modified after being freed.
Corrupt value: 0xe7026101a000bcff
By the way I am kind of using the SFML's VoIP example for the AudioCapturer class.
This is the Github page of it: https://github.com/SFML/SFML/blob/master/examples/voip/Server.cpp
I'd appreciate it If someone can help me with that problem.

pthread_create does not work when a pointer to an object is given as an argument

I don't understand why CLion IDE underlines "pthread_create" and "pthread_join" in red and says "No matching function for call to...". I used a similar code without using the pointer to an object passed to the thread as an argument and it worked.
#include <iostream>
#include <pthread.h>
#define NUM_THREADS 4
using namespace std;
class Animal {
private:
float x, y;
public:
Animal(float x, float y) {
this->x = x;
this->y = y;
}
void print() {
cout<< x << "," << y << endl;
}
};
void *function(Animal *p) {
Animal animal = *p;
animal.print();
}
int main() {
pthread_t thread[NUM_THREADS];
Animal dog[] = {Animal(2, 3), Animal(-1, 2), Animal(5, 2), Animal(5, 10)};
for(int i = 0; i<NUM_THREADS; i++) {
pthread_create(&thread[i], NULL, function, &dog[i]);
}
for(int i = 0; i<NUM_THREADS; i++) {
pthread_join(thread[i]);
}
return 0;
}
I changed the argument of the childThread function from Animal to void *
void *childThread(void *p) {
Animal *animal = (Animal *)p;
animal->print();
}
And added a second argument NULL to pthread_join
pthread_join(thread, NULL)
and now it works

'player' : unknown override specifier

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;
};

Qt MainWindow is not updating

I am using Qt to generate a Window. Additionally I use libnfc to get access to a nfc reader, so far so good.
In my self written nfc-class i generate a new thread, this thread is polling for new tags on the reader. If there is a new tag, the thread will start a signal event for the MainWindow.
In the main window I have just a QWebView which will show different websites on different states (after start, new tag, tag removed), just realy basic stuff.
My problem is now: that the main window (or the QWebView) is not updating. If i switch to another programm and go back to my app, the window will be updated. I was already searching with google and trying different stuff but nothing helps.
Here the thread code:
class NFC_Thread : public QThread
{
Q_OBJECT
public:
NFC_Thread(NFC_Reader * Reader);
void run();
signals:
void NewTarget(nfc_target Target);
void TargetRemoved(nfc_target Target);
private:
int mError;
bool mStopPolling;
};
void NFC_Thread::run()
{
mError = 0;
mStopPolling = false;
while(!mStopPolling)
{
nfc_target Target;
mError = nfc_initiator_poll_target(mReader->GetDevice(), nmModulations, szModulations, mPollNr, mPollPeriod, &Target);
if(mError > 0)
{
cout << "NFC: found target" << endl;
}
#warning Bug in driver: Timeout generate a NFC_EIO Error, 'https://code.google.com/p/libnfc/issues/detail?id=224'
else if(mError > 0)
{
cout << "NFC: Error" << endl;
mStopPolling = true;
}
else
{
cout << "NFC: no target found" << endl;
}
}
}
MainWindow Code:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void SetNewTarget(nfc_target Target);
void doTargetRemoved(nfc_target Target);
private:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *);
void adjust();
Ui::MainWindow *ui;
QWebView * mWebView;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mWebView = new QWebView(this);
mWebView->load(QUrl("http://www.pbuchegger.at/"));
mWebView->show();
}
void MainWindow::SetNewTarget(nfc_target Target)
{
QString str = "NEW TARGET: \n";
{
char * s;
str_nfc_target(&s, Target, false);
str += s;
delete s;
}
//cout << "NFC: Target: " << str << endl;
mWebView->load(QUrl("http://www.google.at"));
update();
repaint();
mWebView->update();
qApp->processEvents();
/*QMessageBox msgBox;
msgBox.setText(str);
msgBox.exec();*/
}
void MainWindow::doTargetRemoved(nfc_target Target)
{
QString str = "TARGET REMOVED: \n";
{
char * s;
str_nfc_target(&s, Target, false);
str += s;
delete s;
}
//cout << "NFC: Target: " << str << endl;
mWebView->load(QUrl("http://www.cde.at"));
update();
repaint();
mWebView->update();
qApp->processEvents();
/*QMessageBox msgBox;
msgBox.setText(str);
msgBox.exec();*/
}
bool MainWindow::event(QEvent *event)
{
if(event->type() == QEvent::Resize)
{
adjust();
return true;
}
return false;
}
void MainWindow::resizeEvent(QResizeEvent *)
{
adjust();
}
void MainWindow::adjust()
{
mWebView->setGeometry(0, 0, ui->centralWidget->geometry().width(), ui->centralWidget->geometry().height());
}
main code:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qRegisterMetaType<nfc_target>("nfc_target");
MainWindow w;
w.setWindowState(Qt::WindowMaximized);
NFC_Reader Reader;
nfc_device_string devs;
size_t nr;
QString str = "";
Reader.GetDevices(devs, nr);
if(nr > 0)
{
if(!Reader.InitReader(NULL))
{
str += "Error on init!";
}
else
{
Reader.Start_Polling();
str += "Started Polling!";
}
}
else
{
str += "No Device found!";
}
w.SetText(str);
SignalHelper Helper;
QObject::connect(Reader.GetThread(), SIGNAL(NewTarget(nfc_target)), &Helper, SLOT(doNewTarget(nfc_target)));
QObject::connect(Reader.GetThread(), SIGNAL(TargetRemoved(nfc_target)), &Helper, SLOT(doTargetRemoved(nfc_target)));
QObject::connect(&Helper, SIGNAL(NewTarget(nfc_target)), &w, SLOT(SetNewTarget(nfc_target)));
QObject::connect(&Helper, SIGNAL(TargetRemoved(nfc_target)), &w, SLOT(doTargetRemoved(nfc_target)));
w.show();
int ret = a.exec();
Reader.Abort_Polling();
return ret;
}
As u can see, I have a "Helper" class, this class is just getting the signal in a slot and starting again a signal which will be forward to the mainwindow. If i want to forward the signal directly to the mainwindow, nothing is happening (like the signal is not fired), but i was checking it with the Qt-About box, and the box is showing up.
Helper class:
class SignalHelper : public QObject
{
Q_OBJECT
public slots:
void doNewTarget(nfc_target Target);
void doTargetRemoved(nfc_target Target);
signals:
void NewTarget(nfc_target Target);
void TargetRemoved(nfc_target Target);
};
void SignalHelper::doNewTarget(nfc_target Target)
{
emit NewTarget(Target);
}
void SignalHelper::doTargetRemoved(nfc_target Target)
{
emit TargetRemoved(Target);
}
no compiler errors or linker errors. this code shows just the important stuff, all the unimportant stuff is removed. just for your information the project file:
QT += core gui testlib
QT += webkit
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
TARGET = NFC_GUI
TEMPLATE = app
SOURCES += main.cpp \
mainwindow.cpp \
nfc_thread.cpp \
nfc_reader.cpp \
signal_helper.cpp
HEADERS += mainwindow.h nfc_thread.h nfc_reader.h signal_helper.h
FORMS += mainwindow.ui
LIBS += -lnfc
Making my comment an answer:
Your function
bool MainWindow::event(QEvent *event)
{
if(event->type() == QEvent::Resize)
{
adjust();
return true;
}
return false;
}
eats any event which is handled in QMainWindow except for QEvent::Resize. You need to call the default behaviour for events you are not interested in:
bool MainWindow::event(QEvent *event)
{
if(event->type() == QEvent::Resize)
{
adjust();
return true;
}
// call the parent implementation
return QMainWindow::event(event);
}
Note you can also just simply implement QWidget::resizeEvent:
void MainWindow::resizeEvent(QResizeEvent *event)
{
adjust();
QMainWindow::resizeEvent(event);
}
If you're calling slots from signals between different threads, you need to make the connect calls with Qt::QueuedConnection as the Connection Type.

Resources