Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: game crashing on draw. Possibly because of pointers.  (Read 2508 times)

0 Members and 1 Guest are viewing this topic.

ka0s420

  • Jr. Member
  • **
  • Posts: 56
    • View Profile
    • Email
game crashing on draw. Possibly because of pointers.
« on: February 13, 2016, 05:01:44 am »
Hello all, this is probably a fairly length bit of code for a forum post, so I do aplogise, but if anyone could help me figure out why this is crashing, I'd be very appreciative  ;)

okay, player headder file and cpp:
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <vector>
#include "laserBeam.h"

class Player
{
public:
        int x;
        int y;
        sf::CircleShape shape;
        sf::Texture frame1;
        sf::Texture frame2;
        sf::Texture frame3;
        sf::Sprite sprite;
        sf::SoundBuffer buffer;
        sf::Sound sound;
        std::vector <Laser*> shots;
        int count;
        void move();
        void getAngle(sf::Vector2f mouse);
        Player(int xI, int yI, sf::CircleShape iconI);
        Player() {};
        ~Player();
       
};

#include <SFML/Graphics.hpp>
#include "Player.h"

void Player::move()
{
        float x = this->sprite.getPosition().x;
        float y = this->sprite.getPosition().y;
        float xR = sin((this->sprite.getRotation()*3.14159265 / 180)) * 3;
        float yR = cos((this->sprite.getRotation()*3.14159265 / 180))* -3;
        this->sprite.setPosition(x + xR, y + yR);
        switch(this->count){
                case 0:
                        this->sprite.setTexture(this->frame1);
                        this->sound.play();
                        break;
                case 6:
                        this->sprite.setTexture(this->frame2);
                        this->sound.play();
                        break;
                case 12:
                        this->sprite.setTexture(this->frame3);
                        this->sound.play();
                        break;
        }
        this->count++;
        if (this->count == 19) {
                this->count = 0;
        }
}

void Player::getAngle(sf::Vector2f mouse)
{
       
        float angle = atan2(mouse.y - this->sprite.getPosition().y, mouse.x - this->sprite.getPosition().x);
        angle = ((angle * 180) / 3.14159265) + 90;
        {
                angle = 360 - (-angle);
        }
       
        this->sprite.setRotation(angle);
       


}

Player::Player(int xI, int yI, sf::CircleShape iconI)
{
        this->shape = iconI;
        this->x = xI;
        this->y = yI;
        this->count = 0;
        this->frame1.loadFromFile("playerU.png");
        this->frame2.loadFromFile("playerU1.png");
        this->frame3.loadFromFile("playerU2.png");
        this->buffer.loadFromFile("conStep.wav");
        this->sprite.setTexture(this->frame1);
        this->sound.setBuffer(buffer);
        this->sprite.setOrigin(this->sprite.getGlobalBounds().width / 2, this->sprite.getGlobalBounds().height / 2);




}
Player::~Player()
{
}

okay so that's the player class etc, here is the laser class header and cpp:
#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

class Laser
{
public:
        sf::Texture texture;
        sf::Sprite sprite;
        int speed;
        sf::Vector2i startPoint;
        sf::SoundBuffer buffer;
        sf::Sound sound;
        void move(std::vector <Laser*> shots);
        bool operator == (const Laser& rh)const;
        Laser(float rot, int spd, sf::Vector2i pos);
        Laser() {};
        ~Laser();
};

#include "laserBeam.h"
#include <iostream>
#include <algorithm>

void Laser::move(std::vector <Laser*> shots)
{
        float x = this->sprite.getPosition().x;
        float y = this->sprite.getPosition().y;
        float xR = sin((this->sprite.getRotation()*3.14159265 / 180)) * this->speed;
        float yR = cos((this->sprite.getRotation()*3.14159265 / 180))* -this->speed;
        this->sprite.setPosition(x + xR, y + yR);
       
        float dX = this->sprite.getPosition().x - this->startPoint.x;
        float dY = this->sprite.getPosition().y - this->startPoint.y;
        float dist = hypotf(dX, dY);
        if (dist > 32) {
                int index = -1;
                for (int i = 0; i < shots.size(); i++) {
                        std::cout << this << " " << &shots[i] << std::endl;
                        if (*this == *shots[i]) {
                                std::cout << "found match" << std::endl;
                                index = i;
                                break;
                        }
                }
                if (index >= 0) {
                        shots.erase(shots.begin() + index);
                }
               
               
        }
       
}

bool Laser::operator==(const Laser&  rh) const
{
        return (this == &rh);
}

Laser::Laser(float rot, int spd, sf::Vector2i pos)
{
        this->texture.loadFromFile("laser.png");
        this->sprite.setTexture(this->texture);
        this->sprite.setOrigin(this->sprite.getGlobalBounds().width/2, this->sprite.getGlobalBounds().height/2);
        this->sprite.setRotation(rot);
        this->sprite.setPosition(pos.x, pos.y);
        this->startPoint = pos;
        this->speed = spd;
        this->buffer.loadFromFile("target.wav");
        this->sound.setBuffer(buffer);
        this->sound.play();
       

}

Laser::~Laser()
{

}
 
and now the main cpp:
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "Player.h"
#include "builder.h"
#include "laserBeam.h"
#include <iostream>
#include <string>
#include <vector>

