Loading sprites via loops - c++

I made a small project in C++ using SFML. I added sprites (a character). I have organized the sprites like Assets/Player/Idle/Idle1.jpg then Idle2.jpg and so on.
I initialize the sprites like this:
texture = new Texture[116];
sprite = new Sprite[116];
texture[0].loadFromFile("Assests/Iori/Ready1.png");
sprite[0].setTexture(texture[0]);
texture[1].loadFromFile("Assests/Iori/Ready2.png");
sprite[1].setTexture(texture[1]);
texture[2].loadFromFile("Assests/Iori/Ready3.png");
sprite[2].setTexture(texture[2]);
texture[3].loadFromFile("Assests/Iori/Ready4.png");
sprite[3].setTexture(texture[3]);
texture[4].loadFromFile("Assests/Iori/Ready5.png");
sprite[4].setTexture(texture[4]);
texture[5].loadFromFile("Assests/Iori/Ready6.png");
sprite[5].setTexture(texture[5]);
texture[6].loadFromFile("Assests/Iori/Ready7.png");
And so on. Now this method works fine and loads my sprites completely. But I don't think this is the efficient or right method. I have to load up 100+ sprites and that would just be a mess for a programmer.
I was wondering can you initialize these sprites via a loop (for/while) that would reduce the code a lot.

Use basic for loop and construct name of the texture dynamicaly.
You might need to use explicit cast to std::string or char* depending on the loadFromFile method.
static const int count = 116;
texture = new Texture[count];
sprite = new Sprite[count];
for (int i = 0; i < count; ++i)
{
texture[i].loadFromFile("Assests/Iori/Ready" + std::to_string(i + 1) + ".png");
sprite[i].setTexture(texture[i]);
}

Related

Figuring out best solution for a Maze solver, with animated output

Abstract
My ultimate goal is to use Fltk to take user inputs of pixels, display a generated maze (either my own, or fetch it from the website mentioned in the details), and then show the animated solution.
This is what i've managed so far:
https://giant.gfycat.com/VioletWelloffHatchetfish.webm
Details
I'm in my first c++/algorithm class of a bachelors in CE.
As we've been learning about graphs, dijkstra etc. the last weeks i decided after watching Computerphile's video about Maze solving, to try to put the theory into "practice".
At first i wanted to output a maze from this site, http://hereandabove.com/maze/mazeorig.form.html, with the plotted solution. I chose that walls and paths should be 1x1 pixel, to make it easier to make into a 2D-vector, and then a graph.
This went well, and my program outputs a solved .png file, using dijkstra to find the shortest path.
I then wanted to put the entire solution in an animated gif.
This also works well. For each pixel it colors green/yellow, it passes an RGBA-vector to a gif-library, and in the end i end up with an animated step by step solution.
I also for each RGBA-vector passed to the gif-library, scale it up first, using this function:
//Both the buffer and resized buffer are member variables, and for each //plotted pixel in the path it updates 'buffer', and in this function makes a //larger version of it to 'resized_buffer'
// HEIGHT and WIDTH are the original size
// nHeight and nWidth are the new size.
bool Maze_IMG::resample(int nWidth, int nHeight)
{
if (buffer.size() == 0) return false;
resized_buffer.clear();
for (int i = 0; i < nWidth * nHeight * 4; i++) resized_buffer.push_back(-1);
double scaleWidth = (double)nWidth / (double)WIDTH;
double scaleHeight = (double)nHeight / (double)HEIGHT;
for (int cy = 0; cy < nHeight; cy++)
{
for (int cx = 0; cx < nWidth; cx++)
{
int pixel = (cy * (nWidth * 4)) + (cx * 4);
int nearestMatch = (((int)(cy / scaleHeight) * (WIDTH * 4)) + ((int)(cx / scaleWidth) * 4));
resized_buffer[pixel] = buffer[nearestMatch];
resized_buffer[pixel + 1] = buffer[nearestMatch + 1];
resized_buffer[pixel + 2] = buffer[nearestMatch + 2];
resized_buffer[pixel + 3] = buffer[nearestMatch + 3];
}
}
return true;
}
Problems
The problem is that it takes a looong time to do this while scaling them up, even with "small" mazes at 50x50 pixels, when trying to scale them to say 300x300. I've spent a lot of time to make code as efficient and fast as possible, but after i added the scaling, stuff that used to take 10 minutes, now takes hours.
In fltk i use the Fl_Anim_Gif-library to display animated gifs, but it wont load the maze gifs that has been scaled up (still troubleshooting this).
My real questions
Is it possible to improve the scaling function, so that it does not take forever? Or is this a totally wrong approach?
Is it a stupid idea to try to display it as a gif in fltk, would it be easier to just draw it directly in fltk, or should i rather try to display the images one after another i fltk?
I'm just familiarizing myself with fltk. Would it be easier now to use something like Qt instead. Would that be more beneficial in the long run as far as learning a GUI-library goes?
I'm mainly doing this for learning, and to start building some sort of portfolio for when i graduate. Is it beneficial at all to make a gui for this, or is this a waste of time?
Any thoughts or input would be greatly appreciated.
Whatever graphics package you use, the performance will be similar. It depends on how you handle the internals. For instance,
If you write it to a buffer and BLT it to the screen, it would be faster than writing to the screen directly.
If you only BLT on the paint event, it would be faster than forcing and update every time the screen data changes.
If you preallocate the buffers then the system does not have to keep on reallocating whenever the buffer space runs out.
Assuming that the space is preallocated, it can be written to without clearing first. Every cell it going to be written to so no need to clear, allocate and and reallocate.

