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

Author Topic: Ignition Engine  (Read 10363 times)

0 Members and 1 Guest are viewing this topic.

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Ignition Engine
« on: January 08, 2014, 10:29:38 pm »
Hello!

I'm new to this forums, and a little green to SFML, but I wanted to post what I have so far in terms of a SFML engine. A lot of the code is from scratch, but a few parts like the camera class are based off of a tutorial I found on dreamincode:

Ignition engine:

#pragma once
#include <SFML\Graphics.hpp>
#include <exception>

////////////////////////////////////////////////////////////////////////////////////////////////
// Ignition 2D Engine v 1.01 ///////////////////////////////////////////////////////////////////
// Written in C++ & SFML by John Lawson ////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////


namespace Ignition
{       class Texture_Manager
        {       public:
                Texture_Manager();
                private:
                std::vector<sf::Texture*> Texture_list;
                public:
                void Add_texture(sf::Texture * iTexture);
                void Smooth_texture(unsigned int index, bool smooth);
            sf::Texture * Get_texture(unsigned int index);
                ~Texture_Manager();
        };

        class CSprite
        {       public:
                CSprite(sf::Texture * texture, float iox, float ioy);
                CSprite(sf::Texture * texture, float iox, float ioy, unsigned int a, unsigned int b, unsigned int c, unsigned int d);
                protected:
                sf::Sprite * Object_sprite;
                virtual void Frame(float dt);                           // Frame updater to be defined in derived classes.
                public:                                                                         // Similar virtual for checking whether the object is in       
                virtual bool In_render(sf::IntRect rBounds);    // the area to be drawn
                float Get_theta();
                sf::Vector2i Get_pos();
                float Get_x();
                float Get_y();
                void Set_theta(float itheta);
                void Set_position(float ix, float iy);
                void Colour_sprite(int red, int green, int blue, int alpha);
                void Colour_sprite(int red, int green, int blue);
                void Draw_sprite(int x, int y, sf::RenderWindow * rwindow);
                void Draw_sprite(sf::RenderWindow * rwindow);
                ~CSprite();    
        };

        class Camera
        {       public:
                Camera(unsigned int h, unsigned int w, unsigned int pofs_x, unsigned int pofs_y);
                Camera(unsigned int h, unsigned int w, unsigned int pofs_x, unsigned int pofs_y, CSprite * iTgt);
                Camera(unsigned int h, unsigned int w, float ispeed, unsigned int pofs_x, unsigned int pofs_y);
                Camera(unsigned int h, unsigned int w, float ispeed, unsigned int pofs_x, unsigned int pofs_y, CSprite * iTgt);
                void Translate_camera(int x,int y);
                void Translate_camera_center(int x, int y);
                void Camera_goto(int x,int y);                                                  // dont worry, not that kind of goto
                void Camera_center_goto(int x, int y);                                  // Sends the camera to a coordinate in "the world"
                void Update_camera();
                void Set_cam_tgt(sf::Vector2i iPos);
                sf::Vector2i* Get_cam_pos();
                sf::Vector2i* Get_cam_size();
                sf::Vector2i* Get_Cam_port_ofs();
                sf::IntRect Get_cam_window();
                CSprite * this_cTgt;
                private:
                sf::Vector2f * Cam_pos;
                sf::Vector2i * Cam_size;
                sf::Vector2f * Cam_tgt;
                sf::Vector2i * Cam_port_ofs;    // Offset from standard render position in the portal window
                float speed;                            // Not strictly necessary, but I may want the camera to have a "lag" motion behind the target, probably great for ConquerSpace
                public:                                         // velocity, speed, dammit. Must respect physics, augh!!!
                friend class Ignition_Engine;
                ~Camera();
        };

        class Portal
        {       public:
                Portal(unsigned int h, unsigned int w, int bpp, std::string wTitle);    // The cake is a lie, apparently.
                void Add_camera_view(Camera * iCam);    // Least, nobody ever gave me any for coding anything.
                sf::RenderWindow * pPortal;    
                std::vector<Camera*> Cam_views;
                public:
                ~Portal();                      // But this is a triumph :)
        };
       
        struct Portal_arg
        {       unsigned int h, w;
                int bpp;
                std::string ptitle;
        };