int main()
{
        sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML works!");
        sf::CircleShape shape;
        Player p(100, 100, shape);
        Builder w(32, 640, 640);
        p.shape.setFillColor(sf::Color(75, 0, 130));
        p.shape.setRadius(20.f);
        p.shape.setPosition(sf::Vector2f(p.x, p.y));
        sf::Font font;
        font.loadFromFile("arial.ttf");
        sf::Text words;
        words.setFont(font);
        words.setString(sf::String("some words n shit"));
        words.setPosition(sf::Vector2f(100, 100));
        words.setColor(sf::Color(255,255,255));
        window.setFramerateLimit(60);
        sf::View view1(sf::FloatRect(p.x, p.y, 600, 600));
       
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed) {
                                window.close();
                        }
                        else if (event.type == sf::Event::MouseButtonReleased) {
                                if (event.mouseButton.button == sf::Mouse::Left) {
                                        std::cout << "mouse click" << std::endl;
                                        float rot = p.sprite.getRotation();
                                        int spd = 6;
                                        sf::Vector2i pos;
                                        pos = sf::Vector2i(p.sprite.getPosition());
                                        Laser l(rot, spd, pos);
                                        Laser * ptr;
                                        ptr = &l;
                                        p.shots.push_back(ptr);
                                }
                        }
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
                        p.move();
                }
                if (!sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
                        p.sprite.setTexture(p.frame1);
                        p.count = 0;
                }

                view1.setCenter(p.sprite.getPosition().x, p.sprite.getPosition().y);
                window.setView(view1);
                sf::Vector2i mouse = sf::Mouse::getPosition(window);
                sf::Vector2f worldPos = window.mapPixelToCoords(mouse);
                p.getAngle(worldPos);
                for (int i = 0; i < p.shots.size(); i++) {
                        (*p.shots[i]).move(p.shots);
                }
                window.clear();
                window.draw(w.floorSprite);
                for (int i = 0; i < p.shots.size(); i++) {
                        (*p.shots[i]).sprite.setTexture((*p.shots[i]).texture);
                        window.draw((*p.shots[i]).sprite);
                }
                window.draw(p.sprite);
                window.draw(words);
                window.display();
        }

        return 0;
}

So yeah, I just included what I thought was relevant. There is another class, but that's for building the map and has worked fine from the start. The problem is when i try and draw a laser from the 'p.shots' vector. It is a dereferenced pointer, and everything else works when i comment out the draw call. again, any help would be appreciated. Thanks for your time!

AlexxanderX

  • Full Member
  • ***
  • Posts: 128
    • View Profile
    • AlexanderX
Re: game crashing on draw. Possibly because of pointers.
« Reply #1 on: February 13, 2016, 07:55:44 am »
Maybe use some debug tools and maybe post a complete and minimal code.
Here you can find my blog and tutorials about SFML - http://alexanderx.net/ (died...) - http://web.archive.org/web/20160110002847/http://alexanderx.net/

Brax

  • Newbie
  • *
  • Posts: 39
  • Wannabe C++ Game Developer
    • View Profile
Re: game crashing on draw. Possibly because of pointers.
« Reply #2 on: February 13, 2016, 01:46:16 pm »
This:

if (event.mouseButton.button == sf::Mouse::Left) {
    // Blah, Blah...
    Laser l(rot, spd, pos);     // Object is created;
    Laser * ptr;                // Pointer is created;
    ptr = &l;                   // Pointer points to the memory address of the object;
    p.shots.push_back(ptr);     // Pointer is stored inside the vector in the player class (std::vector<Laser*>)

} // Here things go wrong: The object that pointer points to is destroyed here because it left scope. Pointer is now nullptr.

 

One of the solutions to your problem is to make pointers own their own memory using std::unique_ptr<...>. Access them by including "memory.h".
Most likely you will have to change your own std::vector<Laser*> into std::vector<std::unique_ptr<Laser>>.

Another solution would be simply to not use pointers at all: You already use std::vector, it can store objects instead of pointers. Each time you release mouse button, you should make a object and that object store (copy) into the vector.

That should take care of your problem.

For everything else (or if your problem persists), next time post complete and minimal example and description of the error.


Also, couple of remarks:

1. There is no point to use "this->" inside classes;
2. Call pointer member objects by using "->" operator, instead of "(*Typename)." It makes the code more readable.
3. If default constructors and destructors do not have code in their own declaration, there is no point to explicitly initialize them. This can also be problematic, because you can by accident call the empty constructor and all the members then will be uninitialized;

There a couple of more things too, but these fell under my eye. ;D

ka0s420

  • Jr. Member
  • **
  • Posts: 56
    • View Profile
    • Email
Re: game crashing on draw. Possibly because of pointers.
« Reply #3 on: February 14, 2016, 05:23:29 am »
Thank you very much for your help. I tried using smart pointers but that didnt fix the issue, I had used just raw objects to start with (pointers are scary) but no matter what, I couldn't get the laser to find itself in the vector. I had an idea that it was because the vector copied them, thus changing their memory addresses, although that makes no sense, lol, as well, I'm sure you can imagine.  :-[

In the end, I went back to using raw objects, but instead of having my code for checking distance in the Laser class, I made a function for it the player class, which is where the vector of lasers was stored anyway. This basically stopped it from going out of scope. And instead of searching the vector for itself, I just poll the vector now to check if the lasers need removing.

So its working, at last. thanks again, you got me on the right track for sure.