Jump to content

  • Log In with Google      Sign In   
  • Create Account

bedtime

Member Since 15 Oct 2012
Offline Last Active Dec 13 2012 01:29 AM

Posts I've Made

In Topic: error: ‘filename’ was not declared in this scope

27 November 2012 - 10:33 PM


I've been at this for a day now and no progress. I read the article and I've still not got this other part of the code to work.

The purpose of the article is to get your code to compile and link when using multiple source and header files. Following those directions doesn't prevent other kinds of problems to show up in your code. If your code even gets to the point where it can run then your problem isn't related to the article.

I appear to have an issue with my Map object not being being recognised even though i've declared it and its within the same class.

If it wasn't being recognized it wouldn't even compile. The fact that it does compile means that it is being recognized. Since the problem is a run time error when accessing the Map variable then most likely the problem is that you aren't initializing your object properly. If that isn't enough of a hint to get your program working properly, try producing a minimal, but complete code sample that demonstrates your problem.

Why do you have braces in the line:
Map.insert({std::make_pair<int, int>(1, 2), gameObj1}); ?

That's a C++11 feature: uniform initialization.


Thanks. I solved it. It was something to do with dereferencing and not using 'new' to declare my game object.

Sorry for my constant posts. Today has just been a frustrating day for me, much more then usual and I'm sitting here with a headache... I've been at this way too long today. Maybe 14 hours. Brain went to mush several hours ago.

Anyways, you guys have all been so helpful.

In Topic: error: ‘filename’ was not declared in this scope

27 November 2012 - 08:59 PM

Why do you have braces in the line:
Map.insert({std::make_pair<int, int>(1, 2), gameObj1}); ?

I'm not sure how to get the code to work without them. I get a compile time error.

I just tried changing the code to:

[source lang="cpp"]getMap()->insert(std::make_pair(std::make_pair(1,2), gameObj1));[/source]
its okay just inserting the once, but if I repeat the code above or try to access getMap() again it seg faults.

In Topic: error: ‘filename’ was not declared in this scope

27 November 2012 - 08:29 PM

Edit,


still not working... sigh




