libGdx array<TextureRegion> fails to assign to Sprite - java

After a long search on StackOverflow and Google I decided to write a question myself as I did not find a solution for my problem. I am learning libgdx from a 'learning LibGdx game development' book. I confirmed that my code is exactly the same as the code provided in the book. Everything runs fine until it reaches this part:
Sprite spr = new Sprite(regions.random());
Region.randoms() is an Array<TextureRegion>. It works fine if I add direct instance of an asset from a Asset class but crashes if I want to add a random asset from Array<TextureRegion>. Why?
private void initTestObj () {
// creates new array for 5 sprite's
testSprites = new Sprite[5];
// Create a list of texture regions
Array<TextureRegion> regions = new Array<TextureRegion>();
regions.add(Assets.instance.bunny.head);
regions.add(Assets.instance.ballon.ballon);
regions.add(Assets.instance.spider.spider);
System.out.println("xxxxxxxxxxxxxxxxx test before Sprite xxxxxxxxxxxxxxxxxxxxx");
System.out.println(regions.size);
//create new sprite's using a random texture region
for( int i = 0; i < testSprites.length ; i++) {
Sprite spr = new Sprite(regions.random()); //<<<< Main problem
System.out.println(".....................test after sprite...............");
//define sprite size to be 1x1 in game world
spr.setSize(1 , 1);
//set origin to sprite's center
spr.setOrigin(spr.getWidth() / 2.0f, spr.getHeight() / 2.0f);
//calculate random position for sprite
float randomX = MathUtils.random(-2.0f, 2.0f);
float randomY = MathUtils.random(-2.0f, 2.0f);
spr.setPosition(randomX, randomY);
// put new sprite into array
testSprites[i] = spr;
}
//set first sprite as selected one
selectedSprite = 0;

I got it working eventually there was nothing wrong with texture region array there was problem with assets, apparently you cant name them like item_1 because after packing texture packer discards the _1 a the end and you left with just item.

Related

Texture Stretching when using a FrameBuffer and SpriteBatch

I have been working on this for 2 days and still cant figure out what is going on. I am working on a Game Framework and i have migrated from Slick2D to LibGDX and would like to render once to a texture as to save CPU/GPU cycles and improve performance. I have created a class called DrawSurface and its main goal is to allow me to draw to a offscreen texture and then just draw that using LibGDXs Built in Image class.
public final class DrawSurface {
public static interface DrawCall{
void draw(SpriteBatch b, int width, int height);
}
public static Texture offscreenDraw(DrawCall c, int canvasWidth, int canvasHeight){
FrameBuffer fbo = new FrameBuffer(Pixmap.Format.RGBA8888,(canvasWidth),(canvasHeight),true);
SpriteBatch batch = new SpriteBatch();
batch.setProjectionMatrix(new Matrix4().setToOrtho2D(0,0,fbo.getWidth(),fbo.getHeight()));
fbo.begin();
batch.begin();
c.draw(batch,fbo.getWidth(),fbo.getHeight());
batch.end();
Pixmap map = ScreenUtils.getFrameBufferPixmap(0,0,fbo.getWidth(),fbo.getHeight());
fbo.end();
Texture t = new Texture(map);
map.dispose();
return t;
}
}
Which Gives me This Result When Drawing Images:
The "DrawCall" that is used to get this image is:
Texture t = DrawSurface.offscreenDraw(new DrawSurface.DrawCall() {
#Override
public void draw(SpriteBatch b, int w, int h) {
Image img = new Image(0x0000FF,w,h);
img.setLocation(0,0);
img.draw(b);
for(int i = 0; i < w; i += 64){
for(int j = 0; j < h; j += 64){
Blocks.GRASS_BLOCK.setLocation(i,j);
Blocks.GRASS_BLOCK.draw(b);
}
}
}
},512,512);
The Image should Render as a blue Square 512x512 pixels in size, with small "Grass" block images that should also be square. Sized 16x16. Unfortunately i get a warped result, and i do not understand why. As the Large White thing (a software JoyStick i created) is not stretched while the "DrawsSurface" is. If you would like a look at my camera code:
// Constructor Above.
this.gameWidth = gameWidth;
this.gameHeight = gameHeight;
this.camera = new OrthographicCamera();
FlatPixelGame.gameCamera = this.camera;
this.viewport = new StretchViewport(gameWidth,gameHeight,camera);
this.viewport.apply();
LogBot.log("Game Instance Created Size [%s,%s]",gameWidth,gameHeight);
InputManager.getInstance().addListener(this);
this.camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
Any Help Would Be Appreciated, i have scoured Forums, StackOverflow and LibGDX Documentation and still cannot seem to fix this issue.
Again, Thank you in Advance :)
After a little work under the hood with LibGDX source code from BadLogic, as well as reading bug threads it seems there is an issue when converting a PixMap to a texture. Rendering a image derived from a file works fine, but generated images that come from a Pixmap can show warping due to the off-screen view-port not being the same as the current rendering view-port.
A quick way around this is using TextureRegions and Sprites.
public static Image offscreenDraw(DrawCall c, int canvasWidth, int canvasHeight){
FrameBuffer fbo = new FrameBuffer(Pixmap.Format.RGBA8888,canvasWidth,canvasHeight,true);
SpriteBatch batch = new SpriteBatch();
Matrix4 matrix = new Matrix4();
matrix.setToOrtho2D(0, 0, canvasWidth,canvasHeight);
batch.setProjectionMatrix(matrix);
fbo.begin();
batch.begin();
c.draw(batch,canvasWidth,canvasHeight);
batch.end();
Texture t = fbo.getColorBufferTexture();
t.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
if(!t.getTextureData().isPrepared()){
t.getTextureData().prepare();
}
fbo.end();
TextureRegion r = new TextureRegion(t,0,0,canvasWidth,canvasHeight);
return new Image(new com.badlogic.gdx.scenes.scene2d.ui.Image(new Sprite(r)));
}

