I am working in C++ SDL lib. And I am trying to dynamically create a number of rectangles. But it doesn't work. The only solution I found over searching stackoverflow.com been to create a constant value, which I don't want to.
Can anyone help me?
This is my code:
void lvl001(){
max_score = 20;
count_enemies = 2;
SDL_Surface *enemie;
SDL_Rect enemies_sources[no] , enemies[no];
enemie = SDL_LoadBMP("player.bmp");
for( int count = 1; count <= no ; count++ ){
enemies_sources[count].x = 0;
}
}
And one more thing. If there would be an solution to this, then how should I proceed if I want to blit it (SDL_Blit...)?
In C++, dynamic arrays are created using std::vector<T>, and looped through using the range-based for when you don't care about the indices:
std::vector<SDL_Rect> enemies_sources(no);
std::vector<SDL_Rect> enemies(no);
for (auto& source : enemies_sources)
{
source.x = 0;
}
Related
So I'm trying to modify the Kinect BodyBasicsD2D code so that a fixed number of "target positions" appear on the screen (as ellipses) for the user to move his hand toward. I'm having trouble creating the initial target positions.
This is my code in the header file for the allocation of the array of target positions (these are a public field of the CBodyBasics class, already built into the original BodyToBasics program):
D2D1_POINT_2F* targetPositions = NULL;
int numTargets = 3;
Then I have a function "GenerateTargetPositions" which is supposed to generate 3, in this case, target positions to be passed into the "DrawTargetPositions" function.
void CBodyBasics::GenerateTargetPositions(D2D1_POINT_2F * targetPositions, int numTargets)
{
targetPositions = new D2D1_POINT_2F[numTargets];
RECT rct;
GetClientRect(GetDlgItem(m_hWnd, IDC_VIDEOVIEW), &rct);
int width = rct.right;
int height = rct.bottom;
FLOAT x;
FLOAT y;
D2D1_POINT_2F tempPoint;
for (int i = 0; i < numTargets; i++) {
x = 1.0f*i*width / numTargets;
y = 1.0f*i*height / numTargets;
tempPoint = D2D1::Point2F(x, y);
targetPositions[i] = tempPoint;
}
}
My DrawTargetPositions function is:
void CBodyBasics::DrawTargetPositions(D2D1_POINT_2F * targetPositions, int numTargets)
{
D2D1_ELLIPSE ellipse;
for (int i = 0; i < numTargets; i++)
{
ellipse = D2D1::Ellipse(targetPositions[i], 50.f, 50.f);
m_pRenderTarget->FillEllipse(ellipse, m_pSilverBrush);
}
}
When I try to run my code, I get the error that both "targetPositions" and "targetPositions[i]" is NULL (and thus my GenerateTargetPositions function must not be working properly). I believe that targetPositions[i] is a struct (a point with x and y values) so I am wondering if this may be the reason for my errors.
I call GenerateTargetPositions and DrawTargetPositions before the main "while" loop in my code so that each function is not being called on each iteration (there are many iterations of through the while loop because this is an interactive Microsoft Kinect, recording one's movements).
Any suggestions and advice would be greatly appreciated. Thanks so much!
I am trying to create array sprites which contain 5 sprites as 0.png, 1.png, 2.png, 3.png, 4.png.
I want them to appear randomly on the screen.
Below is my code but its not working, any help?
std::vector <CCSprite*> _sprites;
_sprites.reserve(10);
int spritearray[5] = { 0.png,1.png,2.png,3.png,4.png }; // I AM GETTING ERROR HERE?
int i;
for(i=0;i<5;i++)
{
CCSprite* foo = new cocos2d::CCSprite();
int index = rand() % 5;
// foo->initWithFile(index);
foo->setPosition(ccp(60,50*i));
_sprites.push_back(foo); //store our sprites to do other stuffs later
this->addChild(foo,1);
}
Your "logic" currently is fine, it's the implementation that you have problem with.
If you check the initWithFile function, you see that it takes a file name as a string.
So you need to make an array of strings (the file names) and not an array of integers. Then you use the random index as index into this file-name array and pass it as argument to the initWithFile function.
Ok, you are using the same code I provided you before:
std::vector <CCSprite*> _sprites;
_sprites.reserve(10);
std::vector<std::string> _spriteNames = {"0.png", "1.png", "2.png", "3.png", "4.png"};
for (int i=0;i < _spriteNames.size(); i++)
{
CCSprite* foo = cocos2d::CCSprite::create(_spriteNames.at(i));
int random = rand() % 5;
foo->setPosition(CCPoint((60 * random), (50 * random)));
_sprites.push_back(foo); // <- store your sprites to do stuff to them later.
addChild(foo, 1); //<-- this is adding the child.
}
I guess it's such an easy question (I'm coming from Java), but I can't figure out how it works.
I simply want to increment an vector element by one. The reason for this is, that I want to compute a histogram out of image values. But whatever I try I just can accomplish to assign a value to the vector. But not to increment it by one!
This is my histogram function:
void histogram(unsigned char** image, int height,
int width, vector<unsigned char>& histogramArray) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
// histogramArray[1] = (int)histogramArray[1] + (int)1;
// add histogram position by one if greylevel occured
histogramArray[(int)image[i][j]]++;
}
}
// display output
for (int i = 0; i < 256; i++) {
cout << "Position: " << i << endl;
cout << "Histogram Value: " << (int)histogramArray[i] << endl;
}
}
But whatever I try to add one to the histogramArray position, it leads to just 0 in the output. I'm only allowed to assign concrete values like:
histogramArray[1] = 2;
Is there any simple and easy way? I though iterators are hopefully not necesarry at this point, because I know the exakt index position where I want to increment something.
EDIT:
I'm so sorry, I should have been more precise with my question, thank you for your help so far! The code above is working, but it shows a different mean value out of the histogram (difference of around 90) than it should. Also the histogram values are way different than in a graphic program - even though the image values are exactly the same! Thats why I investigated the function and found out if I set the histogram to zeros and then just try to increase one element, nothing happens! This is the commented code above:
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
histogramArray[1]++;
// add histogram position by one if greylevel occured
// histogramArray[(int)image[i][j]]++;
}
}
So the position 1 remains 0, instead of having the value height*width. Because of this, I think the correct calculation histogramArray[image[i][j]]++; is also not working properly.
Do you have any explanation for this? This was my main question, I'm sorry.
Just for completeness, this is my mean function for the histogram:
unsigned char meanHistogram(vector<unsigned char>& histogram) {
int allOccurences = 0;
int allValues = 0;
for (int i = 0; i < 256; i++) {
allOccurences += histogram[i] * i;
allValues += histogram[i];
}
return (allOccurences / (float) allValues) + 0.5f;
}
And I initialize the image like this:
unsigned char** image= new unsigned char*[width];
for (int i = 0; i < width; i++) {
image[i] = new unsigned char[height];
}
But there shouldn't be any problem with the initialization code, since all other computations work perfectly and I am able to manipulate and safe the original image. But it's true, that I should change width and height - since I had only square images it didn't matter so far.
The Histogram is created like this and then the function is called like that:
vector<unsigned char> histogramArray(256);
histogram(array, adaptedHeight, adaptedWidth, histogramArray);
So do you have any clue why this part histogramArray[1]++; don't increases my histogram? histogramArray[1] remains 0 all the time! histogramArray[1] = 2; is working perfectly. Also histogramArray[(int)image[i][j]]++; seems to calculate something, but as I said, I think it's wrongly calculating.
I appreciate any help very much! The reason why I used a 2D Array is simply because it is asked for. I like the 1D version also much more, because it's way simpler!
You see, the current problem in your code is not incrementing a value versus assigning to it; it's the way you index your image. The way you've written your histogram function and the image access part puts very fine restrictions on how you need to allocate your images for this code to work.
For example, assuming your histogram function is as you've written it above, none of these image allocation strategies will work: (I've used char instead of unsigned char for brevity.)
char image [width * height]; // Obvious; "char[]" != "char **"
char * image = new char [width * height]; // "char*" != "char **"
char image [height][width]; // Most surprisingly, this won't work either.
The reason why the third case won't work is tough to explain simply. Suffice it to say that a 2D array like this will not implicitly decay into a pointer to pointer, and if it did, it would be meaningless. Contrary to what you might read in some books or hear from some people, in C/C++, arrays and pointers are not the same thing!
Anyway, for your histogram function to work correctly, you have to allocate your image like this:
char** image = new char* [height];
for (int i = 0; i < height; ++i)
image[i] = new char [width];
Now you can fill the image, for example:
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
image[i][j] = rand() % 256; // Or whatever...
On an image allocated like this, you can call your histogram function and it will work. After you're done with this image, you have to free it like this:
for (int i = 0; i < height; ++i)
delete[] image[i];
delete[] image;
For now, that's enough about allocation. I'll come back to it later.
In addition to the above, it is vital to note the order of iteration over your image. The way you've written it, you iterate over your columns on the outside, and your inner loop walks over the rows. Most (all?) image file formats and many (most?) image processing applications I've seen do it the other way around. The memory allocations I've shown above also assume that the first index is for the row, and the second is for the column. I suggest you do this too, unless you've very good reasons not to.
No matter which layout you choose for your images (the recommended row-major, or your current column-major,) it is in issue that you should always keep in your mind and take notice of.
Now, on to my recommended way of allocating and accessing images and calculating histograms.
I suggest that you allocate and free images like this:
// Allocate:
char * image = new char [height * width];
// Free:
delete[] image;
That's it; no nasty (de)allocation loops, and every image is one contiguous block of memory. When you want to access row i and column j (note which is which) you do it like this:
image[i * width + j] = 42;
char x = image[i * width + j];
And you'd calculate the histogram like this:
void histogram (
unsigned char * image, int height, int width,
// Note that the elements here are pixel-counts, not colors!
vector<unsigned> & histogram
) {
// Make sure histogram has enough room; you can do this outside as well.
if (histogram.size() < 256)
histogram.resize (256, 0);
int pixels = height * width;
for (int i = 0; i < pixels; ++i)
histogram[image[i]]++;
}
I've eliminated the printing code, which should not be there anyway. Note that I've used a single loop to go through the whole image; this is another advantage of allocating a 1D array. Also, for this particular function, it doesn't matter whether your images are row-major or column major, since it doesn't matter in what order we go through the pixels; it only matters that we go through all the pixels and nothing more.
UPDATE: After the question update, I think all of the above discussion is moot and notwithstanding! I believe the problem could be in the declaration of the histogram vector. It should be a vector of unsigned ints, not single bytes. Your problem seems to be that the value of the vector elements seem to stay at zero when your simplify the code and increment just one element, and are off from the values they need to be when you run the actual code. Well, this could be a symptom of numeric wrap-around. If the number of pixels in your image are a a multiple of 256 (e.g. 32x32 or 1024x1024 image) then it is natural that the sum of their number would be 0 mod 256.
I've already alluded to this point in my original answer. If you read my implementation of the histogram function, you see in the signature that I've declared my vector as vector<unsigned> and have put a comment above it that says this victor counts pixels, so its data type should be suitable.
I guess I should have made it bolder and clearer! I hope this solves your problem.
I have this in my file blocks.h:
#include <vector>
class Blocks{
public:
string files_name[4];
vector < Sprite > sprites;
void load(){
for(int i=0;i<=sizeof(files_name);i++){
Texture my_texture;
my_texture.loadFromFile(this->files_name[i]);
sprites[i].setTexture( my_texture );
}
}
Blocks(){
this->files_name[0] = "wall.png";
this->files_name[1] = "floor.png";
this->files_name[2] = "live.png";
this->files_name[3] = "coins.png";
this->load();
}
void show(int id, int X, int Y){
sprites[id].setPosition(X, Y);
window.draw(sprites[id]);
}
};
I have no errors, but my game crashed. I think, the problem is in the line which reads sprites[i].setTexture(...)
I only have the message: Process terminated with status -1073741819 (0 minutes, 2 seconds)
My IDE is Code::Blocks 10.05, and I have Windows 8.
Of course, in the file main.cpp, I have defined the window:
RenderWindow window( VideoMode(920, 640, 32 ), "Game" );
#include "blocks.h"
Blocks BLOCKS;
----UPDATE:
Ok, now it's not crashing, thanks! But, now I can't see textures! I read the post by Benjamin Lindley and I added a new vector with textures. My code looks like this now:
const int arraySize = 4;
string files_name[4];
vector < Sprite > sprites;
vector < Texture > textures;
and, in load(), I have:
for(int i = 0; i < arraySize; i++){
Texture new_texture;
new_texture.loadFromFile(this->files_name[i]);
textures.push_back(new_texture);
sprites[i].setTexture(textures[i]);
and then it crashes again!
---UPDATE: Now I have again changed my code and I don't have a crash, but my textures are white squares. My texture live.png works, but the other textures are white! Here's my new code:
Sprite new_sprite;
new_sprite.setTexture(textures[i]);
sprites.push_back(new_sprite);
The problem is this line:
for(int i=0;i<=sizeof(files_name);i++){
If you print out the value of sizeof(files_name), you will find that it is 16 instead of 4! Don't use sizeof here. Also, don't use <= here, since even if you had replaced sizeof(files_name) with 4, you would have tried to access files_name[4], which would also give you an error.
Instead you could use:
const int arraySize = 4;
string files_name[arraySize];
...
for(int i = 0; i < arraySize; i++)
or something of that sort.
Also, hopefully you initialize sprites at some point. You need to fill your vector with Sprites (with something like sprites.push_back(mySprite)) before you call load().
SFML sprites store their associated textures by pointer. The textures you are creating are local to the loop, and so are destroyed at the end of each iteration, thereby invalidating the pointer in the sprite. You need to keep your textures alive for the duration of whatever sprite uses them.
Also, your sprites vector has no elements, you need to either specify a size, or use push_back in your loop.
Also, as Scott pointed out, sizeof(files_name) is not the appropriate terminating value for your loop, since that gives you sizeof(string) * number of elements in the array. You only want the number of elements in the array.
Ok, it works only in two loop: Thanks for helping :)
vector < Sprite > sprites;
vector < Texture > tekstures;
and:
for(int i = 0; i < arraySize; i++){
Texture new_texture;
new_texture.loadFromFile(this->files_name[i]);
tekstures.push_back(new_texture);
}
for(int i = 0; i < arraySize; i++){
Sprite new_sprite;
new_sprite.setTexture(tekstures[i]);
sprites.push_back(new_sprite);
}
and in one loop it doesn't work, i have white textures:
for(int i = 0; i < arraySize; i++){
Texture new_texture;
new_texture.loadFromFile(this->files_name[i]);
tekstures.push_back(new_texture);
Sprite new_sprite;
new_sprite.setTexture(tekstures[i]);
sprites.push_back(new_sprite);
}
Greetings !
I'm developing a 3D game using SDL and OpenGL on Ubuntu 9.04 using Eclipse CDT. I've got a class to hold the mesh data in vectors for each type. Such as Vertex, Normal, UVcoord (texture coordinates), as well as a vector of faces. Each face has 3 int vectors which hold indexes to the other data. So far my game has been working quite well at rendering at nice rates. But then again I only had less then one hundred vertexes among two objects for testing purposes.
The loop accessing this data looks like this:
void RenderFace(oFace face)
{
/*
* More Stuff
*/
oVertice gvert;
oUVcoord tvert;
oNormal nvert;
for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
{
gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);
tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);
nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);
glNormal3f(nvert.X, nvert.Y, nvert.Z);
glTexCoord2f(tvert.U, tvert.V);
glVertex3f(scale * gvert.X, scale * gvert.Y, scale * gvert.Z);
}
/*
* More Stuff
*/
}
There is a loop that calls the renderFace() function which includes the above for loop. The minus one is because Wavefront .obj files are 1 indexed (instead of c++ 0 index). Anyway, I discovered that once you have about 30 thousand or so faces, all those calls to glVertex3f() and the like slow the game down to about 10 FPS. That I can't allow. So I learned about vertex arrays, which require pointers to arrays. Following the example of a NeHe tutorial I continued to use my oVertice class and the others. Which just have floats x, y, z, or u, v. So I added the same function above to my OnLoad() function to build the arrays which are just "oVertice*" and similar.
Here is the code:
bool oEntity::OnLoad(std::string FileName)
{
if (!obj.OnLoad(FileName))
{
return false;
}
unsigned int flsize = obj.TheMesh.GetFaceListSize();
obj.TheMesh.VertListPointer = new oVertice[flsize];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
obj.TheMesh.NormListPointer = new oNormal[flsize];
oFace face = obj.TheMesh.GetFace(0);
oVertice gvert;
oUVcoord tvert;
oNormal nvert;
unsigned int counter = 0;
unsigned int temp = 0;
for (unsigned int flIndex = 0; flIndex < obj.TheMesh.GetFaceListSize(); flIndex++)
{
face = obj.TheMesh.GetFace(flIndex);
for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
{
temp = face.GeoVerts[fvIndex];
gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);
temp = face.UV_Verts[fvIndex];
tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);
temp = face.NrmVerts[fvIndex];
nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);
obj.TheMesh.VertListPointer[counter].X = gvert.X;
obj.TheMesh.VertListPointer[counter].Y = gvert.Y;
obj.TheMesh.VertListPointer[counter].Z = gvert.Z;
obj.TheMesh.UVlistPointer[counter].U = tvert.U;
obj.TheMesh.UVlistPointer[counter].V = tvert.V;
obj.TheMesh.NormListPointer[counter].X = nvert.X;
obj.TheMesh.NormListPointer[counter].Y = nvert.Y;
obj.TheMesh.NormListPointer[counter].Z = nvert.Z;
counter++;
}
}
return true;
}
The unsigned int temp variable is for debugging purposes. Apparently I don't have a default constructor for oFace that doesn't have something to initialize with. Anyway, as you can see it's pretty much that same exact routine. Only instead of calling a gl function I add the data to three arrays.
Here's the kicker:
I'm loading a typical cube made of triangles.
When I access element 16 (0 indexed) of the UV_Verts vector from the RenderFace() function I get 12.
But when I access element 16 (0 indexed) of the same UV_Verts vector from the OnLoad() function I get something like 3045472189
I am so confused.
Does anyone know what's causing this? And if so how to resolve it?
One possible reason could be that you're creating arrays with size flsize:
obj.TheMesh.VertListPointer = new oVertice[flsize];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
obj.TheMesh.NormListPointer = new oNormal[flsize];
but use the arrays with indices up to flsize * face.GeoVerts.size
for (...; flIndex < obj.TheMesh.GetFaceListSize(); ...) { // flsize = GetFaceListSize
for (...; fvIndex < face.GeoVerts.size(); ...) {
...
obj.TheMesh.UVlistPointer[counter].U = ...;
...
counter++;
}
}
so your array creation code should actually be more like
obj.TheMesh.VertListPointer = new oVertice[flsize * face.GeoVerts.size()];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize * face.GeoVerts.size()];
obj.TheMesh.NormListPointer = new oNormal[flsize * face.GeoVerts.size()];