        class Ignition_Engine
        {       public:
                Ignition_Engine(void (*function)(Ignition_Engine* ithis));
                void Ignition(std::vector<std::string> Load_paths, unsigned int h, unsigned int w, int bpp, std::string wTitle);
                void Ignition(std::vector<std::string> Load_paths, std::vector<Portal_arg> Portal_args, unsigned int h, unsigned int w, int bpp, std::string wTitle);
            Texture_Manager Manager;
                std::vector<Camera*> Engine_cams;
                Portal * Main_portal;
                std::vector<Portal*> Sub_portals;
            void Load_texture(std::string file_path);
                void Register_sprite(CSprite * iSprite);             
                std::vector<CSprite*> Sprite_Objects;
                CSprite * eTgt;                 // The primary engine target (ie, usually the current player input that we want to follow);
                private:
                bool Start(unsigned int h, unsigned int w, int bpp, std::string wTitle);                                // Engine Start (The Engines are on!)          
                void Loop();                            // Main Loop()
                void Render_frame();            // {    Renders the graphical output
                void Process_input();           //              Handle user input
                void Update();                          //              Update program internals
                public:                                         // }
                ~Ignition_Engine(void);
        };
       
        void Construct_portal(unsigned int h, unsigned int w, int bpp, std::string wTitle, Ignition_Engine * this_engine);
}

#include "Ignition_Engine.h"
#include <math.h>
#include <vector>


// Ignition Engine ///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

Ignition::Ignition_Engine::Ignition_Engine(void (*function)(Ignition_Engine* ithis))
{       (*function)(this);      // Pass in the new arguments to the engine starting up
}

void Ignition::Ignition_Engine::Ignition(std::vector<std::string> Load_paths, unsigned int h, unsigned int w, int bpp, std::string wTitle)
{       if (!Start(h, w, bpp, wTitle))
        {       throw "Ignition_Failure";
        }
        else
        {       for (std::vector<std::string>::iterator it = Load_paths.begin(); it != Load_paths.end(); ++it)
                {       Load_texture(*it);
                }      
                Loop();
        }
}       // Lights this candle. Yeah baby. Yeah.

void Ignition::Ignition_Engine::Ignition(std::vector<std::string> Load_paths, std::vector<Portal_arg> Portal_args, unsigned int h, unsigned int w, int bpp, std::string wTitle)
{       if (!Start(h, w, bpp, wTitle))
        {       throw "Ignition_Failure";
        }
        else
        {       for (std::vector<std::string>::iterator it = Load_paths.begin(); it != Load_paths.end(); ++it)
                {       Load_texture(*it);
                }
                for (std::vector<Portal_arg>::iterator itArg = Portal_args.begin(); itArg != Portal_args.end(); ++itArg)
                {       Construct_portal(itArg->h, itArg->w, itArg->bpp, itArg->ptitle);
                }
                Loop();
        }
}       // Lights this candle. Yeah baby. Yeah.

void Ignition::Ignition_Engine::Load_texture(std::string file_path)
{       sf::Texture * Tex;      // Trustworthy files of course
        Tex = new sf::Texture();
        Tex->loadFromFile(file_path);
        Manager.Add_texture(Tex);
}       // Load a texture into the managed list

void Ignition::Ignition_Engine::Register_sprite(CSprite * iSprite)
{       Sprite_Objects.push_back(iSprite);
}       // Register a sprite... for iteration of members inheriting from parent class CSprite

bool Ignition::Ignition_Engine::Start(unsigned int h, unsigned int w, int bpp, std::string wTitle)
{       Main_portal = new Portal(Engine_cams, h, w, bpp, wTitle);
        if(!(Main_portal->pPortal))
        {       return false;
        }
        else
        {       return true;
        }
}

void Ignition::Ignition_Engine::Loop()
{       while(Main_portal->pPortal->isOpen())
        {       Process_input();
                Update();
                Render_frame();
        }
}

void Ignition::Ignition_Engine::Render_frame()
{       for (std::vector<Portal*>::iterator it = Sub_portals.begin(); it != Sub_portals.end(); ++it)
        {       (*it)->pPortal->clear();
        }       Main_portal->pPortal->clear();
        sf::Vector2i * rend_ofs;
        for (std::vector<Portal*>::iterator itPortal = Sub_portals.begin(); itPortal != Sub_portals.end(); ++itPortal)
        {       for (std::vector<Camera*>::iterator itCamera = (*itPortal)->Cam_views.begin(); itCamera != (*itPortal)->Cam_views.end(); ++itCamera)
                {       if(!((*itCamera)->Cam_tgt))
                        {       (*itCamera)->this_cTgt = eTgt;
                                (*itCamera)->Cam_tgt = new sf::Vector2f(eTgt->Get_pos());
                        }
                        for (std::vector<CSprite*>::iterator itSprites = Sprite_Objects.begin(); itSprites != Sprite_Objects.begin(); ++itSprites)
                        {       if ((*itSprites)->In_render((*(*itCamera)->Get_cam_window())) == true)
                                {       rend_ofs = new sf::Vector2i( *((*itCamera)->Get_Cam_port_ofs()) + ((*itSprites)->Get_pos()) );
                                        (*itSprites)->Draw_sprite((rend_ofs)->x, (rend_ofs)->y, (*itPortal)->pPortal);
                                        delete  rend_ofs;
                                }      
                        }
                }
        }
}

