Advertisement

[SFML & Tiled] Spawn items on each location

Started by July 30, 2017 09:21 AM
10 comments, last by Rutin 7 years, 4 months ago

So I am trying to get an item to spawn on specific locations. I am using a xml parser to get the objects name and location (solid walls, start point, end point and item spawn points). It will only spawn on the last location and totally avoids the first. Anyway here is my code that I have so far:

the problem:

d4d4240ce11b286553cb6f6618840709.png

 

The spawn locations i want to place on:
3ea4a993241e81a95356c661a0eba6b5.png

The code:


	for (int i = 0; i < obj.size(); i++)
	{
		if (obj[i].name == "item")
		{
			pickups->sprite.setPosition(obj[i].rect.left, obj[i].rect.top);
			pickupVector.push_back(pickups);
		}
	}

so I want to spawn it on the first one location, then push it onto the array, then spawn the next one and put on array and so on..

"pickups" looks like a pointer to something. Inside the "if", you change a field in the pointed-to object, and push the pointer onto the "pickupVector". Since the "pickups" itself is not changed, you change the same field in the same object each time (erasing any previous value of "sprite.position"), and push the same pointer (all pointing to the same object) onto the vector each time.

 

Advertisement
6 hours ago, Alberth said:

"pickups" looks like a pointer to something. Inside the "if", you change a field in the pointed-to object, and push the pointer onto the "pickupVector". Since the "pickups" itself is not changed, you change the same field in the same object each time (erasing any previous value of "sprite.position"), and push the same pointer (all pointing to the same object) onto the vector each time.

 

What is the best way to deal with this?

I don't know, You didn't give any type / structure information, so I don't know what "pickups" is / contains, or what "sprite" contains. I guessed pickupVector purely based on its name, and the fact you use ".push_back", but also for that I have no type information.

Obviously, you need to display the same image at several places on the screen, which seems to suggest a "sprite" with a different position for each thing you need to display.

 

1 hour ago, Elit3d said:

What is the best way to deal with this?

I'm not 100% sure on your system but I've programmed enough level editors in my time. Is the problem you're having that you want items to be placed in the array based on the same order of position clicks on the editor? Please let me know if I'm mistaken so I can provide a better answer.

If this is your only issue, all you need to do is program an event tracker for grid clicks before editing or changing a layer. When you click on any grid on your map record the position into a vector of sf::Vector2f so the order is kept. Then when you want to cycle through your loop you just use the position and remove it, then keep going.

The *32 is assuming your tiles are 32x32 it will give you the correct top left cord.


std::vector<sf::Vector2f> posTracker;
posTracker.push_back(sf::Vector2f(5 * 32, 2 * 32));
posTracker.push_back(sf::Vector2f(6 * 32, 4 * 32));
posTracker.push_back(sf::Vector2f(8 * 32, 6 * 32));

for (int i = 0; i < obj.size(); i++)
{
	if (obj[i].name == "item")
	{
		pickups->sprite.setPosition(posTracker[0].x, posTracker[0].y);
		posTracker.erase(posTracker.begin());
		pickupVector.push_back(pickups);
	}
}

You should also put something in your loop that when your positions are all used it exits the loop.

Programmer and 3D Artist

4 minutes ago, Alberth said:

I don't know, You didn't give any type / structure information, so I don't know what "pickups" is / contains, or what "sprite" contains. I guessed pickupVector purely based on its name, and the fact you use ".push_back", but also for that I have no type information.

Obviously, you need to display the same image at several places on the screen, which seems to suggest a "sprite" with a different position for each thing you need to display.

 


Pickup::Pickup(std::string imgpath)
{
	texture.loadFromFile(imgpath);
	sprite.setTexture(texture);
}

its just a simple entity class really that lets me set the pickup sprite

entity class:


class Entity
{
public:
	sf::Sprite sprite;
	sf::Texture texture;
};

 

 

4 minutes ago, Rutin said:

I'm not 100% sure on your system but I've programmed enough level editors in my time. Is the problem you're having that you want items to be placed in the array based on the same order of position clicks on the editor? Please let me know if I'm mistaken so I can provide a better answer.

If this is your only issue, all you need to do is program an event tracker for grid clicks before editing or changing a layer. When you click on any grid on your map record the position into a vector of sf::Vector2f so the order is kept. Then when you want to cycle through your loop you just use the position and remove it, then keep going.

The *32 is assuming your tiles are 32x32 it will give you the correct top left cord.



std::vector<sf::Vector2f> posTracker;
posTracker.push_back(sf::Vector2f(5 * 32, 2 * 32));
posTracker.push_back(sf::Vector2f(6 * 32, 4 * 32));
posTracker.push_back(sf::Vector2f(8 * 32, 6 * 32));

for (int i = 0; i < obj.size(); i++)
{
	if (obj[i].name == "item")
	{
		pickups->sprite.setPosition(posTracker[0].x, posTracker[0].y);
		posTracker.erase(posTracker.begin());
		pickupVector.push_back(pickups);
	}
}

You should also put something in your loop that when your positions are all used it exits the loop.

basically, when the level loads, depending on how many "item" points there are on the parsed map, will spawn the correct amount of items (i know how to spawn the certain cap of items already) on each grid spot as shown, like Alberth said, its something to do with the sprite position updating to the last position passed to sprite.setPosition

Advertisement

Sorry, I guess I read your question wrong.

The only thing I can think of is you're storing a pointer object into the container, so when you edit it the second time you're changing all the objects because you're not passing in copies. I might be wrong, but you really need to see what the debugger is showing you.

Why don't you just make new objects?


for (int i = 0; i < obj.size(); i++)
{
	if (obj[i].name == "item")
	{
		pickupVector.push_back(pickups(obj[i].rect.left, obj[i].rect.top));
	}
}

 

Programmer and 3D Artist

1 hour ago, Rutin said:

Sorry, I guess I read your question wrong.

The only thing I can think of is you're storing a pointer object into the container, so when you edit it the second time you're changing all the objects because you're not passing in copies. I might be wrong, but you really need to see what the debugger is showing you.

Why don't you just make new objects?



for (int i = 0; i < obj.size(); i++)
{
	if (obj[i].name == "item")
	{
		pickupVector.push_back(pickups(obj[i].rect.left, obj[i].rect.top));
	}
}

 

Ah great, many thanks! I can see my mistake now, I'm so stupid, I'm supposed to create a new instance of the object otherwise the position is going to be transferred to each pickup

this is now my code:


			pickups = new Pickup("images/icon-power.png", sf::Vector2f(obj[i].rect.left, obj[i].rect.top));

			if (bSpawnNoMore == false)
				pickupVector.push_back(pickups);

 

Great.

Glad you're up and running now!

Programmer and 3D Artist

Just now, Rutin said:

Great.

Glad you're up and running now!

I really appreciate the help, great community here :)

This topic is closed to new replies.

Advertisement