game.batch.begin();
for (Array obstacle_array123: obstacle_array) {
body = obstacle_array123;
for (Body bodies: body) {
if (bodies.getUserData() instanceof Array && bodies.isActive()) {
sprites_array = (Array)bodies.getUserData();
for (int fix_pos = 0; fix_pos < sprites_array.size; fix_pos++) {
sprite = sprites_array.get(fix_pos);
if (verts.size != 0) verts.removeRange(0, verts.size - 1);
f = bodies.getFixtureList().get(fix_pos);
s = (PolygonShape)f.getShape();
transform = bodies.getTransform();
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(new Vector2(tmp));
}
rotation_point.set((verts.get(0).x + verts.get(1).x + verts.get(2).x + verts.get(3).x) / 4, (verts.get(0).y + verts.get(1).y + verts.get(2).y + verts.get(3).y) / 4);
sprite.setPosition(rotation_point.x - sprite.getWidth() / 2, rotation_point.y - sprite.getHeight() / 2);
sprite.setRotation(bodies.getAngle() * MathUtils.radiansToDegrees);
sprite.draw(game.batch);
}
}
}
}
game.batch.end();
I have a game where my bodies are made from multiple square fixtures, so this is the code to render each square sprite on each square fixture.
2 problems - 1.st --> it only renders the first sprite in the array
2.nd --> if you look at the following loop (SOLVED)
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(new Vector2(tmp));
}
well it is apperantly different compared to
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(tmp);
}
The spawned coordinates in 2nd example are wrong for half width and half height of the square.
When I try to get the coordinated from both examples the numbers are the same, but when setting the sprite position, 2nd example goes off.
You should probably ask both questions separately, but to answer your second question, then they ARE different.
In the first one you add a new Vector2 to verts each time through the loop. So verts will end up holding a load of different Vector2's.
In the second one you add the same Vector2 to verts over and over again, so it will just have one Vector2 with the same value over and over again (remember Java is pass by reference).
Caveat - My answer assumes that verts is some sort of standard collection or a libgdx Array.
Related
In my Android project,
Here is my code.
for (int x = 0; x < targetBitArray.length; x += weight) {
for (int y = 0; y < targetBitArray[x].length; y += weight) {
targetBitArray[x][y] = bmp.getPixel(x, y) == mSearchColor;
}
}
but this code wastes a lot of time.
So I need to find way faster than bitmap.getPixel().
I'm trying to get pixel color using byte array converted from bitmap, but I can't.
How to replace Bitmap.getPixel()?
Each Bitmap.getPixel method invocation requires a lot of resources, so you need to avoid the amount of requests in order to improve the performace of your code.
My suggestion is:
Read the image data row-by-row with Bitmap.getPixels method into a local array
Iterate along your local array
e.g.
int [] rowData= new int [bitmapWidth];
for (int row = 0; row < bitmapHeight; row ++) {
// Load row of pixels
bitmap.getPixels(rowData, 0, bitmapWidth, 0, row, bitmapWidth, 1);
for (int column = 0; column < bitmapWidth; column ++) {
targetBitArray[column][row] = rowData(column) == mSearchColor;
}
}
This will be a great improvement for the performace of your code
I created 5 sprites using libgdx library, then want to assign the different size to all of them between 0 to 10 and then move from left to right. 5 sprite is succussfully created but the problem is in the size. i tried the S.nextInt(10). but its not working.
Also i want to create all the sprites between 100-200 height. how to do it?
int number = 5;
sprite = new Sprite[number];
for (int i = 0; i < number; i++) {
sprite[i] = new Sprite(texture);
int size = S.nextInt(10);
sprite[i].setSize(size, size);
speed = S.nextInt(2);
sprite[i].setPosition(speed, 100);
}
batch.begin();
for (int i = 0; i < number; i++) {
sprite[i].draw(batch);
}
batch.end();
I was trying to realize an actually simple action, namely to change the color of a normal bitmap.
Unfortunately, there appeared a few errors. In my case I want a bitmap of grey steel to turn into redder steel. Therefore, I wrote some code, which gets the color int of each pixel and raises the red value for each one. Now two things happen:
Firstly, it really takes a long, long time to convert all the pixels, even if I use an AsyncTask.
Secondly, when it finishes one cycle, the whole bitmap kind of rotates and multiplies like in the picture below.
Is there any way to smoothly realize my aim? The thing is that I often see this action in other apps without having problems, so the must be a way to reach my goal.
Thank you!
PS: Please do not be irritated by the comments, they are just tries to find another way!
"steel image" https://drive.google.com/file/d/0B72QIg-baxzjakJsQkFRZFVFOFU/edit?usp=sharing
public void adjustColor(Bitmap bmp)
{
/*for(int i=0; i<bmp.getHeight()-1; i++) {
for(int j=0; j<bmp.getWidth()-1; j++) {
if(bmp.getPixel(j, i) != Color.TRANSPARENT) {
if(Color.green(bmp.getPixel(j, i)) <= 175 && Color.green(bmp.getPixel(j, i)) >= 65) {
red = Color.red(bmp.getPixel(j, i));
green = Color.green(bmp.getPixel(j, i));
blue = Color.blue(bmp.getPixel(j, i));
if (i == bmp.getHeight()-1) {
red = Color.red(bmp.getPixel(j, bmp.getHeight()));
green = Color.green(bmp.getPixel(j, bmp.getHeight()));
blue = Color.blue(bmp.getPixel(j, bmp.getHeight()));}
if ((red + mOfen.heatQ/10) <= 205) red = red + mOfen.heatQ/10;
bmp.setPixel(j, i, Color.rgb(red, green, blue));
}}
}
}*/
for(int h=0; h<bmp.getWidth()*bmp.getHeight(); h++) {
int x = h-bmp.getWidth()*(((int)h/bmp.getWidth()+1)-1);
int y = h/bmp.getWidth();
Log.d("roh", "y " + Integer.toString(y));
Log.d("roh", "height " + Integer.toString(bmp.getHeight()));
if(Color.green(bmp.getPixel(x, y)) <= 175 && Color.green(bmp.getPixel(x, y)) >= 65) {
bmp.setPixel(x, y, Color.WHITE);
red = Color.red( allpixels[h] );
green = Color.green( allpixels[h] );
blue = Color.blue( allpixels[h] );
/* for(int n=1; n<=10; n++) {
/*Log.d("roh", "left " + Float.toString(mOfen.rRoh[n-1].left));
Log.d("roh", "right " + Float.toString(mOfen.rRoh[n-1].right));
Log.d("roh", "n " + Integer.toString(n));
Log.d("roh", "x+RohX " + Float.toString(x+RohX));
Log.d("roh", "top " + Float.toString(mOfen.rRoh[n-1].top));
Log.d("roh", "bottom " + Float.toString(mOfen.rRoh[n-1].bottom));
Log.d("roh", "n " + Integer.toString(n));
Log.d("roh", "y+RohY " + Float.toString(y+RohY)); */
/* if( mOfen.rRoh[n-1].left < x+RohX && y+RohY > mOfen.rRoh[n-1].top &&
mOfen.rRoh[n-1].right > x+RohX && y+RohY < mOfen.rRoh[n-1].bottom) {
/*if ((mOfen.heat[n-1]) <= 245 && (mOfen.heat[n-1]) > red ) red = mOfen.heat[n-1]; */ if(red<255) red++;
/* Log.d("red", "red" + Integer.toString(red));
Log.d("red", Float.toString(x+mOfen.rRoh[n-1].left));
Log.d("red", Float.toString((mOfen.rRoh[n-1].left)));
}} */
allpixels[h] = Color.rgb(red, green, blue);
}
}
copyArrayIntoBitmap(bmp);
//bmp.setPixels(allpixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
}
public void copyBitmapIntoArray(Bitmap bmp)
{
allpixels = new int[bmp.getWidth()*bmp.getHeight()];
int count = 0;
for(int i=0; i<bmp.getHeight()-1; i++) {
for(int j=0; j<bmp.getWidth()-1; j++) {
allpixels[count] = bmp.getPixel(j, i);
count++;
}
}
}
public void copyArrayIntoBitmap(Bitmap bmp)
{
int count = 0;
for(int i=0; i<bmp.getHeight()-1; i++) {
for(int j=0; j<bmp.getWidth()-1; j++) {
bmp.setPixel(j, i, allpixels[count]);
count++;
}
}
}
So your code and your question have different operations being said. Looks like you are doing a little more than just globally updating all pixels to be a bit more red. I say this because both code in your question, commented and uncommented, have a conditional part in them that determines how much more red to make a pixel. I also assume this is why a simple LightingColorFilter will not work, since you need to choose which pixels are affected.
Some issues I spotted immediately:
I am betting you are running into a lot of I/O issues with regards to all the memory allocation and memory copying in this code. WxH is your number of pixels, obviously. But that is also a fairly large amount of entites to do an operation on. So your calls to getPixel() and setPixel() iteratively are very very slow already and doing this for each pixel is just impractical. You should use bulk getPixels() and setPixels() if you are going to do it this way. Just this alone should speed up a large chunk of your process.
Now if you want a forward compatible performance boost (like one that scales better with better hardware), you could look into RenderScript This allows you to do work on a per pixel level, but across multiple CPU's and GPU's. It's sort of like a map-reduce framework for your image buffers. You will have to write some C, but if you find this component to be used a lot then this will probably help out quite a bit and be pretty snappy (especially for larger images).
Try to use LightingColorFilter, some examples are here:
LightingColorFilter example or how to use the LightingColorFilter to make the image form dark to light
I am working to convert my CCScrollLayer.cpp code into more of a CCPicker code. In CCScrollLayer, I've defined a baselayer (CCColorLayer) to hold all of the menu objects. I also have a border that holds the ScrollLayer (using glScissor) called "overlay" that I want to be completely static.
In Objective C:
...
self.baseLayer = [CCLayerColor layerWithColor:(ccColor4B){150,150,150,0} width:s.width height:imgSize.height * numPages];
for (int i=0; i < [arrayPages count]; i++) {
CCNode* n = arrayPages[i];
n.position = ccp(s.width/2, s.height/2 + i * (imgSize.height + padding));
[baselayer addChild:n];
}
baseLayer.position = ccp(-s.width/2, -s.height/2 - s.height * currentPage);
[self addChild:baselayer];
...
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint n = [self convertTouchToNodeSpace:touch];
baselayer.position = ccp(touchStartedbaseLayerPosition.x, touchStartedbaseLayerPosition.y + n.y - touchStartedPoint.y);
}
In C++
...
overlay=new CCSprite();
overlay->initWithFile("overlay.png");
overlay->setPosition(ccp(300,300));
overlay->autorelease();
CCLayerColor* baselayer = new CCLayerColor();
baselayer->initWithColor(ccc4(255, 255, 255,255));
baselayer->setOpacity(255);
baselayer->setContentSize(CCSizeMake(s.width/10, (layers->count()*scrollWidth)));
baselayer->setPosition(s.width*.41,300);
baselayer->autorelease();
// Loop through the array and add the screens
unsigned int i;
for (i=0; i<layers->count(); i++)
{
CCLayer* l = static_cast<CCLayer*>(layers->objectAtIndex(i));
l->setAnchorPoint(ccp(0,0));
l->setPosition(ccp(s.width/40,(i*scrollWidth)));
baselayer->addChild(l);
}
this->addChild(baselayer,1);
this->addChild(overlay,1);
...
void CCScrollLayer::ccTouchMoved(CCTouch *touch, CCEvent *withEvent)
{
CCPoint touchPoint = touch->getLocation(); // Get the touch position
touchPoint = this->getParent()->convertToNodeSpace(touchPoint);
baselayer->setPosition(ccp(0,(-(currentScreen-1)*scrollWidth)+(touchPoint.y-startSwipe)));
}
I'm not sure what I'm doing wrong, but as soon as I try to start scrolling, I get a fatal error in the touchdispatcher
case CCTOUCHMOVED:
pHandler->getDelegate()->ccTouchMoved(pTouch, pEvent);
I'm guessing I'm missing something simple here. Can you point me in the write direction?
when i draw a lot of lines, the apps takes a long time to finish drawing. My goal is to connecting of the points in a1[] to form a line. Is there is faster way of doing this? please help!
> $ for (int i = 0; i < x.length - 1; i++) {
> _canvas.drawLine(a1[i].x, a1[i].y, a1[i + 1].x, a1[i + 1].y,_paint);}
Use draw lines. Pack the points into a float[] with 2 points for each point in the line then do this:
if (count >= 4) {
if ((count & 2) != 0) {
canvas.drawLines(pointlist, 0, count-2, linePaint);
canvas.drawLines(pointlist, 2, count-2, linePaint);
}
else {
canvas.drawLines(pointlist, 0, count, linePaint);
canvas.drawLines(pointlist, 2, count - 4, linePaint);
}
}
Where count is the number usable length in the float[] of points. Drawlines goes by 4 floats per segment, but if you stagger them like that you get the result you want without needing to waste 2x the memory and you can effectively move the points if need be.
Use Canvas.drawLines(float[] pts, Paint paint);
Using Canvas.drawLines instead of Canvas.drawLine i have halved the time of drawing.
I have to draw 12 lines with 5000 points for line and the time of drawing with this code is 2393 milliseconds instead of 6000 milliseconds using Canvas.drawLine() method.
int lineIndex = 0;
float[] lines = new float[a1.length * 4];
for (int i = 0; i < a1.length-1; i++) // -1 to deal with last point
{
lines[lineIndex++] = a1[i].x;
lines[lineIndex++] = a1[i].y;
lines[lineIndex++] = a1[i + 1].x
lines[lineIndex++] = a1[i + 1].y;
}
_canvas.drawLines(lines, _paint);
Try creating a Path first, then calling _canvas.drawPath():
Path p = new Path();
p.moveTo(a1[0].x, a1[0].y);
for (int i = 1; i < x.length; i++) {
p.lineTo(a1[i].x, a1[i].y);
}
_canvas.drawPath(p, _paint);