void Ignition::Ignition_Engine::Process_input()
{       sf::Event Input_Events;
        while(Main_portal->pPortal->pollEvent(Input_Events))
        {       if (Input_Events.type == sf::Event::Closed)
                {       this->~Ignition_Engine();
                }
        }
}

void Ignition::Ignition_Engine::Update()
{
}

Ignition::Ignition_Engine::~Ignition_Engine(void)
{       for (std::vector<CSprite*>::iterator it = Sprite_Objects.begin(); it != Sprite_Objects.end(); ++it)
        {       delete *it;
        }       Sprite_Objects.clear();
        Manager.~Texture_Manager();
        for (std::vector<Portal*>::iterator itPortal = Sub_portals.begin(); itPortal != Sub_portals.end(); ++itPortal)
        {       delete (*itPortal);
        }       delete Main_portal;
}




// Ignition::Texture manager class ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

Ignition::Texture_Manager::Texture_Manager()
{
}

void Ignition::Texture_Manager::Add_texture(sf::Texture * iTexture)
{       Texture_list.push_back(iTexture);
}

void Ignition::Texture_Manager::Smooth_texture(unsigned int index, bool smooth)
{       Texture_list[index]->setSmooth(smooth);
}

sf::Texture * Ignition::Texture_Manager::Get_texture(unsigned int index)
{       return Texture_list[index];    
}

Ignition::Texture_Manager::~Texture_Manager()
{       for(std::vector<sf::Texture*>::iterator it = Texture_list.begin(); it != Texture_list.end(); ++it)
        {       delete *it;
        }       Texture_list.clear();
}




// Ignition::Sprite parent class /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

Ignition::CSprite::CSprite(sf::Texture * texture, float iox, float ioy)
{       Object_sprite = new sf::Sprite();
        Object_sprite->setTexture(*texture);
        Object_sprite->setOrigin(iox, ioy);     // Reset the origin by given coordinates
}       // Constructs the Tile object and assigns it the texture that it uses

Ignition::CSprite::CSprite(sf::Texture * texture, float iox, float ioy, unsigned int a, unsigned int b, unsigned int c, unsigned int d)
{       Object_sprite->setTexture(*texture);
        Object_sprite->setTextureRect(sf::IntRect(a, b, c, d)); // Explicitly defining the texture coordinates of the sprite in the given texture
        Object_sprite->setOrigin(iox, ioy);     // Reset the origin by given coordinates
}       // Constructs the Tile object and assigns it the texture that it uses

float Ignition::CSprite::Get_theta()
{       return (Object_sprite->getRotation());
}       // Get the rotation of the sprite as float.

sf::Vector2i Ignition::CSprite::Get_pos()
{       sf::Vector2i pos((int)Get_x(),(int)Get_y());
        return pos;
}

float Ignition::CSprite::Get_x()
{       return (Object_sprite->getPosition().x);
}

float Ignition::CSprite::Get_y()
{       return (Object_sprite->getPosition().y);
}

void Ignition::CSprite::Set_theta(float itheta)
{       Object_sprite->setRotation(itheta);
}

void Ignition::CSprite::Set_position(float ix, float iy)
{       Object_sprite->setPosition(ix, iy);
}

void Ignition::CSprite::Colour_sprite(int red, int green, int blue, int alpha)
{       Object_sprite->setColor(sf::Color(red, green, blue, alpha));
}

void Ignition::CSprite::Colour_sprite(int red, int green, int blue)
{       Object_sprite->setColor(sf::Color(red, green, blue));
}

void Ignition::CSprite::Draw_sprite(int x, int y, sf::RenderWindow * rwindow)
{       Object_sprite->setPosition(x, y);
    rwindow->draw(*Object_sprite);
}