LibGdx collision detection between sprites?

Using accelerometer my sprite image is moving left and right and if I touch my screen the sprite is moving to Y-axis.I want to make a collision detection between different sprites so that if the sprite pass through an object it will stop to hide in that object. I already watch a tutorial this https://www.youtube.com/watch?v=T1aN--vTqLc but nothings happen. What is the proper way to make collition detection? I don't know what's wrong with my coding.Any suggestion or much better tutorial Thank's and Advance
Here is my coding
private Rectangle rectangleCat;
private Rectangle rectangleShoes;
private float yPosition = -40;
Sprite
cat = new Texture(Gdx.files.internal("cat.png"));
catsprite = new Sprite(cat);
catX=300;
catY=0;
sprite_shoes = new Sprite(new Texture("equip/Shoes.png"));
sprite_shoes.setPosition(260,580);
rectangleShoes=new Rectangle(sprite_shoes.getX(),sprite_shoes.getY(),sprite_shoes.getWidth(),sprite_shoes.getHeight());
rectangleCat = new Rectangle(catsprite.getX(),catsprite.getY(),catsprite.getWidth(),catsprite.getHeight());
Render method
boolean isOverlaping = rectangleCat.overlaps(rectangleShoes);
if(!isOverlaping) {
System.out.println("not overlap");
yPosition = yPosition + (20 * delta);
}
My Sprite image and Object is not overlapping
Full source code http://pastebin.com/Dxfx9f65
First of all your sprite is not sharp Rectangle it's looks like polygon so you need to detect collision between two polygon.
Still if you want to detect collision between rectangle then get Bounding Rectangle of your sprite in render() method.
In render method
rectangleShoes=sprite_shoes.getBoundingRectangle();
rectangleCat=catsprite.getBoundingRectangle();
boolean isOverlaping = rectangleCat.overlaps(rectangleShoes);
if(!isOverlaping) {
System.out.println("not overlap");
yPosition = yPosition + (20 * delta);
}

libgdx - ui SpriteBatch needs to scale based on window size?

I am currently using libgdx 1.5.4. Normally to modify screen size, I have done this:
public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
int temp = 3; //scale viewport
config.width = temp *160;
config.height = temp *144;
new LwjglApplication(new MyGame(), config);
}
}
The temp var above will scale the desktop application window size by some number (3 in this case). In my render() loop, I have a batch (floatingBatch = new SpriteBatch();) that isn't modified by a camera, to draw my 'ui' elements:
floatingBatch.begin();
//bunch of floatingBatch.draw()'s...
floatingBatch.end();
I have noticed, though, that the coordinates in floatingBatch don't scale with my screen size. For example, the point (200,200) in floating batch will be offscreen if temp above = 1, but will be onscreen if temp = 3. This isn't right, I want floatingBatch to scale with the window. If I start with temp = 1, and just manually drag the window out to about 3x it's starting size, everything is as I want obviously.
One thing that I have tried is have the temp = 1 above, and then do this in my create() function:
Gdx.graphics.setDisplayMode(160*3, 144*3, false);
The above is fine, and works, but it looks a little awkward visually (the screen first starts out as 144x160, then resizes to 3x that size.) Is there a better way to do what I am describing? Can I change floatingBatch somehow so that it scales with the window?
You can use
Gdx.graphics.getWidth();
and
Gdx.graphics.getHeight();
to obtain the pixel count of the device then adjust your scene2d
Refer to the api for more help