SDL tilemap rendering quite slow

Im using SDL to write a simulation that displays quite a big tilemap(around 240*240 tiles). Since im quite new to the SDL library I cant really tell if the pretty slow performance while rendering more than 50,000 tiles is actually normal. Every tile is visible at all times, being around 4*4px big. Currently its iterating every frame through a 2d array and rendering every single tile, which gives me about 40fps, too slow to actually put any game logic behind the system.
I tried to find some alternative systems, like only updating updated tiles but people always commented on how this is a bad practice and that the renderer is supposed to be cleaned every frame and so on.
Here a picture of the map
So I basically wanted to ask if there is any more performant system than rendering every single tile every frame.
Edit: So heres the simple rendering method im using
void World::DirtyBiomeDraw(Graphics *graphics) {
if(_biomeTexture == NULL) {
_biomeTexture = graphics->loadImage("assets/biome_sprites.png");
printf("Biome texture loaded.\n");
}
for(int i = 0; i < globals::WORLD_WIDTH; i++) {
for(int l = 0; l < globals::WORLD_HEIGHT; l++) {
SDL_Rect srect;
srect.h = globals::SPRITE_SIZE;
srect.w = globals::SPRITE_SIZE;
if(sites[l][i].biome > 0) {
srect.y = 0;
srect.x = (globals::SPRITE_SIZE * sites[l][i].biome) - globals::SPRITE_SIZE;
}
else {
srect.y = globals::SPRITE_SIZE;
srect.x = globals::SPRITE_SIZE * fabs(sites[l][i].biome);
}
SDL_Rect drect = {i * globals::SPRITE_SIZE * globals::SPRITE_SCALE, l * globals::SPRITE_SIZE * globals::SPRITE_SCALE,
globals::SPRITE_SIZE * globals::SPRITE_SCALE, globals::SPRITE_SIZE * globals::SPRITE_SCALE};
graphics->blitOnRenderer(_biomeTexture, &srect, &drect);
}
}
}
So in this context every tile is called "site", this is because they're also storing information like moisture, temperature and so on.
Every site got a biome assigned during the generation process, every biome is basically an ID, every land biome has an ID higher than 0 and every water id is 0 or lower.
This allows me to put every biome sprite ordered by ID into the "biome_sprites.png" image. All the land sprites are basically in the first row, while all the water tiles are in the second row. This way I dont have to manually assign a sprite to a biome and the method can do it itself by multiplying the tile size(basically the width) with the biome.
Heres the biome ID table from my SDD/GDD and the actual spritesheet.
The blitOnRenderer method from the graphics class basically just runs a SDL_RenderCopy blitting the texture onto the renderer.
void Graphics::blitOnRenderer(SDL_Texture *texture, SDL_Rect
*sourceRectangle, SDL_Rect *destinationRectangle) {
SDL_RenderCopy(this->_renderer, texture, sourceRectangle, destinationRectangle);
}
In the game loop every frame a RenderClear and RenderPresent gets called.
I really hope I explained it understandably, ask anything you want, im the one asking you guys for help so the least I can do is be cooperative :D
Poke the SDL2 devs for a multi-item version of SDL_RenderCopy() (similar to the existing SDL_RenderDrawLines()/SDL_RenderDrawPoints()/SDL_RenderDrawRects() functions) and/or batched SDL_Renderer backends.
Right now you're trying slam at least 240*240 = 57000 draw-calls down the GPU's throat; you can usually only count on 1000-4000 draw-calls in any given 16 milliseconds.
Alternatively switch to OpenGL & do the batching yourself.

