I'm pretty new to libGDX and java in general so I've been following a plethora of tutorials. so FEEL FREE TO CORRECT ME AT EVERY TURN! (yes even in code inefficiencies as well!!)
I currently have the issue of rotating all of the sprites of a single type instead of just a single sprite.
I'll show you how I mean:
libGDX sprite rotation issue
Here are the specifics:
There are 3 different size of sprites.
I use a hashmap to store the 3 sprites so I don't have to Sprite sprite = new Sprite(); every time (supposedly it's a heavy task)
I create a sprite by referencing the one from the hashmap(I think?)
PROBLEM: When I tell a specific sprite to rotate, it rotates each other
sprite of its size.
I have a suspicion that I'm rotating the hashmap reference... If that's the right way to say it.
This is the process I've been using:
hashpmap:
final HashMap<String, Sprite> spriteMap = new HashMap<String, Sprite>();
texture atlas:
spriteAtlas = new TextureAtlas("sprites.txt");
fill hashmap with regions from texture atlas:
private void init spriteMap() {
Array<AtlasRegion> regions = spriteAtlas.getRegions();
for (int i = 0; i < regions.size; i++) {
AtlasRegion region = regions.get(i);
Sprite sprite = spriteAtlas.createSprite(region.name);
float width = sprite.getWidth() / SCALE;
float height = sprite.getHeight() / SCALE;
sprite.setSize(width, height);
sprite.setOrigin(0, 0);
sprite.scale(1f);
spriteMap.put(region.name, sprite);
}
}
create sprite "instance" from hashmap:
private void createNewSprite() {
Sprite sprite;
sprite = spriteMap.get(name);
sprite.setPosition(x, y);
sprite.rotate(rotation);
spriteArray.add(sprite);
}
Maybe I'm not actually extrapolating the sprite from the hashmap well enough?
Let me know if you need anything else to figure out this conundrum.
Thank you so much!
You have only created a single sprite for each region name, referencing it multiple times in spriteArray. Create a new one each time:
private void createNewSprite() {
Sprite sprite = new Sprite(spriteMap.get(name)); //creates a new sprite that is a copy of the one in your map.
sprite.setPosition(x, y);
sprite.rotate(rotation);
spriteArray.add(sprite);
}
They are only slightly heavy. Each Sprite instance has an array of 20 floats for the vertex data, which contains redundant UV data for the underlying TextureRegion, and a redundant Color object and Rectangle object. So it is heavier than creating your own class that references all these things without the redundancies.
They are too heavy to be creating and destroying many of them during game play without using pooling.
What would really be heavy is loading new Textures to create your Sprites instead of them all sharing a single Texture instance.
In my opinion Libgdx Sprites are generally not good for game design because they conflate state with drawing too much, aside from the redundancies. They are useful for particles (and maybe UI elements) where the conflation is not really a design issue. In fact, I think these are the only two places Sprites are used internally in Libgdx.
Related
In my game (created using LibGDX) I have a gameworld filled with a lot of circles changing their size continiously. Because there are so many circles I want to maximize their rendering-performance: I've heard of the ShapeRenderer, but it seems like that it is not the best in case of performance. The PixMap is also no solution because my circles should be vector-based.
Is their another faster solution too? And is the ShapeRenderer really that slow?
PS: I'm already using chunks to reduce the render time.
For the ShapeRenderer (circle in particular), if we look at the method, radius does not effect performance, segments is where the work is. And this is most likely what is hurting you, as you scale up in size, you increase the segments for detail.
I am not sure about there being opengl native vector graphics either... I think ultimately to reach the graphics card, you need to eventually become vertices and polygons (if you are filling). So actually, I think the Pixmap solution is the one you might be looking for. You compute the segments and the polygons to draw once (at the highest resolution you need).
With the Pixmap you should be able to do this in a way which is as performant as any other rendering of a Texture which you change sizes using the scaling variables (which should be as performant as not changing the scale). As you can see from the circle draw method that the ShapeRenderer uses, the circle is still really just describing a polygon (you are just computing its geometry every time).
If you want to give the Pixmap option a go, here is some code to get you bootstrapped.
Here is a kotlin function for building a PolygonSprite. You will have to do the maths for plotting the vertices of your circle, but you can probably use the circle draw method to get an idea for that. If you compute your geometry for a radius of 1, then you can just use your x/y scale to set the radius at whatever size you want.
fun polygonSprite(points: Array<Vector2>): PolygonSprite {
val pix = Pixmap(1, 1, Pixmap.Format.RGBA8888)
pix.setColor(0xFFFFFFFF.toInt())
pix.fill()
val textureSolid = Texture(pix)
val vertices = FloatArray(points.size * 2)
val triangleIndices = triangulator.computeTriangles(vertices)
for (i in 0..points.size - 1) {
val point = points.get(i)
val offset = i * 2
vertices[offset] = point.x
vertices[offset + 1] = point.y
}
val polyReg = PolygonRegion(TextureRegion(textureSolid),
vertices, triangleIndices.toArray())
val poly = PolygonSprite(polyReg)
return poly
}
And here is some rendering code. It takes into account relative positioning of the shape from the parent Body and some other stuff:
fun render(camera: OrthographicCamera) {
val parentRotation = (me().physicsRoot.rotationR() * MathUtils.radDeg)
val parentTransform = me().physicsRoot.transform
val myPosition = vec2(offsetX, offsetY)
parentTransform.mul(myPosition)
poly.color = color.get()
poly.setOrigin(0f, 0f)
poly.setPosition(myPosition.x, myPosition.y)
poly.rotation = parentRotation + rotationD
poly.setScale(scaleX, scaleY)
poly.draw(JJ.B.renderWorld.polyBatch)
recycle(myPosition)
}
Also, don't make a new one of these for every one, try and reuse them.
PS: Another option is to make a circle shader :D
I want to add motion to two sprite objects in single game screen. I mean two sprite object should move(or follow some predefined path) independently in single page or game screen of app using Libgdx. How can I achieve that.
Please help me. If possible please provide some reference code also. Thank you.
you can use scene2d for this purpose.where you can easily move object through actions.
you can follow these links to learn scene2d.
http://www.gamefromscratch.com/post/2013/11/27/LibGDX-Tutorial-9-Scene2D-Part-1.aspx
http://www.gamefromscratch.com/post/2013/12/09/LibGDX-Tutorial-9-Scene2D-Part-2-Actions.aspx
i hope these links will help you.
You can do this:
take two 2DVector objects:
private Vector2 positiononesprite,positiontwosprite;
Sprite sprite_one,sprite_two;
then in your create method do this
positiononesprite = new Vector2(0,0);
positiontwosprite = new Vector2(0,0);
//set your sprite position
sprite_one.setPosition(x,y);//your x and y coordinates
sprite_two.setPosition(x1,y1);//your second sprite postions
positiononesprite.x = sprite_one.getX();
positiononesprite.y = sprite_one.getY();
positiontwosprite.x = sprite_two.getX();
positiontwosprite.y = sprite_two.getY();
/*
then to make them move in a custom direction you can use either
setPosition method or translate method*/
//apply your algorithm on vectors and set or translate your sprites
// in render method define there speed, direction and move them
//for example i did this to move it in a particular direction
pointerposition.x += directionpointer.x * speed;
pointerposition.y += directionpointer.y * speed;
// pointer.setPosition(pointerposition.x, pointerposition.y);
ball.setPosition(pointerposition.x, pointerposition.y);
this is moving my ball in a particular direction
here directionpointer is a direction vector and speed is a float variable and pointerposition is a vector2 object as i declared positiononesprite
I would like to know if anybody can help me with a better method of drawing a Tile map for my android game.
Currently, I use a for loop to draw the required Bitmaps to the screen but when doing this for the amount of tiles I need to render at once (enough to cover the screen and a bit more), when the map scrolls, you can notice the map become jolty with its movement, because of the for loop having to loop through all the tiles. The tiles are drawn simular to this:
for(int i = 0; i < 170; i++) {
canvas.drawBitmap(bitmap, x + i * bitmap.getWidth(), y, null);
}
The method I am currently using uses a few bitmaps to save memory, and draws them in different locations.
A different method i can think of to draw the map would be to create a larger Bitmap from the tiles and move the position of that larger bitmap to create movement. The problem with this is that is does require lots of memory and gets out of memory errors.
So, i need to try and find out a method of drawing multiple tiles preferably without the use of a for-loop (I believe the for-loop is causing the jolty, un-smooth movement of the map).
For more details just ask, thanks.
The for loop is the correct way to draw it, your problem is probably the amount of data you are trying to draw in one frame and/or the number of pixels you are trying to push through the system.
If you want good performance on Android your best bet will be to use the graphics hardware it provides. There are various game frameworks available that will make that easier for you and give you much better performance than you will get otherwise.
If not then you will need to break up the drawing and still run the same effective logic but spread out so you draw a few tiles per frame.
is it really required to draw ALL tiles at once?
if it is possible for you, maybe you can determine the 'visible view port' and then just draw those tiles, which need to be drawn?!?
int width = getWidth()/Tiles.width; // do it once before any rendering
// thats the amount of tiles per line
int height = getHeight()/Tiles.height; // do it once before any rendering
// thats the amount of tiles per row
Point pos = ...; // you should know the position of your 'figure' within the map
// could as well be the scroll position
//now draw only those tile from the 'viewport':
for (int dy = 0; dy < width; dy++){
for (int dx = 0; dy < height; dy++){
int xOnMap = pos.x + x;
int yOnMap = pos.y + dy;
int index = yOnMap*height+yOnMap; //index in list
canvas.drawBitmap(bitmap,
x * bitmap.getWidth(), y * bitMap.getHeight(), null);
}
}
so you just have to draw some tile and that would always be the same amount...
i must confess i wrote that code onstackoverflow so there is a chance i did a syntax terror ^^
Situation: I have a canvas on an Android game, I have some objects (I will keep it as simple as possible):World(where are storaged all Laser and Block objects), Block and Laser. I can draw all this objects in the canvas.
I would like to 'hide' them behind a black 'background', and then draw a blurry 'transparent' circle, so all objects are hidden behind the black background, except the objects behing the circle.
I have thought about it, but I can't think of an approach to do this.
Images:
This is my actual situation:
This is the expected:
Do something like this:
public void drawBitmapsInCanvas(Canvas c){
c.drawBitmap(block, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawBitmap(block2, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawBitmap(laser, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
c.drawColor(Color.BLACK);//this hides everything under your black background.
c.drawBitmap(circle, new Rect(/*coordinates here*/), new Rect(/*More coordinates*/),null);
}
If you want transparency:
Paint paint =new Paint();
paint.setARGB(120,0,0,0); //for the "120" parameter, 0 is completely transparent, 255 is completely opaque.
paint.setAntiAlias(true);
c.drawBitmap(bmp,Rect r,Rect rr, paint);
or if you are trying to change the opacity of individual pixels, the approach is a bit more complicated (I have not tested the code, but you get the gist of it):
public static final Bitmap getNewBitmap(Bitmap bmp, int circleCenterX,
int circleCenterY,int circleRadius){
//CIRCLE COORDINATES ARE THE DISTANCE IN RESPECT OF (0,0) of the bitmap
//, not (0,0) of the canvas itself. The circleRadius is the circle's radius.
Bitmap temp=bmp.copy(Bitmap.Config.ARGB_8888, true);
int[]pixels = new int[temp.getWidth()*temp.getHeight()];
temp.getPixels(pixels,0 ,temp.getWidth(),0,0,temp.getWidth(), temp.getHeight());
int counter=0;
for(int i=0;i<pixels.length;i++){
int alpha=Color.alpha(pixels[i]);
if(alpha!=0&&!((Math.pow(counter/temp.getWidth()-circleCenterY,2.0)+
Math.pow(counter%temp.getWidth()-circleCenterX,2.0))<Math.pow(circleRadius,2.0))){
//if the pixel itself is not completely transparent and the pixel is NOT within range of the circle,
//set the Alpha value of the pixel to 0.
pixels[i]=Color.argb(0,Color.red(pixels[i]),Color.green(pixels[i]),Color.blue(pixels[i]));
}
counter++;
}
temp.setPixels(pixels,0, temp.getWidth(),0,0,temp.getWidth(),temp.getHeight());
return temp;
}
and then draw temp.
I'm not completely sure what you are trying to ask, so you may have to modify as necessary.
If you try the second answer of qwertyuiop5040, you will get a ver low - perfomance when you try to apply it to a large image. Let's say a 1000*800 pixels image. Then you will have a loop:
for (int i = 0 ; i < 1000*800; i++)
You could create an image that's a black rectangle with a transparent hole in it. The hole would be the circle that you can see through, and the image would be rendered over the spot you want to be visible. Then, you can draw four black rectangles around the image to cover the rest of the screen.
I have a question about speed and efficiency whilst coding a game. I would like to know what the best way would be to have lots of enemies on screen at once. Do I use a single sprite, move it and draw it for every enemy? Or do I have an instance of a Sprite for each Enemy (of which there could be 50 on screen at once). I am wondering about the speed impact of having lots of instances of Sprite (and in turn, Texture). Which of the above would be best for efficiency and overall good practice?
Id recommend having an instance of a Sprite for every Monster. All sprites have the same reference to a single texture, so it's easier to have lots of sprites without moving a single texture around.
Here is a example of my code;
public ArrayList<Monster> createMonsters(int count, int maxlevel,
int minlevel, MonsterTypes type) {
ArrayList<Monster> monsters = new ArrayList<Monster>();
// just one texture but multiple sprites
// save memory :)
Texture monster = getTextureByType(type);
for (int i = 0; i < count; i++) {
// create random level inside the area
int level = (int) ((Math.random() * maxlevel) + minlevel);
// create a default monster
Monster mon = new Monster(level, new Sprite(monster), screen,
new RandomAI());
monsters.add(mon);
}
return monsters;
}
private Texture getTextureByType(MonsterTypes typ) {
return this.screen.game.manager.get("monster/" + typ.getFileName()
+ ".png");
}
As you can see it gives every monster a new instance of a sprite with the same texture. All of the sprites refer to the same texture to save memory. Hope this helps.