LibGDX - Efficient way to use tiles & Z-Order of Sprites - libgdx

I have a problem. The sprites I'm rendering aren't in the Z position I want them to be.
The game I'm making is a 2D sandbox game - similar to terraria.
I make a 2-dimensional array and then iterate through it with a for-loop.
Basic code outline:
for(int x = 0; x < worldwidth; x ++){
for(int y = 0; y < worldheight; y ++){
//complicated calculations to check which texture it should use
// draws background blocks
Sprite s = new Sprite(texture);
s.setSize(12, 12);
s.setOriginCenter();
s.rotate(rotation);
s.setPosition(x* world.blocksize, y* world.blocksize);
s.draw(batch);
//draws foreground blocks
//same thing as with background blocks, only with a different texture
}
}
I want the player to be between the background and foreground sprites. But if I draw it at the start or the end of the loop, it ends up at the very back or very front.
I tried drawing it after the background tiles, but that didn't work. What do I do? Do I use something instead of a spritebatch for rendering the player?
Okay, second question: Is drawing tiles this way efficient? Am I doing it right, or should I use something like a tilemap?

Related

create multiple textures with rotation of original texture and save them in a list

Not sure if I am on the right way.
I have a smal texture which I draw multiple times (1000). But I like to have them with different rotations (around 10) for that texture. So I thought to rotate the textures and save the in a list (10) for the reuse (performance).
When my approach is good, how can I rotate an original texture and store it to a new texture (in memory during start) ?
You can use Sprite class that wraps a Texture and provides many useful methods to work with it. For example: scaling, rotating.
So you will have one Texture instance and 10 sprites.
Texture texture = new Texture("path.png");
for (int i = 0; i < 10; i++) {
Sprite sprite = new Sprite(texture);
sprite.setSize(..);
sprite.setRotation(..);
someList.add(sprite);
}
And then you can just select which sprite you want set it's position and draw it:
sprite.draw(spriteBatch);

AS3 cacheAsBitmap confusion