cocos2d-x v3 c++ Drop shadow cocos2d::Sprite

As far as I've found out, cocos doesn't offer a simple filter handling like AS3 for example does.
My situation:
I want to add a realtime shadow to an cocos2d::Sprite.
For example I would like to do something like this (similar to AS3):
auto mySprite = Sprite::createWithSpriteFrameName("myCharacter.png");
DropShadowFilter* dropShadow = new DropShadowFilter();
dropShadow->distance = 0;
dropShadow->angle = 45;
dropShadow->color = 0x333333;
dropShadow->alpha = 1;
dropShadow->blurX = 10;
dropShadow->blurY = 10;
dropShadow->strength = 1;
dropShadow->quality = 15;
mySprite->addFilter(dropShadow);
This should add a shadow to my Sprite to achieve an result like this:
Adobe Drop Shadow Example
Could you help me please?
There isn't any built in support for shadows on Sprites in Cocos2D-X.
The best option, performance-wise, would be to place your shadows in your sprite images already, instead of calculating and drawing them in the code.
Another option is to sub-class Sprite and override the draw method so that you duplicate the sprite and apply your effects and draw it below the original.
One possible way to achieve that is with this snippet from this thread on the Cocos forum. I can't say that I completely follow what this code does with the GL transforms, but you can use this as a starting point to experiment.
void CMySprite::draw()
{
// is_shadow is true if this sprite is to be considered like a shadow sprite, false otherwise.#
if (is_shadow)
{
ccBlendFunc blend;
// Change the default blending factors to this one.
blend.src = GL_SRC_ALPHA;
blend.dst = GL_ONE;
setBlendFunc( blend );
// Change the blending equation to thi in order to subtract from the values already written in the frame buffer
// the ones of the sprite.
glBlendEquationOES(GL_FUNC_REVERSE_SUBTRACT_OES);
}
CCSprite::draw();
if (is_shadow)
{
// The default blending function of cocos2d-x is GL_FUNC_ADD.
glBlendEquationOES(GL_FUNC_ADD_OES);
}
}

Memory increase rapidly using gluTess*, display list and frame buffer

