Hello I'm making a game using SFML, but I ran into some problems.
I want to complete this function:
if a human character collide with items, one garbage draw on screen. (5 textures)
So multiple textures of garbages stack up from the bottom of the window.
I tried to use vector and Sprite array, but my codes can't add garbages. It just draw one garbage, and then change another textures.
What should I do to keep garbages drawn until window closes?
I should add many Sprites to solve this problem, but I have no ideas... I've done everything I can.
My code is here:
// out of main loop
Texture GarbagesTexture[5];
GarbagesTexture[0] = garbageTex1;
GarbagesTexture[1] = garbageTex2;
GarbagesTexture[2] = garbageTex3;
GarbagesTexture[3] = garbageTex4;
GarbagesTexture[4] = garbageTex5;
int SelectedGarbage = 0;
vector<Sprite> Garbages;
Position GarbagesPosition;
GarbagesPosition.x = 890.f;
GarbagesPosition.y = 590.f;
// main loop
//collision
for (size_t i = 0; i < items.size(); i++)
{
if (humanArr[index].getGlobalBounds().intersects(item[i].getGlobalBounds()))
{
...
...
CollisionTime++;
SelectedGarbage++;
if (SelectedGarbage > 5) SelectedGarbage = 0;
GarbagesPosition.x = GarbagesPosition.x - 10.f;
GarbagesPosition.y = GarbagesPosition.y - 5.f;
Sprite GarbageInputSprite;
Garbages.push_back(GarbageInputSprite);
Garbages[i].setTexture(GarbagesTexture[SelectedGarbage];
Garbages[i].setPosition(GarbagesPosition.x, GarbagesPosition.y);
}
}
//draw
window.clear();
...
...
for (int i = 0; i < CollisionTime; i++)
window.draw(Garbages[i]);
window.display();
I am a poor beginner in SFML, but I'll try to do my best.
I would really appreciate it if you could help me solve this problem.
Related
I’m creating a waveform widget in TouchGFX, but unsure how best to loop the waveform back to zero at the end because there are three frame buffers so you have to invalidate over an area three times or you get flickering . How would you handle looping the array back to start (x=0).
The main issue is my code originally assumed there was only one frame buffer. I think my code needs to be refactored for three framebuffers or add the ability to write directly to the frame buffer. Any hints would be greatly appreciated.
bool Graph::drawCanvasWidget(const Rect& invalidatedArea) const
{
if (numPoints < 3)
{
// A graph line with a single (or not even a single) point is invisible
return true;
}
else{
Canvas canvas(this, invalidatedArea);
for (int index = 0; index < (numPoints-1); index++)
{
canvas.moveTo(points[index].x,points[index].y);
canvas.lineTo(points[index].x,points[index+1].y);
canvas.lineTo(points[index+1].x,points[index+1].y);
canvas.lineTo(points[index+1].x,points[index].y);
}
return canvas.render(); // Shape above automatically closed
}
return true;
}
void Graph::newPoint(int y)
{
if(numPoints==501){
numPoints=0;
}else if ((maxPoints-numPoints)<=20){
points[numPoints].x = numPoints;
points[numPoints].y = y;
Rect minimalRect(480,0,20,100);
invalidateRect(minimalRect);
numPoints++;
}else{
points[numPoints].x = numPoints;
points[numPoints].y = y;
Rect minimalRect(numPoints-3,0,20,100);
invalidateRect(minimalRect);
numPoints++;
}
}
With TouchGFX 4.15.0 (just out) the TouchGFX Designer now supports a Graph widget (previously only found in source code in demos) which can be used to produce your waveforms. It has some more elegant ways of inserting points which may suit your needs.
I'm having a bit of issue trying to get meshes I import into my program to have cloth simulation physics using a particle/spring system. I'm kind of a beginner into graphics programming, so sorry if this is super obvious and I'm just missing something. I'm using C++ with OpenGL, as well as Assimp to import the models. I'm fairly sure my code to calculate the constraints/springs and step each particle is correct, as I tested it out with generated meshes (with quads instead of triangles), and it looked fine, but idk.
I've been using this link to study up on how to actually do this: https://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc2010/07LuisPereira/Thesis/LuisPereira_Thesis.pdf
What it looks like in-engine: https://www.youtube.com/watch?v=RyAan27wryU
I'm pretty sure it's an issue with the connections/springs, as the imported model thats just a flat plane seems to work fine, for the most part. The other model though.. seems to just fall apart. I keep looking at papers on this, and from what I understand everything should be working right, as I connect the edge/bend springs seemingly correctly, and the physics side seems to work from the flat planes. I really can't figure it out for the life of me! Any tips/help would be GREATLY appreciated! :)
Code for processing Mesh into Cloth:
// Container to temporarily hold faces while we process springs
std::vector<Face> faces;
// Go through indices and take the ones making a triangle.
// Indices come from assimp, so i think this is the right thing to do to get each face?
for (int i = 0; i < this->indices.size(); i+=3)
{
std::vector<unsigned int> faceIds = { this->indices.at(i), this->indices.at(i + 1), this->indices.at(i + 2) };
Face face;
face.vertexIDs = faceIds;
faces.push_back(face);
}
// Iterate through faces and add constraints when needed.
for (int l = 0; l < faces.size(); l++)
{
// Adding edge springs.
Face temp = faces[l];
makeConstraint(particles.at(temp.vertexIDs[0]), particles.at(temp.vertexIDs[1]));
makeConstraint(particles.at(temp.vertexIDs[0]), particles.at(temp.vertexIDs[2]));
makeConstraint(particles.at(temp.vertexIDs[1]), particles.at(temp.vertexIDs[2]));
// We need to get the bending springs as well, and i've just written a function to do that.
for (int x = 0; x < faces.size(); x++)
{
Face temp2 = faces[x];
if (l != x)
{
verticesShared(temp, temp2);
}
}
}
And heres the code where I process the bending springs as well:
// Container for any indices the two faces have in common.
std::vector<glm::vec2> traversed;
// Loop through both face's indices, to see if they match eachother.
for (int i = 0; i < a.vertexIDs.size(); i++)
{
for (int k = 0; k < b.vertexIDs.size(); k++)
{
// If we do get a match, we push a vector into the container containing the two indices of the faces so we know which ones are equal.
if (a.vertexIDs.at(i) == b.vertexIDs.at(k))
{
traversed.push_back(glm::vec2(i, k));
}
}
// If we're here, if means we have an edge in common, aka that we have two vertices shared between the two faces.
if (traversed.size() == 2)
{
// Get the adjacent vertices.
int face_a_adj_ind = 3 - ((traversed[0].x) + (traversed[1].x));
int face_b_adj_ind = 3 - ((traversed[0].y) + (traversed[1].y));
// Turn the stored ones from earlier and just get the ACTUAL indices from the face. Indices of indices, eh.
unsigned int adj_1 = a.vertexIDs[face_a_adj_ind];
unsigned int adj_2 = b.vertexIDs[face_b_adj_ind];
// And finally, make a bending spring between the two adjacent particles.
makeConstraint(particles.at(adj_1), particles.at(adj_2));
}
}
I am currently experiencing some heavy slowdowns with my game. I have narrowed it down to something related with texture animations.
In my game there are characters that walk in 1 of 4 possible directions, they will walk up to a point, then change direction and continue walking (sort of like a tower defense game).
First i am loading the sprite frame cache like this
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("characters.plist");
This code is only run once during the life time of my application.
When the characters get loaded to the screen their animation is being set using the following code:
int direction = 0;
int number = 0;
if (this->to_x < 0) // Left
{
direction = 1;
number = 1;
}
else if(this->to_x > 0) // Right
{
direction = 2;
number = 1;
}
if (this->to_y < 0) // Down
{
direction = 0;
number = 0;
}
else if(this->to_y > 0) // Up
{
direction = 3;
number = 2;
}
int s = 0; //skin
// Set the animation
Animation *animation = Animation::create();
for (int i = 0; i < INT16_MAX; i++)
{
string frame_sprite_name = StringUtils::format("%s_%d_%d_%d.png",parameters[name].image_name.c_str(),s,number,i);
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(frame_sprite_name);
if (frame) {
animation->addSpriteFrame(frame);
} else {
break;
}
}
// Invert the sprite when they go right
if (direction == 2) {
setFlippedX(true);
}else{
setFlippedX(false);
}
// Set the pace of the animation based on the type
if (name=="runner") {
animation->setDelayPerUnit(0.15f);
} else{
animation->setDelayPerUnit(0.3f);
}
Animate *animate = Animate::create(animation);
this->stopAllActions();
this->runAction(RepeatForever::create(animate));
What this code does is:
Check the direction
Get the sprite frame from the cache based on the direction
Run the action with repeat forever.
However this code is ran every time they change direction to set the new animation of the active characters. Also, at one time I can have around 40-50 of these characters going around.
I've noticed that after a few minutes in the game the slowdown starts to happen as soon as a new "character" is created, (since they are created in rapid succession in waves). And the slowdown also happens when the characters change in direction. So this makes me believe I am using the textures wrong.
If anyone knows how to fix this please let me know.
PD: I was thinking about the possibility of pre-loading all the animations and then just having each of the sprites that represent the characters run the corresponding animation.
You should definitely cache the animation in the AnimationCache with addAnimation and getAnimation methods.
Hi friends,
How to add sprites using init with file please let me know i am directly adding sprites in Resource folder and thus i am not getting any output. Output is blank screen how to handle it please help?
std::vector <CCSprite*> _sprites;
_sprites.reserve(10);
for (int i=0;i < 5; i++)
{
CCSprite* foo = new cocos2d::CCSprite();
foo->initWithFile( "sprites.png" ); // i am adding sprites but nothing being display??
_sprites.push_back(foo);
}
You need to add the Sprite to a Layer or something.
std::vector <CCSprite*> _sprites;
_sprites.reserve(10);
for (int i=0;i < 5; i++)
{
CCSprite* foo = cocos2d::CCSprite::create("sprites.png");
_sprites.push_back(foo); // <- store your sprites to do stuff to them later.
addChild(foo, 1); //<-- this is adding the child.
}
Well, my question is simple, I'm starting with cocos2d-x programming and I'm trying to make a tiled infinite background, lets say I have a png of an image I want to repeat infinitely as a background, What I did was that I created a Sprite as a container, then I added sprites with the same image, one aside the next, covering about 110% the screen, then, following the Space game tutorial I created the same sprite of sprites once again as a second background and I use it as two large identical images to scroll infinite... it works perfect... but I'm wondering if it is possible to create the second sprite by just copying the frist. Some code maybe will clear my situation:
this goes in the init():
acum = 0.0;
city1 = CCSprite::create();
for(int i = 0; i < 12; ++i) {
CCSprite *city = CCSprite::createWithSpriteFrameName("env_buildings_background2.png");
city->setPosition(ccp(acum, 0));
city1->addChild(city);
acum+= city->getContentSize().width*0.99;
}
city1->setContentSize(ccp(acum, 0));
city2 = CCSprite::create();
acum = 0.0;
for(int i = 0; i < 12; ++i) {
CCSprite *city = CCSprite::createWithSpriteFrameName("env_buildings_background2.png");
city->setPosition(ccp(acum, 0));
city2->addChild(city);
acum+= city->getContentSize().width*0.99;
}
city2->setContentSize(ccp(acum, 0));
_backgroundNode->addChild(city1, -1 , buildingspeed, ccp(0, winSize.height * 0.6));
_backgroundNode->addChild(city2, -1 , buildingspeed, ccp(city1->getContentSize().width, winSize.height * 0.6));
printf("%f - %f\n", city1->getContentSize().width, city2->getContentSize().width);
The main problem is here, where I need to create city2 from city1 and not just repeat code... is there a way to do this? I don't see a constructor in CCSprite that allows me to do so...
this goes in the update():
CCArray *cities = CCArray::createWithCapacity(2);
cities->addObject(city1);
cities->addObject(city2);
for ( int ii = 0; ii <cities->count(); ii++ ) {
CCSprite * city = (CCSprite *)(cities->objectAtIndex(ii));
float xPosition = _backgroundNode->convertToWorldSpace(city->getPosition()).x;
float size = city->getContentSize().width;
if ( xPosition < -size ) {
_backgroundNode->incrementOffset(ccp(city->getContentSize().width*2,0),city);
}
}
I will appreciate any help, thanks in advance.
This code will create the exact snapshot of your citySprite. And as this is a snapshot, you'll be having no access to the sprites that it contains. Cause they are now embedded in the image or sprite itself.
float citySpriteWidth = 480;
float citySpriteHeight = 320;
//Set position in order to make it fit inside CCRenderTexture (You can change this later)
citySprite->setPosition(ccp(citySpriteWidth/2, citySpriteHeight/2));
CCRenderTexture *render = CCRenderTexture::renderTextureWithWidthAndHeight(citySpriteWidth, citySpriteWidth);
render->beginWithClear(0, 0, 0, 0);
citySprite->visit();
render->end();
CCTexture2D *tex = render->getSprite()->getTexture();
CCSprite *newCitySprite = CCSprite::spriteWithTexture(tex);
newCitySprite->setFlipY(true); //Texture might be upside down
Hope this helps your requirements.
Else if your problem is just code repetition. Then you can write a function which would give you your city sprite containing other sprites like this one. And call it number of times you want it.
CCSprite* creteCitySprite()
{
float acum = 0.0;
CCSprite *city1 = CCSprite::create();
for(int i = 0; i < 12; ++i)
{
CCSprite *city = CCSprite::createWithSpriteFrameName("env_buildings_background2.png");
city->setPosition(ccp(acum, 0));
city1->addChild(city);
acum+= city->getContentSize().width*0.99;
}
city1->setContentSize(CCSizeMake(acum, 0));
return city1;
}
EDITED:
This gives you what you want. But what I wanted to say is, the sub sprites which you added to your city1 will remain static.
CCSptire *getSpriteFromSprite(CCSprite *citySprite, float citySpriteWidth, float citySpriteHeight)
{
CCPoint prevPosition = citySprite->getPosition();
//Set position in order to make it fit inside CCRenderTexture (You can change this later)
citySprite->setPosition(ccp(citySpriteWidth/2, citySpriteHeight/2));
CCRenderTexture *render = CCRenderTexture::renderTextureWithWidthAndHeight(citySpriteWidth, citySpriteWidth);
render->beginWithClear(0, 0, 0, 0);
citySprite->visit();
render->end();
citySprite->setPosition(prevPosition);
CCTexture2D *tex = render->getSprite()->getTexture();
CCSprite *newCitySprite = CCSprite::spriteWithTexture(tex);
newCitySprite->setFlipY(true); //Texture might be upside down
}