My goal was to have low resolution circles (very pixelated). I know there are other ways to do this, but I'm trying to understand how cacheAsBitmap works. When I use a sprite sheet that I have drawn very very small, and then scale the bitmap up, it looks great (very blocky, pixelated, smoothing turned off). Fine. But when I draw a circle programatically very small (say radius of 4), and then cache it, and then scale it up, it is pixelated, but very much a full, round circle. I take it that somehow the player isn't actually caching it as a bitmap until it is rendered on the screen. Even when I don't do the scale up until the swf is fully loaded and running, I still just get big circles that are perfectly round (but pixelated). Is there a way to cache something programatically that will then scale up the way my imported bitmaps do?
the code I tried looks basically like this:
for (var i: int = 0; i < 200; i++) {
var size: Number = 8;
var item: RunnerMassObj = new RunnerMassObj();
item.graphics.lineStyle(0,0x0,0,true);
item.graphics.beginFill(0xFF8844 + i * 10);
if (i < 10) {
item.graphics.drawCircle(0, 0,size);
} else {
item.graphics.drawRect(0, 0, size, size);
}
item.graphics.endFill();
addChild(item);
item.x = Math.random() * 1000 + 50;
item.y = Math.random() * 1000;
item._bottom.y = size;
// here I cache it as a bitmap.
item.cacheAsBitmap = true;
allMassObj.push(item);
}
and then in my engineTick code I have this:
for(var i:int = 0; i < allMassObj.length; i++)
{
// and here I scale it up, expecting the pixels to stay pixelated.
// has the circle somehow maintained its vector shape?
allMassObj[i].scaleX = 10;
allMassObj[i].scaleY = 10;
}
and instead of the big pixels on the left, I get the tiny "true to screen" pixels on the right:
Any insights will be much appreciated!
If you convert your item into a BitmapData then you could disable smooth:
item = new BitmapData(instance.width * scale, instance.height * scale, true, 0x0);
item.draw(instance, m, null, null, null, false); // final false disables smoothing
(Do not tryied but I think it's worth to have a look)
Best.
Edit: additionally: try to investigate something near color depth of your bitmap. As you know, if you can convert your bitmap to 1 or 2 bit colors, then resizing it, probably you will get a hard pixelated image as you wish.
But when I draw a circle programatically very small (say radius of 4), and then cache it, and then scale it up, it is pixelated, but very much a full, round circle.
The thing is that it's just cached as a bitmap. It doesn't behave like one. The documentation is pretty clear on this one:
After you set the cacheAsBitmap property to true, the rendering does not change
The point of cacheAsBitmap is to improve rendering performance for complex vector data that doesn't change:
If set to true, Flash runtimes cache an internal bitmap representation of the display object. This caching can increase performance for display objects that contain complex vector content.
It basically "bakes" the vector geometry into pixels behind the scenes, so that it doesn't have to do the calculations to display it again and again.
When the DisplayObject is transformed, the cache is updated. That's why you never see a pixelated version of your circle.

Ball Motion Effect libgdx

How can i add a motion effect on a ball as shown in image.
Please help.
Thanks in advance.
If the ball is the only moving element the easiest way to achieve this is to clear screen with a semi-transparent color:
Gdx.gl.glClearColor(0, 0, 0, 0.5f);
If not you can implement a queue that will keep your ball's last positions and will render a ball there with descending transparency. In pseudo code it could be something like
//render() method
for(int i = 0; i < queue.size(); i++)
transparency = i * 1/queue.size();
draw(ball, queue.get(i), transparency);
draw(ball, currentBallPosition)
queue.put(currentBallPosition)
if(queue.size() > 20) //we want to keep last 20 positions
queue.removeLast()
Another nice idea is to use Particle Effects although it will not always do the thing (like when your ball can change color or shape)

implementing mask functionality using BitmapData

I have two BitmapData objects with transparency enabled. One is a large red square, the other is a small blue circle.
If, for example, I position the blue circle over the red square. I would like to create an area of transparency in the red square's BitmapData where the blur circle is. Similar to how a mask works.
I have tried using getPixel32() operations but it is very slow (see below). Is there another way I can do this? Thanks
for(var x:int = 0; x < circleBitmapData.width; x++){
for(var y:int = 0; y < circleBitmapData.width; y++){
if(circleBitmapData.getPixel32(x,y) != 0x00000000){
squareBitmapData.setPixel(x,y,0x00000000);
}
}
}
EDIT - I have one possible solution, but it's not ideal. I can merge the two bitmaps, then use the threshold method to turn pixels above a certain value to transparent. So I could set all blue pixels to transparent. However, I get a thin ring of blue around the transparent area
Check out bitmapData's threshold method. It should return you a bitmapData with the intersected area. With that, you don't have to get and set pixel anymore. Also, getPixel32 should have setPixel32 :P

Speeding up a canvas image crop

I'm working on a simple image crop where the user draws a line with the mouse around an area that they want to keep. When they confirm, the rest of the image will be cropped out. Here's how I'm currently handling said cropping:
var data = c.getImageData(0,0,canvas.width,canvas.height);
for (var x = 0; x < data.width; x++) {
for (var y = 0; y < data.height; y++) {
if (!c.isPointInPath(x,y)) {
var n = x + (data.width * y);
var index = n*4;
data.data[index+3] = 0;
}
}
}
However, this can bog down really quickly. The less of the image you try to retain, the faster it goes, but even saving 30% of the image (canvas is 800x800) causes it to hang for several seconds. Is there a faster way to go about this?
I don't really understand why you are diving into pixel details to manipulate your cropping image functionality. It's understandable as bigger the image is get as more time is needed for cropping out the rest of the image, because practically with iterating over a two dimensional array of pixels the processing time needed for the operation is exponentially increasing with the increasing in size of the pixels map.
So my suggestion would be to try to remake the function without to even touch the getImageData and putImageData function. It's useless. I would make in the following way:
Obtain the pixel coordinates at the mouse down.
Create an event listener for the mouse move.
Create a semi-transparent image over the original image and use the fillRect function to draw into the created canvas.
Create an event listener for mouse up.
Obtain the pixel coordinates at the mouse up.
Calculate the coordinates of the resulting square.
Draw the resulting image into the canvas using as parameters the square coordinates.
As a final step draw the content of the canvas to an image.
This way you will save a lot of overhead on image cropping processing.
Here is a script for your reference: https://github.com/codepo8/canvascropper/blob/master/canvascrop.js
There is no real way to speed it up when you have to use a user defined shape, but the bogging down can be handled with a worker.
Some ideas:
Restrict getImageData to the bounding box of the polygon the user draws.
Put data.height, data.width etc. used inside the loop in a variable.
Maybe you can split up inside/outside tests and setting the imagedata alpha value.
Maybe even draw the polygon to a black and white imagedata object, then get the difference between the two?
Can you share the isPointInPath(x,y) function?