C++ to a whole new level

Pages: 123
Just in case anyone else may not be familiar with the games here are YT videos of each game (as some are from the Atari 2600 days back when I was a kid in the 80s). Just trying to help make it easy access so people aren't googling for gameplay videos.

Pong (Atari 2600): http://www.youtube.com/watch?v=CxgaZenhngU
Worm (Atari 2600)*: http://www.youtube.com/watch?v=rVFvlJ98Fu4
Breakout (Atari 2600): http://www.youtube.com/watch?v=Up-a5x3coC0
Missile Command (Atari 2600): http://www.youtube.com/watch?v=Z4zF790DzyQ
Space Invaders (Atari 2600): http://www.youtube.com/watch?v=opru6qPsPa4
Asteroids (Atari 2600): http://www.youtube.com/watch?v=i3Pr8yC8_F4
Tetris (NES): http://www.youtube.com/watch?v=VEDBCIZwYRA
Pac Man (Atari 2600): http://www.youtube.com/watch?v=XdT0lrm4b2s
Ikari Warriors (NES): http://www.youtube.com/watch?v=hyDi_7swlKo
Super Mario Bros. (NES): http://www.youtube.com/watch?v=ia8bhFoqkVE

Just because they were mentioned in the final paragraph.
Sonic (Sega Genesis): http://www.youtube.com/watch?v=CqOlpQ7sepE
Metroid (NES): http://www.youtube.com/watch?v=Ti1V0YMULGs
Zelda (NES): http://www.youtube.com/watch?v=c4bvZZa5Mtg

*Also called Snakes and Tape worm (as evident by the Atari 2600).
Last edited on by closed account z6A9GNh0
Just in case anyone else may not be familiar with the games here are YT videos of each game (as some are from the Atari 2600 days back when I was a kid in the 80s). Just trying to help make it easy access so people aren't googling for gameplay videos.


thank you! i was just wondering wat games dey were ^^;
Yeah, I was born in '81 so I grew up with the Atari 2600 and have owned every console since. The only recent consoles I've not bothered getting was the 360, PS Vita, or WiiU. I'm now contemplating how to get the money to get a PS4. Sadly, I have met too many who were born in the 90s and only played Playstation up so I wanted to make it easy for whoever may not have ever played those games before to get an idea of how they were done.
Last edited on by closed account z6A9GNh0
AFAIK most games made back then had very little memory so they were forced into using tilemaps. You may want to look into that here are some sites they may help you create a basic tilemap loader.

http://www.dreamincode.net/?p=kudos&kudosmember=503178
http://www.youtube.com/playlist?list=PLHJE4y54mpC5j_x90UkuoMZOdmmL9-_rg ~lesson 27
http://www.xnaresources.com/default.asp?page=TUTORIALS (its in c# but still it has good information)

here's a very simple version(I have a more advanced one but it's still a WIP for the map editor I am creating):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <SFML/Graphics.hpp>
#include <vector>
#include <fstream>
#include <iostream>


std::vector<std::vector<sf::Vector2i> > loadMap( const char *filename );
void displayMap( std::vector<std::vector<sf::Vector2i> > map , const char *filename , sf::RenderWindow &window );
void generateRandomMap( const int ROWS , const int COLUMNS );

int main()
{
    sf::RenderWindow window( sf::VideoMode( 640 , 480 , 32 ) , "Tile Map Loader" );

    std::vector<std::vector<sf::Vector2i> > map;
    map = loadMap( "map1.txt" );
    displayMap( map , "tileset.png" , window );

    while( window.isOpen() )
    {
        sf::Event event;
        while( window.pollEvent(event) )
        {
            switch( event.type )
            {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    switch( event.key.code )
                    {
                        case sf::Keyboard::Key::L:
                            map = loadMap( "map1.txt" );
                            displayMap( map , "tileset.png" , window );
                            break;
                        case sf::Keyboard::Key::G:
                            generateRandomMap(15,20); //generate random 15 x 20 map
                            map = loadMap("map1.txt");
                            displayMap( map , "tileset.png" , window );
                            break;
                    }
                    break;
            }
        }
    }
}