I'm programming with OpenGL under MSVC 2010.
One of my goal is to pick objects in the scene. I design it in the way like assigning each object a unique color, rendering them in a framebuffer, then reading the color where the cursor is, and the corresponding object can be acquired.
Now the picking is working well. However, as long as a picking happens, the memory increases rapidly. In detail, the following code render objects into a framebuffer:
for (unsigned i = 0; i < objects.size(); ++i)
{
//some code computing color;
Color color;
for (unsigned j = 0; j < objects[i].listOfPrimitives.size(); ++j)
{
objects[i].listOfPrimitives[j]->color = color;
}
objects[i].Render();
for (unsigned j = 0; j < objects[i].listOfPrimitives.size(); ++j)
{
objects[i].listOfPrimitives[j]->color = colorStorage[i][j];
}
}
where objects are objects to be rendered. Since every object has a certain number of primitives(which may be a cylinder, sphere etc.), this piece of code just changes the color of each object's primitives to a unique computed one, render the object, then change it back (colorSotrage stores the original colors). And there are some code in the following to deal with the object, which I'm sure has nothing to do with this issue.
The render method are implemented as following for most object:
glColor3ub(color[0], color[1], color[2]);
glBegin(GL_TRIANGLES);
for (unsigned i = 0; i < mesh.faces.size(); ++i)
{
glNormal3d(mesh.faces[i].normal.x, mesh.faces[i].normal.y, mesh.faces[i].normal.z);
for (unsigned j = 0; j < 3; ++j)
{
glVertex3d(mesh.vertices[mesh.faces[i].verts[j]].x,
mesh.vertices[mesh.faces[i].verts[j]].y,
mesh.vertices[mesh.faces[i].verts[j]].z);
}
}
glEnd();
But for some object, there are some concave polygons (even with holes), so I use the gluTess* group functions in GLU to render them, and to speed up the rendering procedure, I use display list to that part.
Now, as I've mentioned. this picking procedure increases the memory cost rapidly. There are two more phenomenons I can't explain:
If I comment line 8 in the first piece of code, the memory will not change at all when the piece of code runs (of course, this code will not work);
After the memory increases, if I do some refresh to the scene (I design an interactive trackball), the memory will drop off again.
So I'm wondering which part could be the reason of this issue? The display list? the gluTess*() calling? or even something related to framebuffer?

Adding bullets yield OpenGL error 0x0503 in -[EAGLView swapBuffers]

I am trying to build up my first game with cocos2d. I am trying to insert bullets. when I get this error. The problem is it only occurs when a player fires not for enemy sprites. When this error occurs no only the position of player swaps with another and back also the bullet is destroyed after hitting two targets.
OpenGL error 0x0503 in -[EAGLView swapBuffers]
my weapon class has the following bullet implementation
if([self.bulletsArray count] <= ([self.numberOfBulletsPerFire intValue]*[self.numberOfBulletsOnScreen intValue]))
{
for (int i =0; i< [self.numberOfBulletsPerFire intValue]; i++) {
BulletClass *bullet = [[Bullet alloc]initWithPosition:position Direction:direction strength:self.weaponLevel spriteArray:spriteArray enemyArray:enemyArray base:base];
[self.bulletsArray addObject:bullet];
[self addChild:bullet];
[bullet release];bullet = nil;
}
}
in BulletClass i have the init method as :
(id)initWithPosition:(CGPoint)position
Direction:(KDirectionInput)direction
strength:(NSNumber *)strength
spriteArray:(NSMutableArray *)sprites
enemyArray:(NSMutableArray *)enemyArray
base:(CCSprite *)base{
if ((self = [super init])) {
self.base = base;
self.strength = strength;
self.movementDirection = direction;
self.spriteArray = sprites;
self.enemyArray = enemyArray;
self.velocity = 200/1;
self.bullet.position = position;
[self addChild:self.bullet z:2];
}
return self;
}
can anyone help me out here..
There are a few issues here that may be contributing to your problems.
First, while not a bug but more of a performance thing, you should not place counts and other object methods like intValue in your conditions, as this slows down the program. Define a local variable just before your loops that equals this number, and then use that variable in the loop so the software doesn't have count the same array or extract the same value over and over again every time it loops.
More importantly, I do not see anywhere that you are using a sprite frame cache (sprite batch), and if you are using sprite arrays that are very large where your array counts are high and manipulating and drawing these sprites many times as is typically requested by bullet operations, you could be adding a lot of burden to OpenGL unnecessarily, perhaps creating the buffer error you saw.
You should use a cocos sprite batch for your sprite arrays and give this another try; at the very least it will vastly improve the program's performance for bullet operations.