Event Handling for a game

Pages: 12
When I use pointers to Tile however, every tile shows black, except for every different tile last read in. so those would show


I'm not sure what you mean by that. Your example doesn't example help either...can I see some code?
How are you adding to the vector<vector<tile>> in your layer object? Perhaps you aren't adding the tiles correctly, or loading them correctly. If it worked without pointers, though, then I'm assuming that the map loads correctly. Provided that, the only other obvious issue is that you aren't creating your tiles correctly.

When you add (push_back()), do you use the new keyword? Do you have to use tile* at all? I don't really see the point, the tile class should take care of itself, so you shouldn't have to pass any tiles to functions. So with actual tile objects, the speed should be pretty much the same, if not faster than using pointers.
code bomb...INCOMING!

I'll only show the necessary:

Map.h
1
2
3
4
5
6
7
8
9
class Map
{
    public:
        Map(TileSet& t, string fileName);
        vector<Layer> layers;
        void draw(sf::RenderWindow& Window);

    private:
};


Map.cpp
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
Map::Map(TileSet &t, string fileName)
{
    int amountOfLayers;
    ifstream file;
    file.open(fileName.c_str());
    file>>amountOfLayers;
    cout<<amountOfLayers<<"\n";
    for(int i = 0; i < amountOfLayers; i++)
    {
        layers.push_back(Layer(t, file));
    }

    //read in events
    for(int i = 0; i < FIELDHEIGHT; i++)
    {
        cout<<"\n";
        for(int j = 0; j < FIELDWIDTH; j++)
        {
            int eventID;
            file>>eventID;
            tileEvent[i][j] = eventID;
            cout<<eventID;
        }
    }
}


Layer.h:
1
2
3
4
5
6
7
8
9
class Layer
{
    public:
        Layer(TileSet& t, ifstream& file);
        int tileWidth;
        int tileHeight;
        void draw(sf::RenderWindow& Window);
        vector<vector<Tile> > grid;
};


Layer.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Layer::Layer(TileSet& t, ifstream& file)
{
    for(int i = 0; i < FIELDHEIGHT; i++)
    {
        vector<Tile> temp;
        grid.push_back(temp);

        cout<<"\n";


        for(int j = 0; j < FIELDWIDTH; j++)
        {
            int id;
            file>>id;
            Tile tile = *t.tiles[id];
            tile.sprite.SetPosition(j*32, i*32);
            grid[i].push_back(tile);
            cout<<id;
        }
    }
}


TileSet.h:
1
2
3
4
5
6
7
8
class TileSet
{
    public:
        TileSet();
        ImageManager im;
        map<int, Tile*> tiles;
        Tile getTile(int id);
};


TileSet.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
TileSet::TileSet()
{
    ifstream file;
    file.open("TileSet.txt");
    int amountOfSprites;
    file>>amountOfSprites;
    for(int i = 0; i < amountOfSprites; i++)
    {
        int id;
        bool walkable;
        string imageName;
        sf::Sprite sprite;
        file>>id;
        file>>imageName;
        file>>walkable;
        sf::Image* image  = im.getImage(imageName);
        sprite.SetImage(*image);
        tiles[id] = new Tile(sprite, walkable, 0);
    }
}


Tell me if you need other files !

@modshop The reason I suggested pointers was to permit a polymorphic hierarchy of tiles, which would react differently to events.

@xander In your TileSet constructor, I don't think you are handling the map correctly. This line:
tiles[id] = new Tile(sprite, walkable, 0);
seems suspicious to me, as each element of tiles is supposed to me a pair<int, Tile*>. Consider inserting elements to your map using std::map::insert, passing it the appropriate std::pair<int, Tile*>.
@xander314:
In the tile class, you could have an int storing what type of event the tile causes. The int could be handled by an EventManager class. This would eliminate the need for polymorphism and inheritance.

@xander333:
I think you should change your map file format from just a grid, to something more dynamic. Such as:

tile
x:1
y:1
graphic:5
event:0
endtile


Then, you could make an editor that creates the files for you, all you would have to do is "click" the tiles into place. This is an how I'm approaching the tilemap section of my next game. It allows me to rotate tiles individually, animate tiles individually (or all tiles of the same type), have different tile "events" on tiles of the same type (i.e. the grass at 0,0 cannot be walked on, but the grass at 5,5 can be) and utilize multiple "layers". Layers meaning background (grass, sand, dirt), foreground(rocks, tress) and an event layer. The map's width/height and filenames for tiles/foreground objects are also stored in the file. I also wrote a nice wrapper class for all the layers so that handling the map from my main game code would be as simple as:

1
2
3
4
Map.load("Gamefiles/Maps/world1.map");

//in game loop
Map.draw();


I would suggest using an approach similar to this one. It would eliminate the need for pointers and would almost guarantee the map loading correctly.
Last edited on
@modshop You could do that, but I would have thought that a function pointer would provide a more extensible solution than an integer.
It would, but an int provides simplicity. Also, with an EventManager class, there is nothing that could be done with a function pointer that can't be done with an int flag.
Last edited on
It would, but an int provides simplicity