Multiple instances of a Texture in LibGDX?

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.

Android Java. Strange behaviour with invalidate(Rect)

I am getting astrange effect with invalidate(Rect).
I use an onDraw method on a canvas. In the simplest case, I have a background and a sprite.
On the first pass through onDraw, I draw the background and use invalidate(Rect) (a rect which covers the whole playfield) and in the same pass, I draw a sprite and (because the code is the same for all passes) I do an invalidate(Rect) for the Rect the sprite was in.
After the first pass, the playfield is correct. The whole background is in place, with the sprite superimposed.
On the next and subsequent passes through onDraw, I draw the "dirty" bit of the background the sprite was on, and do an invalidate(Rect) on that, together with the sprite and its new "dirty" rectangle, and another invalidate(Rect) for the sprite.
After this pass and all subsequent passes, I only see the sprite. It's as though the canvas had been cleared.
Is it not allowed to do multiple invalidate(Rect)s in one pass? Is this the problem? Have I come up against some problem with asynchronicity?
Here is the onDraw() code. It works fine, but slowly, if I do a full screen invalidate() at the end of onDraw() instead.
It's also scaling all the images. All the images and screen positions are based on a 640x480 playfield,
and scaled to the size of the current android device. All that works fine until I try to optimise the screen
drawing by using invalidate(Rect).
#Override
protected void onDraw(Canvas canvas)
{
int ii;
// Draw the background scene
// Restore all the bits of the backcloth that got
// trampled on by any sprites or the cursor
// On the first pass the whole playfield dirty rectangle is in place in mask
paint.reset();
mask.collapse();
ArrayList <Rect> usedSet = mask.getUsedRectSet();
for (ii = 0; ii < usedSet.size(); ii++)
{
Rect src = rescaleRect(usedSet.get(ii));
Rect dst = displaceRect(src);
canvas.drawBitmap(backcloth, src, dst, paint);
invalidate(dst);
}
// Leave used Rect set clear for next set of sprites
mask.ClearUsedRectSet();
//
// draw Sprites
// screen scaling and
// displacement is done here.
//
ArrayList <Sprite> slist = jadedata.getCurrentSprites();
//Sort sprites into ascending order of priority
// This is a sinking sort. On first pass, the highest
// priority sprite arrives at the bottom. On second,
// the next highest arrives at second bottom, etc.
// Sprites of the same priority remain in their
// original sequence with respect to each other.
for (ii = 0; ii< slist.size()-1; ii++)
{
int sw=0;
for (int jj = 0; jj < (slist.size()-ii-1); jj++)
{
Sprite spare1 = slist.get(jj);
Sprite spare2 = slist.get(jj+1);
if (spare1.getPriority() > spare2.getPriority())
{
slist.set(jj+1, spare1);
slist.set(jj, spare2);
sw=1;
}
}
if (sw==0) break; // exit if slist is already in sequence
}
for (ii = 0; ii< slist.size(); ii++)
{
Point p = new Point();
Point e = new Point();
Rect o = new Rect();
Sprite sprite = (Sprite)slist.get(ii);
// Zero-priority sprites do not get drawn
if (sprite.getPriority() == 0) continue;
p = sprite.getPosition();
e = sprite.getExtent();
// make a rect for usedRects
Rect r = new Rect(0, 0, e.x-1, e.y-1);
Rect src = new Rect(r);
// move it to the model playfield position
r.offset(p.x-e.x/2, p.y-e.y/2);
// make an overlap rect so we can apply it to the source image
o = overlapRect(r, 0, 0, iWidth, iHeight);
// trim r for the used rectangles
r = trimRect(r, 0, 0, iWidth, iHeight);
// add it to used Rectangles
mask.addNewRect(r);
// draw the sprite image
Rect d = rescaleRect(usedSet.get(ii));
Rect dst = displaceRect(d);
Bitmap spriteim = sprite.getCurrentImage();
src.top += o.top;
src.left += o.left;
src.bottom -= o.bottom;
src.right -= o.right;
canvas.drawBitmap(spriteim, src, dst, paint);
invalidate(dst);
}
not sure what you are doing since you didn't provide code , so i will just give a general tip:
for the passes after the first pass , use the invalidate only on the rectangle that is dirty , and in the onDraw method , draw everything that needs to be drawn , but only inside the dirty rectangle.

Categories