QT how to use setPixmap skin.copy() for do an animation? - c++
I want to do a little animation in my application. I have an asteroid and when he travel to the right the animation go to the right, when he go to the left animation go to the left,
the angle is between 0 and 360°.
I have add the tiles for you explain me how to cut it perfectly.
I have in the class an integer who have number bewteen 0 and 34 (asteroids on the image) I decrease -1 or add +1 to this variable at each animation.
The method that animates the asteroid:
void Asteroid::animation(){
int x = 1;
int y = 1;
int width = 5;
int height = 5;
// what should I add here?
if(this->angle >= 0 && this->angle < 180){
// cut image go to the right
setPixmap(this->skin.copy(x,y,width,height));
this->frame++;
if(frame > 34) this->frame = 1;
} else {
// cut image go to the left
setPixmap(this->skin.copy(x,y,width,height));
this->frame--;
if(frame < 1) this->frame = 34;
}
}
The contents of the skin pixmap:
Interface
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QPoint>
#include <QVector>
#include <QPixmap>
#include <QString>
#include <QTimer>
#include <QObject>
#include <time.h>
#include <QtCore/qmath.h>
#include "SettingsAsteroid.h"
class Asteroid : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
// Animation
QPixmap skin;
int frame; // 32 images
// Data
int speed;
int size;
int pv;
float angle;
public:
Asteroid(int size);
Asteroid(QPointF position, int size);
~Asteroid();
int getPosX();
int getPosY();
void setPosX(int newPos);
void setPosY(int newPos);
int getSpeed();
int getSize();
int getPV();
int getAngle();
// météorite détruite
void destroyed();
// toucher par un tir
void touched(int damage);
bool isDestroyed();
private slots:
// mouvement de la météorite
void move();
// animation de la météorite
void animation();
signals:
//void notKilled();
// transmet la taille du météorite détruit
void killed(int);
};
Implementation
#include "Asteroid.h"
Asteroid::Asteroid(int size)
{
this->skin = QPixmap(SettingsAsteroid::getRandomSkin());
this->speed = SettingsAsteroid::getRandomSpeed(4,8);
this->pv = SettingsAsteroid::getPV(size);
this->angle = SettingsAsteroid::getRandomAngle();
this->frame = 1;
// Position de départ random
QPointF position = QPointF(SettingsAsteroid::getRandomStartPosition());
this->setPos(position.x(), position.y());
this->size = size;
// mouvement de l'astéroide
QTimer* timer2 = new QTimer();
connect(timer2,SIGNAL(timeout()),this,SLOT(move()));
timer2->start(this->speed);
// animation de l'astéroide
QTimer* timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(animation()));
timer->start(100);
}
Asteroid::Asteroid(QPointF position, int size)
{
this->skin = QPixmap(SettingsAsteroid::getRandomSkin());
this->speed = SettingsAsteroid::getRandomSpeed(4,8);
this->pv = SettingsAsteroid::getPV(size);
this->angle = SettingsAsteroid::getRandomAngle();
this->frame = 1;
this->setPos(position.x(), position.y());
this->size = size;
QTimer* timer2 = new QTimer();
connect(timer2,SIGNAL(timeout()),this,SLOT(move()));
timer2->start(this->speed);
//Decoupe sprite et anmiation
QTimer* timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(animation()));
timer->start(150);
}
Asteroid::~Asteroid()
{
}
int Asteroid::getPosX(){
return this->pos().x();
}
int Asteroid::getPosY(){
return this->pos().y();
}
void Asteroid::setPosX(int newPos){
this->setPos(newPos, this->pos().y());
}
void Asteroid::setPosY(int newPos){
this->setPos(this->pos().x(), newPos);
}
int Asteroid::getSpeed(){
return this->speed;
}
int Asteroid::getSize(){
return this->size;
}
int Asteroid::getPV(){
return this->pv;
}
int Asteroid::getAngle(){
return this->angle;
}
bool Asteroid::isDestroyed(){
if(pv > 0) return false;
else return true;
}
void Asteroid::destroyed(){
// AVERTIR CLASSE PRINCIPALE QUE DETRUIT
}
void Asteroid::touched(int damage){
this->pv -= damage;
if(pv<=0) destroyed();
}
void Asteroid::move(){
double dx = getSpeed() * qCos(qDegreesToRadians(angle)) ;
double dy = getSpeed() * qSin(qDegreesToRadians(angle)) ;
setPos(QPointF(getPosX() + dx, getPosY() + dy)) ;
// place la météorite de l'autre coté de la scène
if (getPosX()<=0) setPosX(799);
else if (getPosY()<=0) setPosY(659);
else if (getPosX()>= 800) setPosX(1);
else if (getPosY()>= 600) setPosY(1);
}
void Asteroid::animation(){
// what add here?
int x = 1;
int y = 1;
int width = 5;
int height = 5;
if(this->angle >= 0 && this->angle < 180){
// cut image go to the right
setPixmap(this->skin.copy(x,y,width,height));
this->frame++;
if(frame > 34) this->frame = 1;
} else {
// cut image go to the left
setPixmap(this->skin.copy(x,y,width,height));
this->frame--;
if(frame < 1) this->frame = 34;
}
}
The angle is the direction of the Asteroid on the scene. There will be a spaceship who should destroyed the asteroid. I want make the animaton of the Asteroids who move on the scene
Assuming that the asteroid images in the skin are square, you can do as follows.
Your skin has only 32 items, not 34, BTW.
void Asteroid::animation() {
int step = skin.height();
int N = skin.width() / step; // Number of images in the skin.
Q_ASSERT(skin.width() % step == 0); // ensure proper format of the skin
if (angle >= 0 && angle < 180) {
frame ++;
if (frame > N) frame -= N;
} else {
frame --;
if (frame < 1) frame += N;
}
int x = (frame - 1) * step;
setPixmap(skin.copy(x, 0, step, step));
}
Related
SDL2 C++ Snake Game Self Collision
As a school project, I've made the classic snake game using SDL2 and C++. I've already implemented the growing, moving features for the Snake but it was required to make the movement based on a grid, but when I implemented the grid feature, the self-collision was always triggering whenever grow one part, so every time I start the game, and eat the first fruit, the snake dies. I've been trying for a while now, from placing a delay to the adding of the tail and delaying the collision check, but to no avail, it's always colliding with itself even though it is not. I can't see what is wrong with the self collision, I would gladly appreciate it if someone can point out what's wrong. Snake.h #include "GameObject.h" #include "common.h" #include "draw.h" #include "Food.h" #include "util.h" #include <vector> struct Segment { int x; int y; Segment(int posx, int posy) { x = posx; y = posy; } }; class Snake : public GameObject { public: ~Snake(); void start(); void update(); void draw(); void outOfBoundsCheck(); void move(); void addSegment(int x, int y); void selfCollisionCheck(bool hasEaten); void setHasMoved(bool a); void setIsAlive(bool a); int getX(); int getY(); int getWidth(); int getHeight(); bool getIsAlive(); bool getHasMoved(); std::vector<Segment*> const& getV() const; private: std::vector<Segment*> body; SDL_Texture* headTexture; SDL_Texture* bodyTexture; int x; int y; int width; int height; int dx; int dy; int tempX; int tempY; bool isAlive; bool hasMoved; }; Snake.cpp Snake::~Snake() { } void Snake::start() { // Load Texture headTexture = loadTexture("gfx/player.png"); bodyTexture = loadTexture("gfx/body.png"); tempX = 0; tempY = 0; x = 0; y = 0; dx = 0; dy = 0; isAlive = true; hasMoved = false; width = 0; height = 0; SDL_QueryTexture(headTexture, NULL, NULL, &width, &height); addSegment(x, y); } void Snake::update() { std::cout << "Head" << body[0]->x << std::endl; if (body.size() > 1) { std::cout << "2nd Segment" << body[1]->x << std::endl; if (body.size() > 2) { std::cout << "3nd Segment" << body[2]->x << std::endl; } } move(); outOfBoundsCheck(); } void Snake::draw() { if (!isAlive) return; // Cancel the render if player dies for (int i = 0; i < body.size(); i++) { blit(headTexture, body[i]->x, body[i]->y); } } void Snake::outOfBoundsCheck() { for (int i = 0; i < body.size(); i++) { if (body[i]->x > SCREEN_WIDTH) { body[i]->x = 0; } if (body[i]->x < 0) { body[i]->x = SCREEN_WIDTH; } if (body[i]->y > SCREEN_HEIGHT) { body[i]->y = 0; } if (body[i]->y < 0) { body[i]->y = SCREEN_HEIGHT; } } } void Snake::move() { if (app.keyboard[SDL_SCANCODE_W] && dy != 5) { dx = 0; dy = -5; } if (app.keyboard[SDL_SCANCODE_A] && dx != 5) { dx = -5; dy = 0; } if (app.keyboard[SDL_SCANCODE_S] && dy != -5) { dx = 0; dy = 5; } if (app.keyboard[SDL_SCANCODE_D] && dx != -5) { dx = 5; dy = 0; } Segment* snakeHead = *(body.begin()); //Grid tempX += dx; tempY += dy; if (tempX % 25 == 0) { snakeHead->x += tempX; tempX = 0; } if (tempY % 25 == 0) { snakeHead->y += tempY; tempY = 0; } for (int i = body.size() - 1; i > 0; i--) { //For the other parts to follow body[i]->x = body[i - 1]->x; body[i]->y = body[i - 1]->y; } } void Snake::addSegment(int x, int y) { Segment* seg = new Segment(x, y ); body.push_back(seg); } void Snake::selfCollisionCheck(bool hasEaten) // Fail { Segment* head = body[0]; if (hasEaten == false) { for (int i = 1; i < body.size(); i++) { if (head->x == body[i]->x && head->y == body[i]->y) { isAlive = false; break; } } } else { return; } } void Snake::setHasMoved(bool a) { hasMoved = a; } void Snake::setIsAlive(bool a) { isAlive = a; } int Snake::getX() { return x; } int Snake::getY() { return y; } int Snake::getWidth() { return width; } int Snake::getHeight() { return height; } bool Snake::getIsAlive() { return isAlive; } bool Snake::getHasMoved() { return hasMoved; } std::vector<Segment*> const& Snake::getV() const { // TODO: insert return statement here return body; } GameScene.h #include "Scene.h" #include "GameObject.h" #include "Snake.h" #include "Food.h" #include "util.h" #include "text.h" #include "SoundManager.h" class GameScene : public Scene { public: GameScene(); ~GameScene(); void start(); void draw(); void update(); void spawnFood(); void collisionLogic(); void selfCollision(); void despawnFood(Food* food); private: Snake* snake; Food* food; int points; std::vector<Food*> spawnedFood; }; GameScene.cpp #include "GameScene.h" GameScene::GameScene() { // Register and add game objects on constructor snake = new Snake(); this->addGameObject(snake); points = 0; } GameScene::~GameScene() { delete snake; delete food; } void GameScene::start() { Scene::start(); // Initialize any scene logic here initFonts(); spawnFood(); } void GameScene::draw() { Scene::draw(); drawText(110, 20, 255, 255, 255, TEXT_CENTER, "POINTS: %03d", points); if (snake->getIsAlive() == false) { drawText(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 255, 255, 255, TEXT_CENTER, "GAME OVER!"); } } void GameScene::update() { Scene::update(); if (spawnedFood.size() == 0 && spawnedFood.size() != 1) { spawnFood(); } collisionLogic(); selfCollision(); } void GameScene::spawnFood() { int random = rand() % 720; if (random % 25 != 0) { random = rand() % 720; } else { Food* food = new Food(); this->addGameObject(food); food->setPosition(rand() % SCREEN_WIDTH, rand() % SCREEN_HEIGHT); spawnedFood.push_back(food); } } void GameScene::collisionLogic() { Segment* head = snake->getV()[0]; std::vector<Segment*> snakeBody = snake->getV(); for (int i = 0; i < objects.size(); i++) { Food* food = dynamic_cast<Food*>(objects[i]); if (food != NULL) { int collision = checkCollision( head->x, head->y, snake->getWidth(), snake->getHeight(), food->getX(), food->getY(), food->getWidth(), food->getHeight() ); if (collision == 1) { despawnFood(food); snake->addSegment(snakeBody[snakeBody.size() - 1]->x, snakeBody[snakeBody.size() - 1]->y); //Adds a part to the snake points++; break; } } } } void GameScene::selfCollision() { std::vector<Segment*> body = snake->getV(); Segment* head = snake->getV()[0]; for (int i = 1; i < snake->getV().size(); i++) { if (head->x == body[i]->x && head->y == body[i]->y) { snake->setIsAlive(false); break; } } } void GameScene::despawnFood(Food* food) { int index = -1; for (int i = 0; i < spawnedFood.size(); i++) { if (food == spawnedFood[i]) { index = i; break; } } if (index != -1) { spawnedFood.erase(spawnedFood.begin() + index); delete food; } }
It seems that I had some logical errors when it comes to the grid movement because when I re-coded everything and changed the grid movement into cell based instead of using modulo condition by dividing the screen width and height to the pixel size of my snake and using that as the coordinates for my movement, everything went back to normal and the collision bug disappeared. Instead of doing this for the grid movement Old Grid Movement Code tempX += dx; tempY += dy; if (tempX % 25 == 0) { snakeHead->x += tempX; tempX = 0; } if (tempY % 25 == 0) { snakeHead->y += tempY; tempY = 0; } I defined this as a permanent value in my defs.h defs.h #define CELL_SIZE 25 // Size of the segment #define CELL_WIDTH SCREEN_WIDTH / CELL_SIZE #define CELL_HEIGHT SCREEN_HEIGHT / CELL_SIZE After that, since I'm still going to render the picture with the default resolution, I multiplied CELL_SIZE to the dest variable of my blit function draw.cpp void blit(SDL_Texture* texture, int x, int y) { SDL_Rect dest; dest.x = x * CELL_SIZE; dest.y = y * CELL_SIZE; SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h); SDL_RenderCopy(app.renderer, texture, NULL, &dest); } This results to the snake and any other thing that I'm going to render to follow a grid and by assigning the x and y values with the CELL_WIDTH and CELL_HEIGHT as substitution to the resolution, I accomplished the grid movement with no conflict with my collision check.
QT real time graph has flickering problem
i am using openglseris (line) to display incoming data. i edited the opengl series example given by the qt as per my needs. How can I update the openglseris without flickering the display (smooth data update)? Because so far I have managed to display incoming data but the display is flickering every time it updates the value. //***********datasource.h**********// #ifndef DATASOURCE_H #define DATASOURCE_H #include <QtCore/QObject> #include <QtCharts/QXYSeries> #include <QtWidgets/QLabel> #include <QtCore/QElapsedTimer> #include <QtCore/QTimer> QT_CHARTS_USE_NAMESPACE class DataSource : public QObject { Q_OBJECT public: explicit DataSource(QObject *parent = 0); void startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel); public slots: void generateData(int seriesCount, int rowCount, int colCount); void update(QAbstractSeries *series, int seriesIndex); void handleSceneChanged(); void updateAllSeries(); private: QVector<QVector<QVector<QPointF> > > m_data; int m_index; QList<QXYSeries *> m_seriesList; QLabel *m_fpsLabel; QElapsedTimer m_fpsTimer; QTimer m_dataUpdater; }; #endif // DATASOURCE_H //*************datasource.cpp*******************// #include "datasource.h" #include <QtCore/QtMath> #include<QDebug> QT_CHARTS_USE_NAMESPACE int shift=0; int c[2048]={50,149,143,148,151,151,150,150,149,149,152,148,148,147,146,152,149,150,147,151,150,149,148,149,152,150,148,150,147,149,149,149,149,151,152,151,149,148,151,147,151,147,150,147,151,150,154,150,151,151,151,151,154,154,150,152,148,151,150,148,150,151,149,151,150,156,155,159,158,154,154,151,152,154,155,150,154,149,150,149,154,152,155,150,154,152,155,150,149,154,150,156,154,150,151,150,151,155,151,157,151,152,150,151,148,150,150,157,150,156,150,147,155,150,155,155,152,150,154,151,152,151,150,152,151,157,151,152,150,149,154,152,154,154,151,151,150,150,157,154,154,155,150,155,157,150,152,151,156,151,150,152,152,154,155,150,155,150,150,156,154,149,152,154,154,154,151,150,156,148,150,157,150,154,150,154,154,154,156,150,150,155,156,155,156,154,154,150,154,155,158,151,154,154,150,150,156,151,148,150,151,150,154,150,156,150,154,151,154,150,150,157,154,155,154,157,155,156,152,155,155,157,154,159,156,156,154,155,154,156,156,151,152,150,150,156,154,152,159,150,150,158,150,155,156,155,156,155,155,154,154,154,155,155,155,154,149,156,150,156,150,155,155,156,157,150,157,157,151,157,157,158,152,150,156,155,154,154,155,156,154,154,156,150,157,154,150,157,157,152,155,155,154,154,155,154,156,156,150,155,154,157,155,156,156,150,155,157,154,157,154,161,155,155,155,158,156,156,150,154,155,155,157,157,157,152,155,156,159,155,154,154,155,157,151,159,154,157,154,157,158,154,155,155,155,159,155,156,156,157,154,158,155,160,157,157,158,158,155,158,155,155,155,150,159,156,157,158,156,157,156,154,156,158,157,156,159,156,157,158,155,157,154,157,155,157,156,157,157,159,156,157,156,162,158,155,159,156,156,159,155,157,155,158,155,162,156,157,154,163,157,158,156,161,157,156,157,156,154,158,159,160,156,159,159,157,159,155,162,159,156,155,157,154,155,156,157,156,157,155,159,157,160,150,157,158,152,157,155,154,158,155,158,158,158,155,158,156,156,157,159,156,159,156,157,157,156,156,158,155,155,160,150,158,154,159,157,154,157,155,157,159,154,157,150,155,155,155,152,155,159,158,155,155,158,156,154,154,155,157,157,154,158,155,159,155,160,156,159,157,155,150,160,156,150,154,157,150,158,155,150,154,157,155,158,160,158,154,159,157,157,157,155,156,159,154,157,160,154,155,157,156,150,156,157,156,158,150,156,156,154,157,156,159,158,158,156,155,156,155,156,155,160,155,156,158,157,154,150,158,157,155,157,155,158,156,159,156,157,159,157,156,157,159,154,160,158,158,160,156,155,154,161,159,160,157,156,154,155,154,156,159,158,155,154,150,158,162,156,156,155,154,160,159,162,160,159,158,161,150,159,156,155,160,158,159,158,155,161,155,157,154,154,156,150,156,163,154,149,160,160,155,159,155,156,155,150,157,158,157,157,154,157,155,158,155,156,156,156,155,150,156,157,155,155,155,157,157,157,157,155,157,157,155,159,158,150,156,157,155,158,156,158,155,154,157,157,156,155,156,155,160,157,159,150,158,155,162,157,159,159,155,156,154,155,158,157,161,156,158,157,155,156,158,158,157,156,158,157,154,155,150,158,156,160,160,160,156,157,154,155,150,159,156,152,156,160,158,157,154,158,158,158,155,156,160,160,155,156,157,158,157,159,157,161,155,152,157,158,154,157,160,156,158,155,158,158,156,155,155,150,154,156,155,158,155,155,157,156,158,154,155,158,162,156,159,158,157,159,154,155,160,157,158,154,155,157,158,159,158,158,157,155,156,159,159,155,155,158,155,155,158,155,160,161,157,159,159,156,155,150,156,155,150,156,157,155,155,158,155,156,159,156,158,162,155,160,154,158,158,158,157,160,156,155,157,152,156,160,158,160,155,158,155,155,157,155,156,159,154,155,157,157,160,159,156,157,162,158,156,157,154,160,157,156,159,159,156,155,159,158,157,156,162,160,158,157,162,157,158,157,157,163,156,156,160,161,154,155,156,159,157,156,158,159,157,155,157,162,157,160,158,159,155,156,155,160,158,157,155,160,159,156,157,157,160,155,157,158,157,157,156,160,155,157,156,157,159,159,160,159,160,157,162,157,157,154,157,157,159,161,155,160,155,155,157,160,156,158,158,161,159,156,156,158,160,160,158,155,157,161,154,160,156,155,156,160,158,156,157,150,155,154,160,157,154,155,155,160,155,154,158,157,155,160,155,156,160,154,157,154,158,157,159,157,155,152,155,156,156,155,155,155,155,156,156,159,159,157,160,155,158,158,157,157,150,155,156,155,156,156,155,159,150,161,155,159,156,156,158,161,155,157,156,159,155,150,155,156,161,155,156,156,154,157,155,157,158,156,158,160,155,161,158,156,159,157,156,159,155,158,162,155,160,158,161,160,156,158,164,156,158,159,158,154,161,158,157,157,156,156,160,157,155,156,160,160,155,158,156,162,160,160,158,157,160,163,156,154,154,162,156,157,155,160,150,158,155,156,154,157,159,160,158,157,162,154,158,163,158,154,158,154,156,155,158,156,159,158,156,156,159,154,159,154,159,156,157,157,160,159,159,156,150,159,158,156,156,156,158,155,158,156,155,156,157,158,156,156,159,157,157,156,156,159,157,160,159,161,159,158,158,160,157,158,156,156,160,160,158,157,157,158,162,150,156,158,158,163,159,158,154,156,159,159,159,157,158,155,161,155,159,155,160,157,156,161,158,157,156,157,158,155,160,158,160,156,157,159,160,156,156,158,156,156,156,155,157,156,156,160,157,154,159,160,157,158,162,159,158,161,158,156,160,156,159,162,162,157,158,160,159,158,160,160,157,156,159,158,160,157,161,158,158,154,160,160,161,154,161,159,156,158,157,160,159,161,157,157,162,156,157,159,152,161,157,158,158,157,158,157,158,158,157,159,159,159,150,157,159,158,151,158,156,160,158,158,157,156,158,158,156,156,158,160,155,159,156,161,156,163,154,161,159,157,159,161,158,157,155,159,156,158,155,161,158,156,161,155,159,158,159,155,162,154,162,161,157,159,159,156,160,157,159,160,160,159,156,156,156,157,157,163,159,161,156,158,156,159,156,157,158,156,160,163,163,156,160,159,157,156,160,160,155,157,155,160,157,160,160,157,158,159,157,159,160,161,160,159,156,158,157,157,156,160,156,162,159,157,154,156,155,162,159,159,161,157,162,159,156,156,156,162,158,161,158,167,159,159,156,158,156,159,157,154,159,160,159,155,163,158,158,162,156,162,158,158,156,161,159,155,160,155,159,150,161,155,156,157,157,155,157,155,163,155,158,157,155,157,161,154,154,155,156,157,159,156,156,159,158,158,158,161,159,156,158,158,158,160,160,162,158,159,156,161,154,154,158,157,161,159,157,159,154,159,161,159,159,160,159,162,160,158,158,157,160,159,161,161,157,158,157,158,162,160,161,159,161,159,162,159,157,161,160,158,160,160,156,157,157,159,159,159,161,158,160,155,157,162,159,162,161,159,161,158,159,162,155,159,161,155,160,157,156,157,160,154,157,159,157,158,160,159,160,157,156,156,158,157,158,154,161,159,154,158,159,160,160,159,162,159,161,158,161,158,156,160,160,158,156,159,158,155,155,156,160,159,162,158,160,159,159,159,156,156,156,164,155,158,157,160,157,160,158,160,158,158,159,152,159,158,157,162,160,160,160,159,155,158,154,159,161,157,160,158,157,154,160,155,158,160,152,156,150,158,157,159,158,162,158,157,157,156,160,159,158,159,155,156,160,154,158,155,156,152,156,156,156,156,154,158,156,157,155,154,156,156,157,156,158,157,156,159,161,152,156,155,152,156,156,155,158,159,157,156,157,156,158,158,155,152,161,159,155,156,157,152,156,158,158,150,155,152,158,159,158,155,160,150,154,156,158,155,157,160,156,157,155,155,157,159,158,156,158,158,156,159,156,157,150,155,158,158,157,158,159,158,150,160,156,157,158,155,154,157,156,156,160,157,161,157,158,158,158,150,150,154,150,150,150,157,157,150,158,155,159,158,158,150,158,159,154,154,157,154,155,157,155,154,155,157,154,157,156,157,158,160,155,159,155,157,160,150,152,156,156,156,154,157,156,154,156,159,154,155,150,150,158,158,156,160,158,152,150,157,154,159,150,150,158,155,154,157,155,154,150,152,156,156,154,159,152,156,156,150,156,156,157,154,152,154,151,155,155,152,158,157,161,152,152,157,154,158,150,156,158,150,157,154,156,154,155,158,156,154,150,154,158,150,159,155,151,152,155,154,154,154,154,152,150,154,154,154,152,150,150,156,150,157,150,151,151,151,155,150,150,158,150,152,155,155,152,150,156,151,152,150,151,158,150,152,152,158,148,154,151,152,154,155,150,154,154,154,155,155,150,150,156,151,155,151,151,151,152,152,150,151,151,151,151,150,156,152,159,148,156,154,150,149,156,152,154,155,150,152,155,151,155,149,150,150,151,155,149,155,150,152,152,149,150,154,151,149,156,154,149,154,151,147,149,150,149,151,154,149,155,151,149,148,150,155,150,149,149,152,148,154,150,149,150,149,151,154,149,152,154,150,150,151,152,155,150,150,151,149,148,152,149}; int b[2048]={150,149,143,148,151,151,150,150,149,149,152,148,148,147,146,152,149,150,147,151,150,149,148,149,152,150,148,150,147,149,149,149,149,151,152,151,149,148,151,147,151,147,150,147,151,153,154,153,151,151,151,151,154,154,153,152,148,151,150,148,153,151,149,151,150,156,155,159,158,154,154,151,152,154,155,150,154,149,153,149,154,152,155,150,154,152,155,150,149,154,150,156,154,153,151,153,151,155,151,157,151,152,153,151,148,153,150,157,150,156,153,147,155,150,155,155,152,153,154,151,152,151,153,152,151,157,151,152,153,149,154,152,154,154,151,151,153,153,157,154,154,155,153,155,157,153,152,151,156,151,153,152,152,154,155,153,155,150,150,156,154,149,152,154,154,154,151,150,156,148,150,157,153,154,153,154,154,154,156,150,150,155,156,155,156,154,154,153,154,155,158,151,154,154,153,153,156,151,148,153,151,153,154,153,156,153,154,151,154,153,153,157,154,155,154,157,155,156,152,155,155,157,154,159,156,156,154,155,154,156,156,151,152,153,153,156,154,152,159,150,153,158,153,155,156,155,156,155,155,154,154,154,155,155,155,154,149,156,153,156,153,155,155,156,157,150,157,157,151,157,157,158,152,153,156,155,154,154,155,156,154,154,156,153,157,154,150,157,157,152,155,155,154,154,155,154,156,156,153,155,154,157,155,156,156,153,155,157,154,157,154,161,155,155,155,158,156,156,153,154,155,155,157,157,157,152,155,156,159,155,154,154,155,157,151,159,154,157,154,157,158,154,155,155,155,159,155,156,156,157,154,158,155,160,157,157,158,158,155,158,155,155,155,153,159,156,157,158,156,157,156,154,156,158,157,156,159,156,157,158,155,157,154,157,155,157,156,157,157,159,156,157,156,162,158,155,159,156,156,159,155,157,155,158,155,162,156,157,154,163,157,158,156,161,157,156,157,156,154,158,159,160,156,159,159,157,159,155,162,159,156,155,157,154,155,156,157,156,157,155,159,157,160,153,157,158,152,157,155,154,158,155,158,158,158,155,158,156,156,157,159,156,159,156,157,157,156,156,158,155,155,160,153,158,154,159,157,154,157,155,157,159,154,157,153,155,155,155,152,155,159,158,155,155,158,156,154,154,155,157,157,154,158,155,159,155,160,156,159,157,155,153,160,156,150,154,157,153,158,155,153,154,157,155,158,160,158,154,159,157,157,157,155,156,159,154,157,160,154,155,157,156,153,156,157,156,158,153,156,156,154,157,156,159,158,158,156,155,156,155,156,155,160,155,156,158,157,154,153,158,157,155,157,155,158,156,159,156,157,159,157,156,157,159,154,160,158,158,160,156,155,154,161,159,160,157,156,154,155,154,156,159,158,155,154,153,158,162,156,156,155,154,160,159,162,160,159,158,161,153,159,156,155,160,158,159,158,155,161,155,157,154,154,156,153,156,163,154,149,160,160,155,159,155,156,155,153,157,158,157,157,154,157,155,158,155,156,156,156,155,153,156,157,155,155,155,157,157,157,157,155,157,157,155,159,158,153,156,157,155,158,156,158,155,154,157,157,156,155,156,155,160,157,159,153,158,155,162,157,159,159,155,156,154,155,158,157,161,156,158,157,155,156,158,158,157,156,158,157,154,155,153,158,156,160,160,160,156,157,154,155,153,159,156,152,156,160,158,157,154,158,158,158,155,156,160,160,155,156,157,158,157,159,157,161,155,152,157,158,154,157,160,156,158,155,158,158,156,155,155,153,154,156,155,158,155,155,157,156,158,154,155,158,162,156,159,158,157,159,154,155,160,157,158,154,155,157,158,159,158,158,157,155,156,159,159,155,155,158,155,155,158,155,160,161,157,159,159,156,155,153,156,155,153,156,157,155,155,158,155,156,159,156,158,162,155,160,154,158,158,158,157,160,156,155,157,152,156,160,158,160,155,158,155,155,157,155,156,159,154,155,157,157,160,159,156,157,162,158,156,157,154,160,157,156,159,159,156,155,159,158,157,156,162,160,158,157,162,157,158,157,157,163,156,156,160,161,154,155,156,159,157,156,158,159,157,155,157,162,157,160,158,159,155,156,155,160,158,157,155,160,159,156,157,157,160,155,157,158,157,157,156,160,155,157,156,157,159,159,160,159,160,157,162,157,157,154,157,157,159,161,155,160,155,155,157,160,156,158,158,161,159,156,156,158,160,160,158,155,157,161,154,160,156,155,156,160,158,156,157,153,155,154,160,157,154,155,155,160,155,154,158,157,155,160,155,156,160,154,157,154,158,157,159,157,155,152,155,156,156,155,155,155,155,156,156,159,159,157,160,155,158,158,157,157,153,155,156,155,156,156,155,159,153,161,155,159,156,156,158,161,155,157,156,159,155,153,155,156,161,155,156,156,154,157,155,157,158,156,158,160,155,161,158,156,159,157,156,159,155,158,162,155,160,158,161,160,156,158,164,156,158,159,158,154,161,158,157,157,156,156,160,157,155,156,160,160,155,158,156,162,160,160,158,157,160,163,156,154,154,162,156,157,155,160,153,158,155,156,154,157,159,160,158,157,162,154,158,163,158,154,158,154,156,155,158,156,159,158,156,156,159,154,159,154,159,156,157,157,160,159,159,156,153,159,158,156,156,156,158,155,158,156,155,156,157,158,156,156,159,157,157,156,156,159,157,160,159,161,159,158,158,160,157,158,156,156,160,160,158,157,157,158,162,153,156,158,158,163,159,158,154,156,159,159,159,157,158,155,161,155,159,155,160,157,156,161,158,157,156,157,158,155,160,158,160,156,157,159,160,156,156,158,156,156,156,155,157,156,156,160,157,154,159,160,157,158,162,159,158,161,158,156,160,156,159,162,162,157,158,160,159,158,160,160,157,156,159,158,160,157,161,158,158,154,160,160,161,154,161,159,156,158,157,160,159,161,157,157,162,156,157,159,152,161,157,158,158,157,158,157,158,158,157,159,159,159,153,157,159,158,151,158,156,160,158,158,157,156,158,158,156,156,158,160,155,159,156,161,156,163,154,161,159,157,159,161,158,157,155,159,156,158,155,161,158,156,161,155,159,158,159,155,162,154,162,161,157,159,159,156,160,157,159,160,160,159,156,156,156,157,157,163,159,161,156,158,156,159,156,157,158,156,160,163,163,156,160,159,157,156,160,160,155,157,155,160,157,160,160,157,158,159,157,159,160,161,160,159,156,158,157,157,156,160,156,162,159,157,154,156,155,162,159,159,161,157,162,159,156,156,156,162,158,161,158,167,159,159,156,158,156,159,157,154,159,160,159,155,163,158,158,162,156,162,158,158,156,161,159,155,160,155,159,153,161,155,156,157,157,155,157,155,163,155,158,157,155,157,161,154,154,155,156,157,159,156,156,159,158,158,158,161,159,156,158,158,158,160,160,162,158,159,156,161,154,154,158,157,161,159,157,159,154,159,161,159,159,160,159,162,160,158,158,157,160,159,161,161,157,158,157,158,162,160,161,159,161,159,162,159,157,161,160,158,160,160,156,157,157,159,159,159,161,158,160,155,157,162,159,162,161,159,161,158,159,162,155,159,161,155,160,157,156,157,160,154,157,159,157,158,160,159,160,157,156,156,158,157,158,154,161,159,154,158,159,160,160,159,162,159,161,158,161,158,156,160,160,158,156,159,158,155,155,156,160,159,162,158,160,159,159,159,156,156,156,164,155,158,157,160,157,160,158,160,158,158,159,152,159,158,157,162,160,160,160,159,155,158,154,159,161,157,160,158,157,154,160,155,158,160,152,156,153,158,157,159,158,162,158,157,157,156,160,159,158,159,155,156,160,154,158,155,156,152,156,156,156,156,154,158,156,157,155,154,156,156,157,156,158,157,156,159,161,152,156,155,152,156,156,155,158,159,157,156,157,156,158,158,155,152,161,159,155,156,157,152,156,158,158,150,155,152,158,159,158,155,160,150,154,156,158,155,157,160,156,157,155,155,157,159,158,156,158,158,156,159,156,157,153,155,158,158,157,158,159,158,153,160,156,157,158,155,154,157,156,156,160,157,161,157,158,158,158,153,153,154,153,153,153,157,157,150,158,155,159,158,158,153,158,159,154,154,157,154,155,157,155,154,155,157,154,157,156,157,158,160,155,159,155,157,160,153,152,156,156,156,154,157,156,154,156,159,154,155,153,153,158,158,156,160,158,152,153,157,154,159,153,153,158,155,154,157,155,154,153,152,156,156,154,159,152,156,156,153,156,156,157,154,152,154,151,155,155,152,158,157,161,152,152,157,154,158,153,156,158,153,157,154,156,154,155,158,156,154,153,154,158,153,159,155,151,152,155,154,154,154,154,152,153,154,154,154,152,153,153,156,153,157,153,151,151,151,155,153,153,158,153,152,155,155,152,153,156,151,152,153,151,158,153,152,152,158,148,154,151,152,154,155,153,154,154,154,155,155,153,153,156,151,155,151,151,151,152,152,150,151,151,151,151,150,156,152,159,148,156,154,150,149,156,152,154,155,153,152,155,151,155,149,153,150,151,155,149,155,153,152,152,149,153,154,151,149,156,154,149,154,151,147,149,153,149,151,154,149,155,151,149,148,150,155,150,149,149,152,148,154,153,149,150,149,151,154,149,152,154,153,150,151,152,155,153,150,151,149,148,152,149 }; DataSource::DataSource(QObject *parent) : QObject(parent), m_index(-1) { generateData(0, 0, 0); } void DataSource::update(QAbstractSeries *series, int seriesIndex) { if (series) { QXYSeries *xySeries = static_cast<QXYSeries *>(series); const QVector<QVector<QPointF> > &seriesData = m_data.at(seriesIndex); if (seriesIndex == 0) m_index++; if (m_index > seriesData.count() - 1) m_index = 0; QVector<QPointF> points = seriesData.at(m_index); // Use replace instead of clear + append, it's optimized for performance xySeries->replace(points); } } void DataSource::handleSceneChanged() { m_dataUpdater.start(); } void DataSource::updateAllSeries() { static int frameCount = 0; static QString labelText = QStringLiteral("FPS: %1"); for (int i = 0; i < m_seriesList.size(); i++) update(m_seriesList[i], i); frameCount++; int elapsed = m_fpsTimer.elapsed(); if (elapsed >= 1000) { elapsed = m_fpsTimer.restart(); qreal fps = qreal(0.1 * int(10000.0 * (qreal(frameCount) / qreal(elapsed)))); m_fpsLabel->setText(labelText.arg(QString::number(fps, 'f', 1))); m_fpsLabel->adjustSize(); frameCount = 0; } m_data.clear(); // Append the new data depending on the type QVector<QVector<QPointF> > seriesData; QVector<QPointF> points; // points.reserve(2048); for (int j(0); j < 2048; j++) { qreal x(0); qreal y(0); if(shift==0) { y = b[j] ; x=j; }else { y = c[j] ; x=j; } points.append(QPointF(x, y)); } seriesData.append(points); m_data.append(seriesData); if(shift==0) { shift=1; }else { shift=0; } } void DataSource::startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel) { m_seriesList = seriesList; m_fpsLabel = fpsLabel; m_dataUpdater.setInterval(500); m_dataUpdater.setSingleShot(true); QObject::connect(&m_dataUpdater, &QTimer::timeout,this, &DataSource::updateAllSeries); m_fpsTimer.start(); updateAllSeries(); } void DataSource::generateData(int seriesCount, int rowCount, int colCount) { // Remove previous data foreach (QVector<QVector<QPointF> > seriesData, m_data) { foreach (QVector<QPointF> row, seriesData) row.clear(); } m_data.clear(); // Append the new data depending on the type for (int k(0); k < seriesCount; k++) { QVector<QVector<QPointF> > seriesData; for (int i(0); i < rowCount; i++) { QVector<QPointF> points; points.reserve(colCount); for (int j(0); j < colCount; j++) { qreal x(0); qreal y(0); if(shift==0) { y = a[j] ; x=j; }else { y = b[j] ; x=j; } points.append(QPointF(x, y)); } seriesData.append(points); } m_data.append(seriesData); } if(shift==0) { shift=1; }else { shift=0; } qDebug()<<"test"; } //***********main.cpp**********// #include "datasource.h" #include <QtWidgets/QApplication> #include <QtWidgets/QMainWindow> #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include <QtCharts/QScatterSeries> #include <QtCharts/QValueAxis> #include <QtCharts/QLogValueAxis> #include <QtWidgets/QLabel> QT_CHARTS_USE_NAMESPACE int main(int argc, char *argv[]) { QApplication a(argc, argv); QStringList colors; colors << "red" << "blue" << "green" << "black"; QChart *chart = new QChart(); chart->legend()->hide(); QValueAxis *axisX = new QValueAxis; QValueAxis *axisY = new QValueAxis; chart->addAxis(axisX, Qt::AlignBottom); chart->addAxis(axisY, Qt::AlignLeft); const int seriesCount = 1; const int pointCount = 2048; chart->setTitle("OpenGL Accelerated Series"); QList<QXYSeries *> seriesList; for (int i = 0; i < seriesCount; i++) { QXYSeries *series = 0; int colorIndex = i % colors.size(); if (i % 2) { series = new QScatterSeries; QScatterSeries *scatter = static_cast<QScatterSeries *>(series); scatter->setColor(QColor(colors.at(colorIndex))); scatter->setMarkerSize(qreal(colorIndex + 2) / 2.0); // Scatter pen doesn't have affect in OpenGL drawing, but if you disable OpenGL drawing // this makes the marker border visible and gives comparable marker size to OpenGL // scatter points. scatter->setPen(QPen("black")); } else { series = new QLineSeries; series->setPen(QPen(QBrush(QColor(colors.at(colorIndex))), qreal(colorIndex + 2) / 2.0)); } seriesList.append(series); //![1] series->setUseOpenGL(true); //![1] chart->addSeries(series); series->attachAxis(axisX); series->attachAxis(axisY); } if (axisX->type() == QAbstractAxis::AxisTypeLogValue) axisX->setRange(0.1, 2048.0); else axisX->setRange(0, 2048.0); if (axisY->type() == QAbstractAxis::AxisTypeLogValue) axisY->setRange(0.1, 255.0); else axisY->setRange(0, 255.0); QChartView *chartView = new QChartView(chart); QMainWindow window; window.setCentralWidget(chartView); window.resize(600, 400); window.show(); DataSource dataSource; dataSource.generateData(seriesCount, 1, pointCount); QLabel *fpsLabel = new QLabel(&window); QLabel *countLabel = new QLabel(&window); QString countText = QStringLiteral("Total point count: %1"); countLabel->setText(countText.arg(pointCount * seriesCount)); countLabel->adjustSize(); fpsLabel->move(10, 2); fpsLabel->adjustSize(); fpsLabel->raise(); fpsLabel->show(); countLabel->move(10, fpsLabel->height()); fpsLabel->raise(); countLabel->show(); // We can get more than one changed event per frame, so do async update. // This also allows the application to be responsive. QObject::connect(chart->scene(), &QGraphicsScene::changed, &dataSource, &DataSource::handleSceneChanged); dataSource.startUpdates(seriesList, fpsLabel); return a.exec(); }
Animating sprites in sfml from a sprite sheet
I am trying to animate a sprite in sfml. At the moment I am able to move the sprite and change it's image when moving in a different direction, but I want to animate it while it is moving. I am thinking that there might be a way to accomplish this with sf::Clock or there might be a better way. All sprites are on the same sprite sheet so I just need to find a way to change the X and Y coordinates of the textureRect based on a time while moving in a direction. If I am missing something or you have any questions, I will answer to the best of my ability. main.cpp #include <iostream> #include <SFML/Graphics.hpp> #include "Character.hpp" int main() { sf::RenderWindow window(sf::VideoMode(5000, 5000), "Awesome Game" ); Character Boi("SpritesBoi.png", 0, 0, 5, 100); sf::Sprite BoiSprite = Boi.getSprite(); Boi.SheetX = 0; Boi.SheetY = 48; while (window.isOpen()){ // check all the window's events that were triggered since the last iteration of the loop sf::Event event; while (window.pollEvent(event)){ // "close requested" event: we close the window if (event.type == sf::Event::Closed){ window.close(); } } Boi.Move(); BoiSprite.setTextureRect(sf::IntRect(Boi.SheetX, Boi.SheetY, 110, 150)); BoiSprite.setPosition(Boi.x_pos, Boi.y_pos); window.clear(sf::Color(255, 255, 255)); window.draw(BoiSprite); window.display(); } } Character.hpp #ifndef Character_hpp #define Character_hpp #include <stdio.h> #include <SFML/Graphics.hpp> #endif /* Character_hpp */ class Character{ public: int health; int speed; int x_pos; int y_pos; int SheetX; int SheetY; sf::Texture texture; sf::Sprite sprite; Character(std::string image, int xlocation, int ylocation, int s, int h){ health = h; speed = s; x_pos = xlocation; y_pos = ylocation; texture.loadFromFile(image); } sf::Sprite getSprite() { sprite.setTexture(texture); sprite.setPosition(x_pos, y_pos); sprite.setTextureRect(sf::IntRect(SheetX, SheetY, 110, 150)); return sprite; } void Move(); }; Character.cpp #include "Character.hpp" #include <iostream> void Character::Move(){ //Up if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){ SheetX = 0; SheetY = 192; y_pos = y_pos - 1; Up = true; } //Down if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){ SheetX = 0; SheetY = 48; y_pos = y_pos + 1; Down = false; } //Left if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){ SheetX = 0; SheetY = 480; x_pos = x_pos - 1; Left = true; } //Right if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){ SheetX = 0; SheetY = 339; x_pos = x_pos + 1; Right = true; } //Up Right if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) and sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){ SheetX = 334; SheetY = 490; } //Up Left if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) and sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){ SheetX = 333; SheetY = 340; } //Down Right if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) and sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){ SheetX = 334; SheetY = 48; } //Down Left if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down) and sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){ SheetX = 334; SheetY = 191; } }
You need to keep track of the frames in the animation (list of sf::IntRects). And have some sort of delay inbetween. On update, simply move through the frames and apply the rectangle. struct Frame { sf::IntRect rect; double duration; // in seconds }; class Animation { std::vector<Frame> frames; double totalLength; double totalProgress; sf::Sprite *target; public: Animation(sf::Sprite& target) { this->target = ⌖ totalProgress = 0.0; } void addFrame(Frame&& frame) { frames.push_back(std::move(frame)); totalLength += frame.duration; } void update(double elapsed) { totalProgress += elapsed; double progress = totalProgress; for(auto frame : frames) { progress -= (*frame).duration; if (progress <= 0.0 || &(*frame) == &frames.back()) { target->setTextureRect((*frame).rect); break; // we found our frame } } }; You can use like so: sf::Sprite myCharacter; // Load the image... Animation animation(myCharacter); animation.addFrame({sf::IntRect(x,y,w,h), 0.1}); // do this for as many frames as you need // In your main loop: animation.update(elapsed); window.draw(myCharacter);
2D Isometric(diamond shape) game engine - Reversed sprites
All my sprites are reversed when I try to draw my isometric map. Here is the tileset.png mentionned in the following code : Object.h/Object.cpp I can use them to draw tiles, UI element, etc. ... #pragma once class Object { public: //FUNCTIONS Object(); void addComponent(float value); int getComponent(float index); void editComponent(float index, float value); void deleteComponent(float index); private: vector<int> components; }; #include "Object.cpp" - #pragma once //FUNCTIONS Object::Object() { //... } void Object::addComponent(float value) { components.push_back(value); } int Object::getComponent(float index) { return components[index]; } void Object::editComponent(float index, float value) { components[index] = value; } void Object::deleteComponent(float index) { components.erase(components.begin() + index); } Note: I may have weird includes, I'm struggling with visual studio ha ha. Scene.h/Scene.cpp Handle data & graphics #pragma once class Scene { public: Scene(float w, float h, int mapx, int mapy, int tilesize, int mapwidth, int mapheight); void run(); void addLayer(); void loadTileset(sf::String url); void loadUiTileset(sf::String url); //functions //... //getters //... //setters //... private: sf::RenderWindow window; float width; float height; int nb_layers; int map_x; int map_y; int map_width; int map_height; int tile_size; int selected_tile_index; sf::RenderTexture texture; sf::Sprite tile; sf::Sprite map; sf::Texture tileset; vector<Object> tiles; sf::Texture uiTileset; //private functions void updateMap(); //... void processEvent(); void update(sf::Time deltaTime); void render(); //... }; #include "Scene.cpp" - #pragma once //functions Scene::Scene(float w, float h, int mapx, int mapy, int tilesize, int mapwidth, int mapheight) : window(sf::VideoMode(w, h), "Editor") { width = w; height = h; map_x = mapx; map_y = mapy; map_width = mapwidth; map_height = mapheight; tile_size = tilesize; selected_tile_index = 0;//default nb_layers = 0; } void Scene::run() { sf::Clock clock; sf::Time timeSinceLastUpdate = sf::Time::Zero; sf::Time TimePerFrame = sf::seconds(1.f / 60.f); while (window.isOpen()) { processEvent(); timeSinceLastUpdate += clock.restart(); while (timeSinceLastUpdate > TimePerFrame) { timeSinceLastUpdate -= TimePerFrame; processEvent(); update(TimePerFrame); } render(); } } void Scene::addLayer() { nb_layers += 1; int tile_x = map_x, tile_y = map_y, num_layer = nb_layers - 1, layer_pos = (num_layer * tile_size) / 2, tile_zOrder = -1; tile_y -= layer_pos; int x = map_x, y = map_y; for (int h = 0; h < map_height; h++) { for (int w = 0; w < map_width; w++) { tile_zOrder = (w * (h + 1)) + (num_layer * 10); x = carthesianToIsometric(tile_x, tile_y)[0]; y = carthesianToIsometric(tile_x, tile_y)[1] - layer_pos; cout << x << ", " << y << endl; Object tile; tile.addComponent(selected_tile_index); tile.addComponent(x); tile.addComponent(y); tile.addComponent(tile_zOrder); tile.addComponent(num_layer); tiles.push_back(tile); tile_x += tile_size; } tile_x = 0; tile_y += tile_size; } updateMap(); } void Scene::loadTileset(sf::String url) { if (!tileset.loadFromFile(url)) { cout << std::string(url) << "couldn't be loaded..." << endl; } } void Scene::loadUiTileset(sf::String url) { if (!uiTileset.loadFromFile(url)) { cout << std::string(url) << "couldn't be loaded..." << endl; } } //getters //... //setters //... //private functions void Scene::updateMap() { int tile_position_x = 0, tile_position_y = 0; int tile_x = 0, tile_y = 0; if (!texture.create(map_width * tile_size, (map_height * tile_size) / 2)) cout << "Texture couldn't be loaded... " << endl; texture.clear(sf::Color(133, 118, 104, 255)); sf::Sprite image; image.setTexture(tileset); int tileset_width = image.getGlobalBounds().width, tileset_height = image.getGlobalBounds().height; tile.setTexture(tileset); for (int tile_index = 0; tile_index < tiles.size(); tile_index++) { tile_position_x = getTilePosition(tileset_width, tileset_height, tiles[tile_index].getComponent(0), tile_size)[0]; tile_position_y = getTilePosition(tileset_width, tileset_height, tiles[tile_index].getComponent(0), tile_size)[1]; tile.setTextureRect(sf::IntRect(tile_position_x, tile_position_y, tile_size, tile_size)); tile_x = tiles[tile_index].getComponent(1); tile_y = tiles[tile_index].getComponent(2); tile.setPosition(sf::Vector2f(tile_x, tile_y)); texture.draw(tile); } map.setTexture(texture.getTexture()); } void Scene::processEvent() { sf::Event event; while (window.pollEvent(event)) { switch (event.type) { case sf::Event::Closed: window.close(); break; case sf::Event::KeyPressed: if (event.key.code == sf::Keyboard::Escape) window.close(); break; } } } void Scene::update(sf::Time deltaTime) { //REMEMBER: distance = speed * time //MOVEMENT, ANIMATIONS ETC. .. } void Scene::render() { window.clear(); window.draw(map); window.display(); } main.cpp #pragma once //global functions + main headers + class headers => #include "globalfunctions.h" int main() { int map_width = 15, map_height = 15, tile_size = 64; float scene_width = map_width * tile_size, scene_height = (map_height * tile_size) / 2; Scene engine(scene_width, scene_height, 0, 0, tile_size, map_width, map_height); engine.loadTileset("tileset.png"); //engine.loadUiTileset("menu.png"); engine.addLayer(); //... engine.run(); return EXIT_SUCCESS; } globalfunctions.h Some utility functions. getTilePosition(...) allow me to get x, y on a texture with a given tile index. Example : if I want to draw the tile n°0 of the tileset texture. #pragma once #include <SFML/System.hpp> #include <SFML/Graphics.hpp> #include <SFML/Window.hpp> #include <iostream> #include <math.h> #include <vector> using namespace std; vector<float> getTilePosition(float tileset_width, float tileset_height, float tile_index, float tile_size) {//In a tileset float tileX = 0, tileY = 0, tilePerLine = 0; tilePerLine = tileset_width / tile_size; tileY = floor(tile_index / tilePerLine); tileX = ((tile_index + 1) - (tileY * tilePerLine)) - 1; tileX *= tile_size; tileY *= tile_size; vector<float> coords; coords.push_back(tileX); coords.push_back(tileY); return coords; } vector<int> carthesianToIsometric(int x, int y) { vector<int> coords; float isoX = (x - y) / 2, isoY = (x + y) / 4; coords.push_back(isoX); coords.push_back(isoY); return coords; } #include "Object.h" #include "Scene.h" //... And here, the WTF result I get : Thanks for reading all that weird code ! Edit : When I change tile.setPosition(sf::Vector2f(tile_x, tile_y)); to tile.setPosition(sf::Vector2f(0, 0)); in updateMap() from scene.cpp : Unfortunatly, I cannot explain why. Maybe it will help you to understand the problem.
In case someone encounter the same problem : As #Spectre suggested it was a problem of the sfml function draw(). http://en.sfml-dev.org/forums/index.php?topic=6903.0 You need to use display on the sf::renderTexture after your cleared it.
C++ "Unable to read memory" when accessing pointer object from inherited class
I have this error: Exception thrown at 0x0108C6E9 in myprojectname.exe: 0xC0000005: Access violation reading location 0x00000028. However, this only happens when I call a function from the base class via the derived class. derived class: #pragma once #include "Player.h" class Space; class Enemy : public Player{ public: void init(Space * s); private: //Space * space = nullptr; }; CPP file: #include "Space.h" #include "Enemy.h" #include "Player.h" void Enemy::init(Space * s) { //space = s; } I need a pointer to the space object because my base class also needs that. I am not sure if this is needed. This is how I call the functions of the base(Player) class: space->getEnemy().drawPlayer(); //FIRST I GET THE OBJECT OF THE DERIVED(ENEMY CLASS) AND THAN I CALL A FUNCTION FROM THE BASE CLASS(PLAYER CLASSS) The error message "Unable to read memory" happens in getter functions in a class that the base class needs(for example a pointer to the window). Does anyone know what I am doing wrong? EDIT I forgot to tell: I initialize that space pointer to my import class named Space, in every class of my project. The program works fine with those space pointers if I don't call the inherited stuff of Enemy class Space.h #pragma once #include "Window.h" #include "Game.h" #include "Input.h" #include "Text.h" #include "Player.h" #include "Enemy.h" #include <ctime> class Space { public: void init(); int getStartTime(); Window & getWindow(); Game & getGame(); Input & getInput(); Text & getText(); Player & getPlayer(); Enemy & getEnemy(); private: Text textObj; Window windowObj; Game gameObj; Input inputObj; Player playerObj; Enemy enemyObj; int startTime = clock(); }; Space.cpp: #include "Space.h" //PASSING THE SPACE CLASS OBJECT TO THE INIT FUNCTIONS OF THE OTHER CLASSES void Space::init(){ windowObj.init(this); gameObj.init(this); inputObj.init(this); textObj.init(this); playerObj.init(this); enemyObj.init(this); //STARTING THE GAME ACTUALLY windowObj.createWindow(); } Enemy & Space::getEnemy() { return enemyObj; } Window & Space::getWindow(){ return windowObj; } Game & Space::getGame() { return gameObj; } Input & Space::getInput() { return inputObj; } Text & Space::getText() { return textObj; } Player & Space::getPlayer(){ return playerObj; } int Space::getStartTime(){ return startTime; } Player.h(has space pointer): #pragma once class Space; class Player { public: void init(Space * s); void drawPlayer(); void setPlayerXSpeed(float speed); void move(); void jump(); void checkFalling(); void setJumping(bool value); void setAttacking(bool value); void projectileAttack(); float getPlayerX(); float getPlayerY(); private: Space * space; int sprites = 8; int chanceToMove = 0; int times = 0; int spriteCount = 0; float spritePart = 0.0f; float spritePiece; float playerX = -0.7f; float playerY = -0.42f; float playerXSpeed = 0.0f; float playerYSpeed = 0.0f; bool ableToChangeY = true; bool jumping = false; bool falling = false; bool strafeRight = true; bool attacking = false; }; Player.cpp: #include "Player.h" #include "Space.h" #include <SDL2\SDL_opengl.h> #include <iostream> #define MAX_JUMP_HEIGHT 0.2f #define SPAWN_X -0.42f void Player::init(Space * s){ //INITIALIZING SPACE CLASS OBJECT space = s; spritePiece = 0.125f; } void Player::drawPlayer(){ glPushMatrix(); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, space->getWindow().getTexture(1)); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); //PART OF THE SPRITESHEET DRAWING COORDINATES glTexCoord2f(spritePart, 0.0f); if (strafeRight) { glVertex2f(playerX , playerY + 0.52f); } else { glVertex2f(playerX , playerY + 0.52f); } glTexCoord2f(spritePart + spritePiece, 0.0f); if (strafeRight) { glVertex2f(playerX + 0.13f, playerY + 0.52f); } else { glVertex2f(playerX - 0.13f, playerY + 0.52f); } glTexCoord2f(spritePart + spritePiece, 1.0f); if (strafeRight) { glVertex2f(playerX + 0.13f, playerY) ; } else { glVertex2f(playerX - 0.13f, playerY ); } glTexCoord2f(spritePart, 1.0f); if (strafeRight) { glVertex2f(playerX , playerY) ; } else { glVertex2f(playerX , playerY ); } glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glPopMatrix(); } void Player::move(){ chanceToMove++; if (!attacking){ //NORMAL WALK ANIMATION if (playerXSpeed != 0.0f) { if (spriteCount != sprites - 3) { //IF CURRENT PART IS NOT THE LAST PART if (chanceToMove % 4 == 0) { //SO THE ANIMATION IS NOT AS FAST AS SANIC IS spritePart += spritePiece; spriteCount++; } }else { spritePart = 0.0f; spriteCount = 0; } }else { spritePart = 0.0f; //ALSO RESET } }else { //ATTACKING spritePart = spritePiece * (sprites - 2); //ATTACK SPRITE projectileAttack(); if (times == 5) { attacking = false; times = 0; }else { times++; } } if (playerXSpeed < 0) { //IF PLAYER IS MOVING LEFT strafeRight = false; }else { strafeRight = true; //MOVING RIGHT } if (jumping) { jump(); } playerX += playerXSpeed; //UPDATING PLAYER POSITIONS playerY += playerYSpeed; } void Player::checkFalling() { if ((playerX < space->getGame().getPlatformLeft() - 0.1f || playerX > space->getGame().getPlatformRight() - 0.05f) && playerY < -0.4f) { //IF PLAYER JUMPED OFF THE PLATFORM ableToChangeY = false; playerYSpeed = -0.03f; }if (playerY < -2.0f) { //IF PLAYER FELL TO DEATH(RIP) space->getGame().stopGame(); } } void Player::setJumping(bool value){ jumping = value; } void Player::setAttacking(bool value){ attacking = value; } void Player::projectileAttack(){ } void Player::jump(){ spritePart = spritePiece * (sprites-1); //JUMPING SPRITE if (ableToChangeY) { //IF PLAYER IS NOT FALLING RIP if (playerY < MAX_JUMP_HEIGHT && !falling) { //WHILE THE PLAYER DID NOT PASS THE MAXIMUM JUMP HEIGHT playerYSpeed = 0.03f; }else { //IF THE PLAYER JUMPED TOO HIGH falling = true; if (playerY > SPAWN_X) { playerYSpeed = -0.03f; }else { //PLAYER IS BACK ON EARTH jumping = false; falling = false; playerYSpeed = 0.0f; } } } } void Player::setPlayerXSpeed(float speed){ playerXSpeed = speed; } float Player::getPlayerX() { return playerX; } float Player::getPlayerY(){ return playerY; } EDIT MAIN FUNCTION #include "Space.h" #include <iostream> #include <SDL2\SDL.h> #include <SDL2\SDL_opengl.h> #include <SDL2\SDL_ttf.h> #undef main int main(int argc, char** argv) { SDL_Init(SDL_INIT_EVERYTHING); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); TTF_Init(); Space space; space.init(); std::cout << "Type something and press ENTER to quit..." << std::endl; char temp; std::cin >> temp; TTF_Quit(); SDL_Quit(); return 0; }