std::vector<std::vector<sf::Vector2i> > loadMap( const char *filename )
{
    std::vector<std::vector<sf::Vector2i> >map;
    std::vector<sf::Vector2i> tempMap;
    sf::Vector2i tempCoord;

    std::ifstream in( filename );
    if( in.is_open() )
    {
        while( in.good() )
        {
            in >> tempCoord.x;
            in >> tempCoord.y;

            tempMap.push_back(tempCoord);
            if( in.peek() == '\n' )
            {
                map.push_back(tempMap);
                tempMap.clear();
            }
        }
    }
    in.close();
    return( map );
}
void displayMap( std::vector<std::vector<sf::Vector2i> > map , const char *filename , sf::RenderWindow &window )
{
    sf::Color background = sf::Color( 58 , 171 , 115 );
    window.clear(background);

    sf::Texture tileset;
    tileset.loadFromFile(filename);
    sf::Sprite tile(tileset);

    const int SIZE = 32; //size of tile 32x32

    for( int row = 0; row < map.size(); ++row )
    {
        for( int column = 0; column < map[row].size(); ++column )
        {
            if( map[row][column].x != -1 && map[row][column].y != -1 )
            {
                tile.setPosition(column * SIZE , row * SIZE );
                tile.setTextureRect( sf::IntRect( map[row][column].x * SIZE , map[row][column].y * SIZE , SIZE , SIZE ) );
                window.draw(tile);
            }
        }
    }
    window.display();
}

void generateRandomMap( const int ROWS , const int COLUMNS )
{
    srand( (unsigned) time(NULL) );
    std::ofstream out( "map1.txt" );
    const short MAX_ROWS = 1;
    const short MAX_COLUMNS = 4;
    //tileset is a 1x4

    for( int row = 0; row < ROWS; ++row )
    {
        for( int column = 0; column < COLUMNS; ++column )
        {
            out << ' ' << rand() % (MAX_COLUMNS+1) - 1 << ' ' << rand() % (MAX_ROWS+1) - 1;
        }
        out << '\n';
    }
    out.close();
}


*typo
Last edited on
closed account (Dy7SLyTq)
i was born in the 90s but my dad is such a big nerd that i grew up around those games (well not on that console, usually more on an arcade system). now hes building a coffee table arcade using mame. i can play galaga on an hd tv!
closed account (N36fSL3A)
Not to derail the thread but was a 2D vector really necessary? Giblit, you could have just used a 1d vector with 2 variables - one that represented the width, and one that represented the height.

Not only is that easier to manage, but It'd take up less memory as well.
How does it take up less memory? If you are using a 1D to act like a 2D then the 1D should end up being the same size as the 2D. For example, if you make a 2D array (int array[100][100] = {{0}};) and make a 1D equivalent (int array2[100*100] = {0};, and assuming I read this right, do sizeof(array) and sizeof(array2) they both (depending on system) will put out the same size). Not really sure how vectors do it since they are dynamic and can grow and shrink as needed.
Last edited on by closed account z6A9GNh0
How does it take up less memory?


Multidimensional vectors and "nested new" arrays consume more memory than one dimensional arrays (and 'straight' MD arrays) because they need to keep track of an array of pointers.

IE:

1
2
3
4
5
6
int foo** = new int*[5];
for(int i = 0; i < 5; ++i)
    foo[i] = new int[5];

// vs
int bar* = new int[5*5];


The former allocates memory for 25 ints + 5 pointers
The latter allocates memory for 25 ints (but no pointers)

Though the latter demands all 25 ints be store contiguously, whereas the former does not.

A 2D vector is similar to the former. A 'straight' 2D array is similar to the latter.
The thing I am trying to understand is, everyone is stressing memory, but until now every programmer I've talked to has always told me the same thing. "With today's computers, memory use in applications means very little now." In fact, the only time I've seen a programmer freak over memory use was Blow when he was talking about making Braid on 360 because you were only allotted a small amount of usable memory for the game.