void Ignition::CSprite::Draw_sprite(sf::RenderWindow * rwindow)
{       rwindow->draw(*Object_sprite);
}

Ignition::CSprite::~CSprite()
{       delete Object_sprite;
}



// Ignition::Portal class ////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

Ignition::Portal::Portal(unsigned int h, unsigned int w, int bpp, std::string wTitle)
{       pPortal = new sf::RenderWindow(sf::VideoMode(w, h, bpp), wTitle);
}

void Ignition::Portal::Add_camera_view(Camera * iCam)
{       Cam_views.push_back(iCam);
}

Ignition::Portal::~Portal()
{       Cam_views.clear();
        pPortal->close();
        delete pPortal;
}      




// Ignition::Camera class ////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

Ignition::Camera::Camera(unsigned int h, unsigned int w, unsigned int pofs_x, unsigned int pofs_y)
{       Cam_size = new sf::Vector2i(w, h);
        Cam_pos = new sf::Vector2f(0.000, 0.000);
        Cam_port_ofs = new sf::Vector2i(pofs_x, pofs_y);
        speed = 1.000;
}

Ignition::Camera::Camera(unsigned int h, unsigned int w, unsigned int pofs_x, unsigned int pofs_y, CSprite * iTgt)
{       Cam_size = new sf::Vector2i(w, h);
        Cam_pos = new sf::Vector2f(0.000, 0.000);
        Cam_port_ofs = new sf::Vector2i(pofs_x, pofs_y);
        speed = 1.000;
        this_cTgt = iTgt;
        Cam_tgt = new sf::Vector2f((this_cTgt->Get_pos()));
}

Ignition::Camera::Camera(unsigned int h, unsigned int w, float ispeed, unsigned int pofs_x, unsigned int pofs_y)
{       Cam_size = new sf::Vector2i(w, h);
        Cam_pos = new sf::Vector2f(0.000, 0.000);
        Cam_port_ofs = new sf::Vector2i(pofs_x, pofs_y);
        speed = ispeed;
}

Ignition::Camera::Camera(unsigned int h, unsigned int w, float ispeed, unsigned int pofs_x, unsigned int pofs_y, CSprite * iTgt)
{       Cam_size = new sf::Vector2i(w, h);
        Cam_pos = new sf::Vector2f(0.000, 0.000);
        Cam_port_ofs = new sf::Vector2i(pofs_x, pofs_y);
        speed = ispeed;
        this_cTgt = iTgt;
        Cam_tgt = new sf::Vector2f((this_cTgt->Get_pos()));
}

void Ignition::Camera::Translate_camera(int x, int y)
{       Cam_pos->x = (float)x;
        Cam_pos->y = (float)y;
        Cam_tgt = Cam_pos;
}

void Ignition::Camera::Translate_camera_center(int x, int y)
{       x -= ((Cam_size->x)/(2));
        y -= ((Cam_size->y)/(2));
        Cam_pos->x = (float)x;
        Cam_pos->y = (float)y;
        Cam_tgt = Cam_pos;
}

void Ignition::Camera::Camera_goto(int x, int y)
{       Cam_tgt->x = (float)x;
        Cam_tgt->y = (float)y;
}

void Ignition::Camera::Camera_center_goto(int x, int y)
{       x -= ((Cam_size->x)/(2));
        y -= ((Cam_size->y)/(2));
        Cam_tgt->x = x;
        Cam_tgt->y = y;
}

void Ignition::Camera::Update_camera()
{       struct coords
        {       float l, dl;
        }x, y, d;
        x.l = (float)(Cam_tgt->x - Cam_pos->x);
        y.l = (float)(Cam_tgt->y - Cam_pos->y);
        if (d.l <= 1)
        {       Cam_pos = Cam_tgt;
        }       // The snap-to case when the locations are close enough. Not really sure if this is worth it, but maybe overshooting is a problem otherwise
        else
        {       d.l = sqrt((pow(x.l, 2))+(pow(y.l, 2)));
                d.dl = (((d.l)*(speed))/60);
                if (d.dl < 1.0f)
                {       d.dl = 1.0f;
                }
                x.dl = ((x.l)*(d.dl/d.l));              // Similar triangles method
                y.dl = ((y.l)*(d.dl/d.l));              // to get v components
                Cam_pos->x += x.dl;
                Cam_pos->y += y.dl;
        }
}