I disagree, it just makes seemingly magic numbers or enums that people have to go looking up unnecessarily. I like the fptr route, however you can combine the two fairly easily.

The reason I suggested pointers was to permit a polymorphic hierarchy of tiles, which would react differently to events.

I can't think of a more appropriate use of OO in c++.

For my paticular system, I have the regular event system, a wrapper that allows me to get input at any given time, and a registration aspect that allows me to add new events and types and wait on other events so that objects can be informed of changes. For instance my button class derived from my event receiving objects, registers for click down and up, and has functions to handle both, and members that allow me to check if both were within the bounds of the button, in which case I call another method that takes action, I'm considering a functor path here...

It's becoming increasingly usable. My whole system is allowing for extremely rapid dev of games and demos which is just plain awesome! =]
Hmm, I think I'll use the system with ints from ModShop. So how do I know which arguments to pass? Hardcode a switch statement?
@ultifinitus
ultifinitus wrote:
system is allowing for extremely rapid dev of games and demos

That's what I'm aiming for, but right now I'm so busy that my engine is still in early stages TT. You're using SFML? Any other libraries? What about C++0x features? (Forgive my curiosity, but I'm interested :p)

@xander
xander333 wrote:
how do I know which arguments to pass

To pass to your event handling functions? I still think that function pointers or inheritance would provide a more elegant solution, but if you aren't yet comfortable with those things, then do it as you want to and just make sure you learn those features ASAP :)
@314:
I'm using SFML, though honestly I like my SDL engine more (I was able to come up with a lot more of the back end, SFML kind of limits you(not really, that's just how it feels))

I'm also using winsock/posix sockets for the multiplayer aspect.

0x = nope.. Though when it becomes std I'll gladly take the time to learn everything, I have written some crossplatform threading stuff and networking stuff, so the biggest things i'd be interested in are already taken care of.

Hahahaha, I have seriously NO time whatsoever. I am at work from 9-6 usually and when I get home my friends have been taking the rest of my time... At the same time I'm starting a business, see: http://i.imgur.com/trTXJ.png (newspaper ad) and working on another iPhone app.. Time is a joke. I've lately begun waking up at 5:30 to program every day.
When I switched from SDL to SFML, I almost went back because it was almost as if I were using .NET again (I felt so dirty... ;) ), but meh I stuck with it and it's certainly good for my blog's SEO.

I'm not using C++0x much, but I have embraced auto as a quick STL iterator. I wish I could have iteration within bounds, but VC doesn't have it TT

Bet you can make a killing doing that, even though you'll be dying inside :P
My granddad's motherboard died, so he bought a new computer, and need the old hard disk contents recovered, so I did it for him. However, if he'd had a tech guy to do it, it would have been ~£100/$160!
I am familiar with function pointers, but as far as I know, to have a vector of function pointers they all need the same arguments right? How would I do it with them otherwise?
They must all have the same argument, but you could use something like boost::any to pass different arguments. You would, however, be limited to a fixed number of arguments. Perhaps someone else has a tidier solution.

Also, I wouldn't have a vector of function pointers. The function pointer ought to be a member of the tile class. Note that if you aren't going to be using inheritance and polymorphism, then you can change the Tile pointers back to Tiles.
I already changed them back, I still need to find a solution to get it working with pointers. And ofcourse it should be a member, what was I thinking XD!
The function pointer type could look like this:
typedef void (*TileReaction)(const boost::any& data);
Then the tile could have a member TileReaction Reaction, which could be called to react to the user stepping on the tile.
Last edited on
Okay, I'm TOTALLY stuck right now. For the last couple of days I've been trying to wrap my head around an event handler. And I'm stuck. I have no clue as to how to event START with this. How do I register hits from monsters, load new maps, have convos with NPCs, start/end quests, that kind of stuff. Do I need like an SIGNAL/SLOT connection type of thing (like Qt?). I just don't know what to do!

I've searched all over the internet but couldn't find answers...

PS: I'm sorry for asking so much help in regards with my game...it's just my first ever :S
Last edited on
Hey sorry for the late reply.

I see this happening in one of several ways.

First. Easiest method: Simply have an enum of types of events. Make your manager the creator of your objects so you call a new object with:object& myobj = *manager.newobj<object>("myoptionalimage.here"); where newobj(""); returns a pointer to a new object of type "object" this way you are guaranteed that all objects are given a pointer to your manager (because all classes are derived from a base class which is the reason you can use a template in your manager class and not screw your later code up. Then have an overloadable method to send events to, and receive events from, the manager. The manager also receives events from the operating system, and displays your objects(objects have a hidden aspect, so you can hide them from the view) you can also transfer objects between managers, or you can also have layers within your manager, so you can have huds, and independent movement of containers of objects.

did that make ANY sense?



Second. Harder method. TBA. =] (working on it)
Topic archived. No new replies allowed.
Pages: 12