In the 17 years I've been doing this I have never had someone say what everyone has said about 1D vs 2D array/vectors until now. I don't even post my code anymore when I have questions because I prefer 2D arrays and vectors and know that it will turn into this 1D vs 2D debate as it has every time so I just keep googling and figuring out the problem on my own.
I agree that the memory difference is inconsequential and isn't worth worrying about. I was just answering your question.
Sorry, I appreciate you replying. Just drives me nuts that it comes down to the 1D vs 2D debate any time someone posts a 2D array or vector.
It's not just memory usage, 2D vectors aren't guaranteed to be sequential in memory, if you have to loop over all elements in a 2D vector you could cause significant slowdowns.
@Lachlan Easton
Are you sure about that? Googling gave me numerous Stackoverflow pages that say vectors are sequential.
@BHX
Pretty sure, as the top answer here points out, only the elements are stored sequentially, in a vector< vector<t> > each internal vector<t> has to be able to re-size, the pointers to each vector<t> would be sequential in the 'outer' vector and each t element would be sequential within their own vector<t>, but each vector<t> could happily sit somewhere completely different in memory.
http://stackoverflow.com/questions/10898007/stdvector-of-stdvectors-contiguity
closed account (Dy7SLyTq)
someone correct me if im wrong. this is the dumbed down point of view. i would have to think it couldnt work like that, because there is no gaurantee that their will be enough strung together. if programs are started and finished at predictable times maybe, but otherwise that whole thing is in flux and so the kernel just grabs the memory as it goes. however you can test it by printing the adress of the pointer
It must be implementation based. I wrote code that created a 1D array, 1D vector, 2D array, and 2D Vector of type int, then printed out their memory address locations and they all were sequential every time I ran the code.

This was the output I got from one of the runs:

1D Array       : 1D Vector
0x7fff299f47d0 : 0x173a010
0x7fff299f47d4 : 0x173a014
0x7fff299f47d8 : 0x173a018
0x7fff299f47dc : 0x173a01c
0x7fff299f47e0 : 0x173a020

2D Array       : 2D Vector
0x7fff299f4720 : 0x173a0d0
0x7fff299f4724 : 0x173a0d4
0x7fff299f4728 : 0x173a0d8
0x7fff299f472c : 0x173a0dc
0x7fff299f4730 : 0x173a0e0

0x7fff299f4734 : 0x173a0f0
0x7fff299f4738 : 0x173a0f4
0x7fff299f473c : 0x173a0f8
0x7fff299f4740 : 0x173a0fc
0x7fff299f4744 : 0x173a100

0x7fff299f4748 : 0x173a110
0x7fff299f474c : 0x173a114
0x7fff299f4750 : 0x173a118
0x7fff299f4754 : 0x173a11c
0x7fff299f4758 : 0x173a120

0x7fff299f475c : 0x173a130
0x7fff299f4760 : 0x173a134
0x7fff299f4764 : 0x173a138
0x7fff299f4768 : 0x173a13c
0x7fff299f476c : 0x173a140

0x7fff299f4770 : 0x173a150
0x7fff299f4774 : 0x173a154
0x7fff299f4778 : 0x173a158
0x7fff299f477c : 0x173a15c
0x7fff299f4780 : 0x173a160
@ BHX: those aren't quite contiguous:


2D Array       : 2D Vector
0x7fff299f4720 : 0x173a0d0
0x7fff299f4724 : 0x173a0d4
0x7fff299f4728 : 0x173a0d8
0x7fff299f472c : 0x173a0dc
0x7fff299f4730 : 0x173a0e0

0x7fff299f4734 : 0x173a0f0  <- notice how the 2D array goes +4 here
    but the 2D vector goes +0x10
@Disch
True, but it did that with every run. Between each section of five it jumped 0x10, which is why I said it must be implementation based. I have ran the code several times now with the same effect. Here is the program ran four times side by side and you see the pattern stays the same (for whatever reason, maybe implementation overhead or some other reason) http://prntscr.com/251hpu .
closed account (N36fSL3A)
I hate it how when someone writes inefficient code they're like "it doesn't matter, give it more hardware." Seriously, better machines are not an excuse to write inefficient code.
Pages: 123