void Ignition::Camera::Set_cam_tgt(sf::Vector2i iPos)
{       Cam_tgt->x = iPos.x;
        Cam_tgt->y = iPos.y;
}

sf::Vector2i* Ignition::Camera::Get_cam_pos()
{       sf::Vector2i * output = new sf::Vector2i((int)((Cam_pos)->x),(int)((Cam_pos)->y));
        return output;
}

sf::Vector2i* Ignition::Camera::Get_cam_size()
{       return Cam_size;
}

sf::Vector2i* Ignition::Camera::Get_Cam_port_ofs()
{       return Cam_port_ofs;
}

sf::IntRect Ignition::Camera::Get_cam_window()
{       sf::IntRect cWindow((Cam_pos->x),(Cam_pos->y),(Cam_size->x),(Cam_size->y));
        return cWindow;
}

Ignition::Camera::~Camera()
{       delete Cam_tgt;
        delete Cam_size;
        delete Cam_pos;
        delete Cam_port_ofs;
}




// Ignition Engine - Functions() /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

void Ignition::Construct_portal(unsigned int h, unsigned int w, int bpp, std::string wTitle, Ignition_Engine * this_engine)
{       Portal * iPort = new Portal(h, w, bpp, wTitle);
        this_engine->Sub_portals.push_back(iPort);
}

Any thoughts on the progress so far are welcome :)
Quote
The computer is mightier than the pen, the sword, and usually the programmer.

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re: Ignition Engine
« Reply #1 on: January 08, 2014, 10:41:15 pm »
I think its more valuable to post small videos and demonstrations of what you can do with it, rather than posting all that code! But by all means keep working ^^

Its like, no one wants to look at an engine of a car, without the actual car it goes inside :p

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Re: Ignition Engine
« Reply #2 on: January 08, 2014, 10:47:26 pm »
Fair enough, I just wanted to see if anyone had any thoughts on the quality of the work so far. Most of it I feel confident about, but its still untested. I'll see if I can get something running in a little bit.
Quote
The computer is mightier than the pen, the sword, and usually the programmer.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Ignition Engine
« Reply #3 on: January 08, 2014, 10:54:10 pm »
Since you only show code, that's all we can judge -- and to be honest, there are several flaws: Memory leaks, unnecessary copies, no use of RAII (why don't you copy 2D vectors?), ignoring the rule of three, hungarian notation, inconsistent naming, code duplication...

I recommend to have a look at a list of C++ advice I recently put together. By reading the tips, you can improve your code a lot.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Re: Ignition Engine
« Reply #4 on: January 08, 2014, 11:00:33 pm »
Leaks? Where? I thought I had that covered completely, but apparently not.

Thanks for the link, will read  :)
Quote
The computer is mightier than the pen, the sword, and usually the programmer.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Ignition Engine
« Reply #5 on: January 08, 2014, 11:08:33 pm »
The caller has to invoke delete when using your getters. That's never a good idea.

If you have to think whether you have covered leaks, then you have already done something wrong. The intent behind RAII is to automate memory management completely, so that the programmer doesn't have to wrap his head around it and can instead focus on important things.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Re: Ignition Engine
« Reply #6 on: January 08, 2014, 11:20:24 pm »
Ack, yes

How does this sound:

sf::Vector2i Ignition::Camera::Get_cam_size()
{       return *Cam_size;
}
Quote
The computer is mightier than the pen, the sword, and usually the programmer.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Ignition Engine
« Reply #7 on: January 09, 2014, 12:24:13 am »
The return type is better, but the member variable is still bad. There is no reason to use pointers in the first place. And your method should be const-qualified.

Please read about RAII (e.g. on Wikipedia) and automatic memory management, it's a crucial part of C++.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

BruceJohnJennerLawso

  • Jr. Member
  • **
  • Posts: 55
    • View Profile
    • My Code on Github
Re: Ignition Engine
« Reply #8 on: January 10, 2014, 10:22:13 pm »
Reading up about RAII, but very confused about mutex. I kinda get what std::unique_ptr does by self deleting once out of scope, but mutex locks something then releasing what... ???  :o

Is there anything that can be done to salvage the engine at this point, or is it a lost cause? I would really like to get it to a marginally useable state in order to play with it just once.
Quote
The computer is mightier than the pen, the sword, and usually the programmer.

Grimshaw

  • Hero Member
  • *****
  • Posts: 631
  • Nephilim SDK
    • View Profile
