Advice on global variables

Started by
48 comments, last by Nathan Baum 17 years ago
No, they don't have to. Group all their usage as part of a single class, which will be responsible for storing and using them. Then, initialize an instance of that class and pass the values to it.
Advertisement
hi ToohrVyk,

Yeah that's what I'm looking for.

I'm not sure what 'TheUnbeliever' was getting at, just sounded too simplified.

ok so I define a class

class Cwindow{  public:    bool  fullscreen;	    int   scrWidth;		    int   scrHeight;	    int   scrBitDepth;};    



//Then create an instance: Cwindow myWindow;//And assign some values:  myWindow.scrWidth = 1024;  myWindow.scrHeight = 768;//and use them: CreateGLWindow(WND_TITLE, myWindow.scrWidth, myWindow.scrHeight) // in main


What have I achieved apart from more code ?


And thinking that main.cpp is just the loop pretty much.
(init, loop (game state/render) , kill)

That still doesn't give me access to these variables from other units.
depending on time/level/state would depend where I am .. intro.cpp, level1.cpp, level2.cpp, credits.cpp
It's not until we have fallen, we realize how much it hurts !
Actually, you'd define a class which moderately encapsulates its properties:

class Window {  std::string title;  int width, height;public:  Window(const std::string & title, int width,int height)   :    title(title), width(width), height(height)  {    CreateGLWindow(title.c_str(), width, height);    // Other details related to creating a window     // with these properties  }  void Resize(int width,int height)  {    this->width = width;    this->height = height;    // Handle other details of resizing  }    int Width() const { return width; }  int Height() const { return height; }  ~Window()  {    // Destroy a window with these properties  }};


Then, you use it:

Window myWindow("The window title",1024,768);Renderer myRenderer(myWindow);World myWorld(myRenderer);myWorld.load("1.lvl");


EDIT:
intro.cpp, credits.cpp — no reason to know the width and heigth as global variables. Just pass it a target window.
level1.cpp, level2.cpp — why would you need width and height at all?
Quote:
What have I achieved apart from more code?


You have achieved that the Window width&height are not accessible by anywhere, but only by modules related to CWindow. Your code is more organized, easier to extend, and if you get some kind of bug/problem with width&height, you know where to look(Window class), instead of the whole program.

Btw, I would implement CWindow like this(Assuming that CreateGLWindow is modified to return an HWND value instead of storing it in a global):

class Window{private:	    int   scrWidth;		    int   scrHeight;	    int   scrBitDepth;    HWND hwnd;    std::string title;public:	Window(std::string title,int width,int height,int depth):title(title),srcWidth(width),srcHeight(height),srcBitDepth(depth)	{		hwnd=CreateGLWindow(title,width,height);	}};


And just use it like this:

Window mywindow("My window",1024,768);

-EDIT: Beaten...
maybe someone could share a sample project (visual studio) to render an OpenGL blank Window, with this kind of structure or framework.

I'm not looking for anyone to write a game for me, but I need a framework to learn from, I will pick it up better like that.

NeHe's tutorials are so out-dated, half the other examples are ALL (or mixing) C and C++.

No real problem, with the game logic, and openGL, I guess just getting to grips with this C++, and 'better' programming skills is what I need.

Don't get me wrong I have a very functional openGL program, cameras, lighting, music, sound FX, crosshairs, HUD, fonts, the works.

The more I read, I am realizing some of my programming methods might not be the best ;-)

So if anyone is kind enough to share a good structured framework.
Just as we have been discussing, no globals, better class/structures.
(and I've been using chars* not strings) slap on the wrist.

I would appreciate it ;-)
It's not until we have fallen, we realize how much it hurts !
Original post by dazedandconfused
typedef struct sWindow{  bool    fullscreen;		  int     scrWidth;		  int     scrHeight;		  int     scrBitDepth;	} myWindow;

You and others in this thread seem not to understand what this code actually does.

It creates a struct called sWindow, and creates a global instance of that stuct called myWindow. Except that it is global to each file that includes it, but not to all all the files together. And it is still possible to create other instances of sWindow.

That is surely not what you want.

And as has been mentioned, the "typedef" is superfluous there in C++.
Quote:Original post by King Mir
It creates a struct called sWindow, and creates a global instance of that stuct called myWindow.


It does no such thing. It creates a struct named sWindow - and creates a typedef to that struct named myWindow. It instantiates nothing.

i.e.

typedef struct sWindow{  bool    fullscreen;		  int     scrWidth;		  int     scrHeight;		  int     scrBitDepth;	} myWindow;int main(){    sWindow foo;   // Fine    myWindow bar;  // Fine    myWindow.scrWidth = 800; // Error! myWindow is a type - not an object}


Indeed, it is equivalent to:

struct sWindow{  bool    fullscreen;		  int     scrWidth;		  int     scrHeight;		  int     scrBitDepth;	};typedef sWindow myWindow;


EDIT 1305BST 25/03/07: Typo

[Edited by - TheUnbeliever on March 25, 2007 6:15:34 AM]
[TheUnbeliever]
No wonder we get confused in this place !!

(no offence to GameDev by that [wink])

But do you see my point, some of you guys have been members of this forum for 3-5 years.

Who's advice should we take.

I appreciate everyone's help, wiithout a doubt, trust me.

And multiple opinions and advice is better than one.
Which is why I'd rather hear it from you "seasoned pro's", instead of just reading the word of one author in a book.

But what do I do [headshake]

Note: ok let's forget the 'C' or 'C++' debate, I followed some old code.
I'm working on C++ to clear things up, if I have made mistakes, I'm working on rectifying that. Hence why I'm here.

Let's work on the problem assuming I'm trying to code in C++

Cheers ;-)
It's not until we have fallen, we realize how much it hurts !
In this particular instance, King Mir is wrong, period. He's not far from being right; he just misunderstood the meaning of the typedef keyword in this context, possibly because he isn't familiar with this (somewhat strange) idiom, which does not exist in C++. In situations like this, of course, you can just test it out yourself and see.

In the larger question of "who should you trust" there's no easy answer, unfortunately. Opinions over software engineering which don't come down to actual syntactic meaning are just that: opinions. Try stuff out for yourself, keep an open mind, never assume you know everything.
ok to keep things simple this just uses the console and im typing it in here without testing so if theres bug's sorry but you should be able to get the basic idea from it.

Edit: i should mention, its the example you asked for above demonstrating how I avoid globals etc..

//main.cpp#include "renderer.h"#include "game_world.h"#include <iostream>int main(){    // create a renderer that renders to a window 80 * 40 in size    renderer renderer(std::cout, 80, 40);    game_world game(renderer, std::cin);    game.run();}


// renderer.h#include "vertex.h"#include <boost/utility/non_copyable.hpp>#include <vector>#include <iostream>struct renderer : boost::non_copyable{    typedef std::ostream window_type;    renderer(window_type& window, std::size_t width, std::size_t height);    void point(vertex v);    void line(vertex v1, vertex v2);    void triangle(vertex v1, vertex v2, vertex v3);    void square(vertex top_left, std::size_t size);    void rectangle(vertex top_left, vertex bottom_right);    void text(std::size_t x, std::size_t y, const std::string text);     std::size_t screen_width();    std::size_t screen_height();    void bitblt();private:    typedef std::vector<char> row_type;    typedef std::vector<row_type> buffer_type;    struct point_drawer    {        point_drawer(renderer& renderer, std::size_t x, std::size_t y):        renderer(&renderer),        x(x),        y(y)        { }        void operator()(vertex::color_type c)        {            renderer->point(vertex(x++, y, c));        }    };    buffer_type buffer;    window_type& window;    static void clear_row(row_type& row);    static void display_row(const row_type& row, window_type& window)};


// renderer.cpp#include "renderer.h"#include <algorithm>#include <iterator>renderer::renderer(renderer::window_type window, std::size_t width, std::size_t height):window(window){    // allocate height rows    buffer.resize(height);    // and resize each row to be width units wide    std::for_each(buffer.begin(),                   buffer.end(),                  std::bind2nd(std::mem_fn(&buffer_type::resize), width));    // clear the back buffer    std::for_each(buffer.begin(),                  buffer.end(),                  &clear_row);}void renderer::point(vertex v){    if (v.x < screen_width() && v.y < screen_height())    {        buffer[v.y][v.x] = v.color;    }}void renderer::line(vertex v1, vertex v2){    // http://en.wikipedia.org/wiki/Bresenham's_line_algorithm    bool steep = std::abs(v2.y - v1.y) < std::abs(v2.x - v1.x);    if (steep)    {        std::swap(v1.x, v1.y);        std::swap(v2.x, v2.y);    }    if (v1.x > v2.x)    {        std::swap(v1, v2);    }    int delta_x = v2.x - v1.x;    int delta_y = std::abs(v2.y - v1.y);    int error = 0;    int ystep = v1.y < v2.y ? 1 : -1;    for (vertex current = v1; current.x < v2.x; ++current.x)    {        if (steep)        {            point(vertex(current.y, current.x, current.color));        }        else        {            point(current);        }        error += delta_y;        if (error > 2 * delta_x)        {            y += ystep;            error -= delta_x;        }    }}void renderer::triangle(vertex v1, vertex v2, vertex v3){    line(v1, v2);    line(v2, v3);    line(v3, v1);}void renderer::square(vertex top_left, std::size_t size){    rectangle(top_left, vertex(top_left.x + size, top_left.y + size, top_left.colot);}void renderer::rectangle(vertex top_left, vertex bottom_right){    vertex top_right(bottom_right.x, top_left.y, (top_left.color + bottom_right.color) / 2);     vertex bottom_left(top_left.x, bottom_right.y, (top_left.color + bottom_right.color) / 2);    line(top_left, top_right);    line(top_right, bottom_right);    line(bottom_right, bottom_left);    line(bottom_left, top_left);}void renderer::text(std::size_t x, std::size_t y, const std::string text){    std::for_each(text.begin(),                  text.end(),                  point_drawer(*this, x, y));}std::size_t renderer::screen_width(){    return buffer[0].size();}std::size_t renderer::screen_height(){    return buffer.size();}void renderer::bitblt(){    std::for_each(buffer.begin(),                  buffer.end(),                  std::bind_2nd(&display_row, window));    window << std::endl;}void renderer::clear_row(renderer::row_type& row){    std::fill(row.begin(), row.end(), ' ');}void renderer::display_row(const renderer::row_type& row, renderer::window_type& window){    std::copy(row.begin(), row.end(), std::ostream_iterator<char>(window));    window << '\n';}


// game_world.h#include "renderer.h"#include <iostream>struct game_world{    game_world(renderer& renderer, input_type& input):    renderer(renderer),    input(input)    { }    void run();private:    typedef std::istream input_type;    renderer& renderer;    input_type& input;    void diplay_menu();    void process_input();    static vertex read_point(input_type& input)    enum    {        point = 1,        line,        traingle,        square,        rectangle,        exit    };};


// game_world.cpp#include "game_world.h"game_world::run(){    bool finished = false;    while (!finished)    {        diplay_menu();        finished = process_input();        renderer.bitblt();    }}vertex game_world::read_point(game_world::input_type& input){    std::size_t x, y;    vertex::color_type color;    input >> x >> y >> color;    return vertex(x, y, color);}game_world::diplay_menu(){    renderer.text(0, 0, "Select an Option:");    renderer.text(4, 2, "1) Draw Point.");    renderer.text(4, 3, "2) Draw Line.");    renderer.text(4, 4, "3) Draw Triangle.");    renderer.text(4, 5, "4) Draw Square.");    renderer.text(4, 6, "5) Draw Rectangle.");    renderer.text(4, 7, "6) Exit.");    renderer.bitblt();}game_world::process_input(){    int selection;    input >> selection;    switch (selection)    {    case point:        renderer.point(read_point(input));    case line:        renderer.line(read_point(input), read_point(input));    case triangle:        renderer.triangle(read_point(input), read_point(input), read_point(input));    case square:    {        vertex v = read_point(input);        std::size_t size;        input >> size;        renderer.square(v, size);    }    case rectangle:        renderer.rectangle(read_point(input), read_point(input));    case exit:        return true;    }    return false;}


// vertex.hstruct vertex{    vertex(std::size_t x, std::size_t y, char color):    x(x),    y(y),    color(color)    { }    std::size_t x, y;    char color;};

This topic is closed to new replies.

Advertisement