I've been at this for a day now and no progress. I read the article and I've still not got this other part of the code to work. I appear to have an issue with my Map object not being being recognised even though i've declared it and its within the same class. I've tried the map object as a pointer as suggested in the link (its not a pointer because i dont feel like changing all the other stuff around by adding the arrow insertion operator for the 5th time.... Pointer or not both result in seg faults. Out of everything in c++ these cyclic dependancies are the holding my code back the most. This is really quite frustrating. The article said in 99% of cases adding a forward declaration and pointer to object of another class is enough. I'm missing something.

Here is the code:

[source lang="cpp"]// game.h#ifndef GAME_H#define GAME_H#include <map>#include <vector>#include "staticcount.h"#include "value.h"#include "tvalue.h"class GameObject;typedef std::pair<int, int> Key;class Game{ Value value; std::multimap<std::pair<int, int>, GameObject*> Map; std::multimap<std::pair<int, int>, GameObject*> go2; // x chunk, y chunk, gameObject std::multimap<int, std::multimap<int, GameObject*>*> go;public: Game() { value.newNum("game number", StaticCount::getNumGames()->getNum()); } // get game values Value* val() { return &value; } void loop(int x_begin, int x_end, int y_begin, int y_end); std::multimap<std::pair<int, int>, GameObject*> getMap();};#endif[/source]


[source lang="cpp"]// game.cpp#include <iostream>#include "game.h"#include "gameobject.h"#include "keys.h"std::multimap<std::pair<int, int>, GameObject*> Game::getMap(){ return Map;}void Game::loop(int x_begin, int x_end, int y_begin, int y_end){ /* uncommenting the line below makes the code below works but its useless as it goes out of scope and is not stored. if the line is commented i get a seg fault */ //std::multimap<std::pair<int, int>, GameObject*> Map; GameObject* gameObj1 = new GameObject; gameObj1->val()->setNum("test", 10); // seg fault is from the line below: (this works if above code 6 lines above is uncommented) Map.insert({std::make_pair<int, int>(1, 2), gameObj1}); std::cout << "made this far" << std::endl; GameObject* gameObj2 = new GameObject; gameObj2->val()->setNum("test", 20); Map.insert({std::make_pair<int, int>(3, 4), gameObj2}); GameObject* gameObj3 = new GameObject; gameObj3->val()->setNum("test", 30); Map.insert({std::make_pair<int, int>(5, 10), gameObj3}); x_begin = 2; y_begin = 1; x_end = 5; y_end = 9; x_end++; y_end++; // if (x_end <= x_begin) return; // if (y_end <= y_begin) return; Key lower(x_begin, y_begin); Key upper(x_end - 1, y_end); auto first = Map.lower_bound(lower); auto last = Map.lower_bound(upper); for (auto itr = first; itr != last;) { int x = itr->first.first; int y = itr->first.second; if (y < y_begin) { itr = Map.lower_bound(Key(x, y_begin)); } else if (y >= y_end) { itr = Map.lower_bound(Key(x + 1, y_begin)); } else { std::cout << "x: " << x << " y: " << y <<" test: " << itr->second->val()->getNum("test") << std::endl; ++itr; } }}[/source]

In Topic: How do I insert a multimap into another multimap?

27 November 2012 - 04:37 PM

If what you want to do is to do some operation on every element with x_begin <= x < x_end and y_begin <= y < y_end, one way to do that would be like:

typedef std::pair<int, int> Key;
typedef std::multimap<Key, GameObject *> Map;

template <typename Operation>
void loop(const Map & map, int x_begin, int x_end, int y_begin, int y_end, Operation operation) {
  if (x_end <= x_begin) return;
  if (y_end <= y_begin) return;

  Key lower(x_begin, y_begin);
  Key upper(x_end - 1, y_end);
  auto first = map.lower_bound(lower);
  auto last = map.lower_bound(upper);  

  for (auto itr = first; itr != last;) {
	int x = itr->first.first;
	int y = itr->first.second;

	if (y < y_begin) {
	  itr = map.lower_bound(Key(x, y_begin));
	} else if (y >= y_end) {
	  itr = map.lower_bound(Key(x + 1, y_begin));
	} else {
	  //do whatever
	  operation(*itr);

	  ++itr;
	}
  }
}


Thank you so much for taking the time to type that up. This was exactly what I was looking for; iterating within a range of x/y chunks. Took me a few times reading it over to understand most of what's going on. One thing that puzzles me is the operator input within the parameters. I'm not entirely sure how to supply that parameter input or what it does. If I had to guess its something to do with iterating... I noticed you left out the 3rd parameter in the for loop and incremented it within the loop below the 'operator'. Looks intriguing. Could you explain this?

Also, I see you made map a const in the parameters. Was there a reason for that? I'm likely going to be changing some object within the loop if that's advisable to do.

Once again, I really appreciate you taking the time write all that out for me.


Are chunks are composed of tiles? Or objects?

Objects. Each x/y map cooridinate is loaded with a GameObject which stores the 'components' such as rendering values and instructions for that specific character, the character itself, and sound components...


Have you actually tried just making a grid of uniform chunks, and actually seeing if it's too slow for your program?

Yes, I had started out with a vector tile-based situation. I profiled it (bare text run, no graphics), testing it with various chunk sizes and getting best performance at around 250 - 500 fps. This was with little characters on the screen and no AI, graphics, at all yet. More characters slowed it right down, 25 - 100 fps. Just not cutting it. I then profiled a system based on a 'list' of airborne x/y chunks, which only had chunks that held objects, and fps went to 4000 -10000 fps. When I first jumped I thought it was broken because I couldn't see the character jump! Posted Image When I loaded the board and level with characters, massively, it still did 150 - 500 fps, which was good enough.


So you break your world into 'chunks'. World has a grid of smart pointers to Chunks (yes, a grid). Each location on the grid can either be a null smart pointer (thus saving you your precious memory Posted Image), or can have a smart pointer to a valid Chunk.

I like the smart pointer idea and I like the idea of maybe using something to say if a character is enabled or not. Objects not enabled could be used as pooled objects, which is fine. By 'chunks' I see you mean a 'grid' but I do not want a tile-based grid. I'd rather a list (map, vector....whatever container) 'within' a chunk. So anything on that list that is processed if that chunk is on the screen.

A chunk is just a "bucket" of entities. Any solid who's center is over the chunk's boundaries, belongs to that chunk.
A Chunk:

  • Manages it's own loading and saving from file.
  • Tells the Objects within it to draw, think, etc...
  • If an Object Entity walks off of one chunk, that chunk passes ownership of that object to the next chunk.[/qoute]
I'll take a look at your code. I'm thinking of maybe having an outside entity control the chunks. As for objects changing chunks, you've described it exactly how I had it before; objects swapping memory positions to different containers. As well, leaving a pooled disabled object in its tracks to be used later.


Maybe you want to specify to only keep an object in memory if it's within a certain range.

That's a good idea. Perhaps a small loop that runs a list of these characters and runs an update() with full or high range chunks. But that's a while away.

Let's convert this directly to pseudo-code:

Object
{
	 Position
	 IsPersistent
	 RangeToKeepInMemory //The distance away the player needs to be before it is destroyed.
	
	 bool SaveStateWhenDestroyed() -> (IsPersistant && hasChanged)
	 bool KeepInMemory(playerDistance) -> (playerDistance > RangeToKeepInMemory)

	 Save()
	 Load()

	 Draw()
	 Update(deltaTime) //Think, animate, etc...
}

Chunk
{
	 Vector<Object::Ptr> Objects

	 StreamOut() //Unloads all objects except those it needs to keep in memory.
	 StreamIn() //Loads all persistent objects, like walls and enemies that don't spawn but have preset locations like bosses.

	 Draw() -> Draw every object
	 Update(deltaTime) -> Update every object
}

World
{
	 Grid<Chunk::Ptr> Chunks;

	 LoadNewWorld();
	 StreamChunksAround(location);

	 Draw() -> Draws all chunks nearby.
	 Update(deltaTime) -> Updates chunks (which in turn updates objects)
}

This can be improved upon, but it's a good start and really straightforward and simple. It also does not waste much memory or speed.

You can steal my C++ Grid class here - re-sizable and permits negative indices. If you know the size of your World ahead of time, and it doesn't change during the course of that play, you could use a std::vector of size (width*height) instead.

The whole map<map<Object>> thing just doesn't seem like good design.

Thank you for all that info! I'll take a look at your Grid class tomorrow when my mind is more agile and has had some rest. Been at this all day. Negative indices and resizable definately sounds good. It's just what I need.

In Topic: How do I insert a multimap into another multimap?

27 November 2012 - 01:06 PM

Let's step back a second. What are you actually trying to do? Not, "how are you trying to implement it", but what is your overall design problem you are solving?

Do you have a grid of spaces, and a game object might be on that grid?



I'm making a mario-style side-scroller. My map is made up of x and y chunks, but it is not a grid. They are more like a list of chunks. This way I can skip chunks (or sections, whatever you want to call it) for areas that don't have any objects. So this is not tile-based. I would like to make a board map that is speed and memory efficient that can do positive and negative chunks. This is important because I want the map to be realtime expandable during runtime. There will be a lot of objects in the game so I want to be able to focus on only displaying the very minimum. There may be more then one object on the same chunk as well, hence the multimap. Levels might just go up 0 degrees. They might go backwards (270 deg). They might 'squiggle' or go in a circle.

I've done this all before but only with an X chunk and not with a Y chunk as well. So the map was only cut into X sections which led to inefficiencies if the level went straight upward. Since then I've since learned some new concepts such as component/entity programming so I'm changing things up and starting over.

PARTNERS