Re: Ignition Engine
« Reply #9 on: January 11, 2014, 04:50:55 am »
Please try not to overuse the word game engine :p Right now its just a couple of files, I am sure you can refactor whats needed and make it smooth! Keep learning and improving it or start again if you prefer. No big losses yet! :)

Matt Guerrette

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Ignition Engine
« Reply #10 on: January 11, 2014, 06:14:29 am »
Just some input. You should really be using const qualified getters. something like

const sf::Vector2i& Ignition::Camera::Get_cam_size() const
{  
     return *Cam_size;
}
 

Thats just my two cents. That way the return value cannot be modified by the user and your intentions are clear as to what this getter is for. *im assuming just to return the size for info not for modification*

Using pointers is dangerous, so I would recommend return by const correct reference wherever you can and think it would make since.

Write set methods for actually setting the values.

Also, i noticed this line

Manager.~Texture_Manager();

Just call delete...or use
std::uniqure_ptr<Texture_Manager> Manager
and it will
auto delete when out of scope.

Here put this namespace somewhere in your engine for use. Its what I use for memory management of
pointers in replace of delete

namespace Memory
{
        //Due to comments below, I've removed the check for value before delete
        template <class T> void SafeDelete(T& t)
        {
                delete t;
                t = nullptr;
        }

       
        template <class T> void SafeRelease(T& t)
        {
                if(t)
                {
                        t->Release();
                        t = nullptr;
                }
        }
}



There is more, but i think that will give you a start. Cheers!
« Last Edit: January 11, 2014, 07:17:18 pm by Matt Guerrette »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Ignition Engine
« Reply #11 on: January 11, 2014, 02:51:39 pm »
I don't recommend the SafeDelete() function template, because it's a weak solution to a non-existing problem and because it hides logic errors. If you attempt to delete a pointer multiple times, that's a bug which should be noticed, not ignored. Plus, the if (t) has absolutely no effect.

Anyway, I don't see a reason why you don't use std::unique_ptr -- it's almost always superior to new and delete. Even in the case of Release() you can construct a custom deleter and thereby apply the RAII idiom.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Matt Guerrette

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Ignition Engine
« Reply #12 on: January 11, 2014, 05:55:11 pm »
I don't recommend the SafeDelete() function template, because it's a weak solution to a non-existing problem and because it hides logic errors. If you attempt to delete a pointer multiple times, that's a bug which should be noticed, not ignored. Plus, the if (t) has absolutely no effect.

Anyway, I don't see a reason why you don't use std::unique_ptr -- it's almost always superior to new and delete. Even in the case of Release() you can construct a custom deleter and thereby apply the RAII idiom.

Exactly, that why i specifically said "in replace of delete", it would be much preferred he use smart pointers seeing as its 2014 now...not 1995.

Also, just so you know. It is completely safe to delete a nullptr object from what I can tell. Multiple deletions of a nullptr will do nothing. It is not an error in modern c++.
« Last Edit: January 11, 2014, 06:02:03 pm by Matt Guerrette »

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Ignition Engine
« Reply #13 on: January 11, 2014, 06:39:32 pm »
Quote
Also, just so you know. It is completely safe to delete a nullptr object from what I can tell. Multiple deletions of a nullptr will do nothing. It is not an error in modern c++.
We know but the question is why do you post code that checks for null before deleting?
Back to C++ gamedev with SFML in May 2023

Matt Guerrette

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Ignition Engine
« Reply #14 on: January 11, 2014, 07:10:01 pm »
Quote
Also, just so you know. It is completely safe to delete a nullptr object from what I can tell. Multiple deletions of a nullptr will do nothing. It is not an error in modern c++.
We know but the question is why do you post code that checks for null before deleting?

Just a habit I picked up when I started learning C++ a while back. My background is in DX programming and you'll find rather quickly why that matters. Most of the resources for learning DirectX from the past decade used either the template functions I posted, or a SAFE_DELETE macro such as this

#define SAFE_DELETE(x) { if(x) delete x; x=NULL; }

These books are written by professionals who coded long before smart pointers, and it was a time where deleting a null value WAS actually dangerous and ill advised hence the check. Nowadays the C++ standard removes need for unnecessary checks.

I only keep these template functions around for DX programming because from what I can tell, it is not safe to use C++11 smart pointers due to reference counting issues, and I don't want to clutter my code with both C++11 smart pointers and COM smart pointers.


That is all. Sorry I wasn't clear before.
« Last Edit: January 11, 2014, 07:37:56 pm by Matt Guerrette »