LibGDX textures rendering black - libgdx

I know that there are many questions related to this, but none are relevant to my problem.
So, I have a TiledMap which has 2 layers for boxes in my game - one for the box graphics and one for the box objects. Now, I want to get the textures of all the boxes because I want to be able to draw them anywhere freely. So I wrote some code to find out which tiles a given rectangle (attained from the object layer of the boxes) is covering (this code works fine). Then, from the graphics layer (TileMapTileLayer), I am accessing the textures in those tiles and drawing them to a single texture using Pixmaps. Finally, I store this texture. However, when I render these textures, they are black. Heres the code -
TiledMapTileLayer boxLayer = (TiledMapTileLayer) (map.getLayers().get(2)); // this is the graphics layer
ArrayList<Vector2> cells;
Texture tex;
Pixmap pmap, pmapScld;
int numCols, numRows, cellNum;
int boxInd = 0;
FileTextureData texData;
StaticTiledMapTile tile;
for(RectangleMapObject boxBody : map.getLayers().get(3).getObjects().getByType(RectangleMapObject.class)) { //object layer
bounds = boxBody.getRectangle();
cells = getOccupiedCells(bounds);
numCols = (int) cells.get(0).x; //I have stored the width and height of the texture
numRows = (int) cells.get(0).y; //in tiles in the first Vector2 of the Array
tex = new Texture(numCols * tileWidthOrg, numRows * tileHeightOrg, Format.RGBA8888);
cellNum = 1;
System.out.println(cells);
for(int i = 0 ; i < numCols ; i++) {
for(int j = 0 ; j < numRows ; j++) {
tile = (StaticTiledMapTile) (boxLayer.getCell((int) cells.get(cellNum).x, (int) cells.get(cellNum).y).getTile());
texData = (FileTextureData) tile.getTextureRegion().getTexture().getTextureData();
texData.prepare();
pmap = texData.consumePixmap();
//pmapScld = new Pixmap(tileWidthScld, tileHeightScld, pmap.getFormat());
//pmapScld.drawPixmap(pmap, 0, pmap.getHeight(), pmap.getWidth(), pmap.getHeight(),
//0, pmapScld.getHeight(), pmapScld.getWidth(), pmapScld.getHeight());
tex.draw(pmap, i * tileWidthOrg, j * tileHeightOrg);
pmap.dispose();
texData.disposePixmap();
//pmapScld.dispose();
cellNum++;
}
}
contactListener.addBox(new GBox(world, tex, bounds, boxInd));
tex.dispose();
boxInd++;
}
The code for rendering these boxes -
for(GBox box : contactListener.boxes) {
box.render(sb);
}
public void render(SpriteBatch sb) {
sb.draw(tex, body.getPosition().x - width / 2, body.getPosition().y - height / 2, width, height);
//System.out.println("rendering box " + index + " at position " + body.getPosition());
}

Related

Spliting a PolygonSprite in two gives wrong rotation + offset?

I'm trying to achieve a split effect similar to Fruit Ninja, but the object has to be cut where the user swipes. I followed this tutorial and got the split working on box2d bodies, but I can't get the sprites to split correctly. So what I want is for the body to have a sprite, and the sprite to split the same way the body does, I'm using PolygonSprite and the sprites split in the correct shapes and move at the same time with the bodies, but there's an offset in the image and also it seems that every time I make a cut it will just cut the original texture with no rotation. Here's what I get:
Before I make a cut:
After the first cut (notice that the small triangle is not the top right corner of the original image, and also the image is not centered correctly):
And after I cut the small triangle (notice how it rotated back and didn't cut the actual image):
Here is the method in which I split the object:
private void createSlice(Array<Vector2> vertices, int numVertices, Body affectedBody) {
Vector2 center = findCentroid(vertices, vertices.size);
for (int i = 0; i < numVertices; i++) {
vertices.get(i).sub(center);
}
BodyDef sliceBody = new BodyDef();
sliceBody.position.set(center.x, center.y);
sliceBody.type = BodyDef.BodyType.DynamicBody;
PolygonShape slicePoly = new PolygonShape();
float[] verticesArray = new float[vertices.size * 2];
int j = 0;
for (int i = 0; i < verticesArray.length; i+=2) {
verticesArray[i] = vertices.get(j).x;
verticesArray[i+1] = vertices.get(j++).y;
}
slicePoly.set(verticesArray);
FixtureDef sliceFixture = new FixtureDef();
sliceFixture.shape = slicePoly;
sliceFixture.density = 1;
Body worldSlice = mWorld.createBody(sliceBody);
worldSlice.createFixture(sliceFixture);
for (int i = 0; i < numVertices; i++) {
vertices.get(i).add(center);
}
// create polygon sprite
float[] scaledVertices = new float[verticesArray.length];
for (int i = 0; i < verticesArray.length; i++) {
scaledVertices[i] = verticesArray[i] * Constants.BOX_TO_WORLD;
}
short[] triangles = mTriangulator.computeTriangles(scaledVertices).toArray();
TextureRegion bodyPolyTexReg = ((PolygonSprite) affectedBody.getUserData()).getRegion().getRegion();
PolygonRegion polyReg = new PolygonRegion(bodyPolyTexReg, scaledVertices, triangles);
PolygonSprite polySprite = new PolygonSprite(polyReg);
polySprite.setOrigin(0, 0);
// set the sprite as the body's user data
worldSlice.setUserData(polySprite);
}
My guess is that I would have to rotate the vertices to 0 degrees, make the cut, and then rotate them back, but I'm not sure how to do this.
Thanks!

How to place multiple bitmaps in a scrollable rectangle? AS3

This code builds a palette of tiles for use in a map maker program. It takes in an array set by its parent and uses the bitmaps(from the objects) in that array to display a grid of tiles. Right now it only does a 5x5 grid, but what if there are more than 25 tiles in my tileSet? I want to display only the 5x5 tile grid, but be able to scroll through the images. I imagine that I need to make another rectangle to use as its mask and use a ScrollBar to make it scrollRect, but I can't get this working. Please Help.
public function Palette(X:uint, Y:uint, tileSet:Array)
{
addChild(handleGraphics);
var palette:Rectangle = new Rectangle(X, Y, 5*32, tileSet.length*32); //Default size is 5x5 tiles.
handleGraphics.DrawGrid(32,palette.x,palette.y,5,5);
var counter:int = 0;
for(var i:int = 0; i < 5; i++)
{
paletteArray[i] = [];
for(var u:int = 0; u < 5; u++)
{
if(counter >= tileSet.length)
{
counter = 0; //Which frame to show?
}
var b:Bitmap = new Bitmap(tileSet[counter].Graphic);
b.x = (palette.x) + 32 * u; //Align with palette Rectangle.
b.y = (palette.y) + 32 * i; ///////////////////////////////
addChild(b);
var tileObj:Object = new Object();
tileObj.Name = tileSet[counter].Name;
tileObj.Frame = tileSet[counter].Frame;
tileObj.Graphic = tileSet[counter].Graphic;
paletteArray[i].push(tileObj);
setChildIndex(b, 0); //Under grid.
counter++;
}
}
ActivatePaletteListeners();
}
This code works great for a tileSet array that has less than 25 objects. It loops and shows them continuously until it hits 25. I could do without this I guess, but it is a neat affect.
In another class (HandleTiles) I cycle through my tileSet MovieClip and use each frame to create a new object for each tile.
public function GetPaletteTiles(MC:MovieClip)
{
if (tileArray != null)
{
tileArray.length = 0;
}
for(var i:int = 1; i <= MC.totalFrames; i++)
{
MC.gotoAndStop(i); //Change frame for new info.
var tileObj:Object = new Object(); //The object to push to an array of tiles.
var graphicData:BitmapData = new BitmapData(32,32);
graphicData.draw(MC); //Graphic data from sampleTS.
tileObj.Name = MC.currentFrameLabel;
tileObj.Frame = MC.currentFrame;
tileObj.Graphic = graphicData;
tileArray.push(tileObj);
}
BuildIndexArray(15, 20); //Default size 15 x 20.
}
And here I set the tileSet to use
private function ChangeActiveTileset(Mc:MovieClip)
{
activeTileset = Mc;
GetPaletteTiles(activeTileset);
UpdatePalette();
}
I can change the tileSet with a comboBox. That's why I tear down the tileArray every time I call GetPaletteTiles(). Each tileSet is a different MovieClip, like Buildings, Samples, InTheCity, etc.
Sorry I didn't have time to get this code together earlier. Here's tiling code pieces. Because you're using rectangle and you have to stay under max dimensions you have to move the source mc. I think you already know everything else in there.
// set the bmp dimensions to device screensize to prevent exceeding device's max bmp dimensions
if (bStagePortrait) {
iTileWidth = Capabilities.screenResolutionX;
iTileHeight = Capabilities.screenResolutionY;
} else {
iTileWidth = Capabilities.screenResolutionY;
iTileHeight = Capabilities.screenResolutionX;
}
// mcList.mcListVector is the source mc - a regular mc containing mcs, jpgs, dynamic text, vector shapes, etc.
// mcList.mcListBmp is an empty mc
aListTiles = new Array();
iNumberOfTiles = Math.ceil(mcList.height / iTileHeight);
for (i = 0; i < iNumberOfTiles; i++) {
var bmpTile: Bitmap;
// move the source mc
mcList.mcListVector.y = -(i * iTileHeight);
bmpTile = fDrawTile(mcList, 0, 0, iTileWidth, iTileHeight);
mcList.mcListBmp.addChild(bmpTile);
bmpTile.x = 0;
bmpTile.y = (i * iTileHeight);
aListTiles.push(bmpTile);
}
// remove the regular mc
mcList.mcListVector.removeChild(mcList.mcListVector.mcPic);
mcList.mcListVector.mcPic = null;
mcList.removeChild(mcList.mcListVector);
mcList.mcListVector = null;
}
function fDrawTile(pClip: MovieClip, pX: int, pY: int, pWidth: int, pHeight: int): Bitmap {
trace("fDrawTile: " + pX + "," + pY + " " + pWidth + "," + pHeight);
var rectTemp: Rectangle = new Rectangle(pX, pY, pWidth, pHeight);
var bdClip: BitmapData = new BitmapData(pWidth, pHeight, true, 0x00000000);
var bdTemp: BitmapData = new BitmapData(pWidth, pHeight, true, 0x00000000);
bdClip.draw(pClip, null, null, null, rectTemp, true);
bdTemp.copyPixels(bdClip, rectTemp, new Point(0, 0));
var bmpReturn: Bitmap = new Bitmap(bdTemp, "auto", true);
return bmpReturn;
}

createJS caching tilemap background does not render

If I don't cache the container of tiles after creating the map, I can see them rendered to the canvas:
function createWorld() {
background = new createjs.Container();
for (var y = 0; y < mapWidth; y++) {
for (var x = 0; x < mapHeight; x++) {
var tile = new createjs.Bitmap('images/tile.png');
tile.x = x * 28;
tile.y = y * 30;
background.addChild(tile);
}
}
//background.cache(0, 0, mapWidth, mapHeight);
stage.addChild(background);
}
If I do cache the background container of tile children, it won't render
function createWorld() {
background = new createjs.Container();
for (var y = 0; y < mapWidth; y++) {
for (var x = 0; x < mapHeight; x++) {
var tile = new createjs.Bitmap('images/tile.png');
tile.x = x * 28;
tile.y = y * 30;
background.addChild(tile);
}
}
background.cache(0, 0, mapWidth, mapHeight);
stage.addChild(background);
}
Why?
This is probably because that even when preloaded, images may not be available synchronously if you use a path to create them. If you aren't caching them, then they wouldn't show up immediately when the stage is updated -- but if you ticked the stage, they might appear to load instantly (they just take a frame or so).
I recommend you preload them, either internally, or using something like PreloadJS. Then pass the loaded instance to the bitmaps instead.
var img = document.createElement("img");
img.onload = draw;
img.src = "images/tile.png";
function draw() {
// loop
var bmp = new createjs.Bitmap(img); // Use a reference instead of a path
}
Note that this also reduces overhead, since only one image is created, and all the Bitmaps share a reference to it.
If all your tiles are the same, you might want to look at the Graphics.beginBitmapFill() method. http://www.createjs.com/Docs/EaselJS/classes/Graphics.html#method_beginBitmapFill

Application crashes when I try to display multiple images with a for loop

I am trying to display multiple random grass tile images across the 1200 pixel width window. I am using a method called placeGrass which takes an image, an x coordinate, a y coordinate, and then displays the object at that given coordinate. This works correctly if I use my method getRandomGrass() (which returns a random grass tile image) and type in each coordinate by hand. However, when I try and use a method I made called printGrass(), the flash application fails to boot up.
Here is my attempt at the printGrass() method.
public function printGrass():void
{
var grass:Grass = new Grass(play);
for(var i:int = 0; i < 1200; i + 64)
{
grass.placeGrass(grass.getRandomGrass(), i, 800);
}
}
Where as my manual attempts below work correctly.
var test:Grass = new Grass(play);
test.placeGrass(test.getRandomGrass(), 0, 800);
var test2:Grass = new Grass(play);
test2.placeGrass(test2.getRandomGrass(), 64, 800);
I believe the for statement is never terminated because the counter does not increment the i variable.
for(var i:int = 0; i < 1200; i + 64)
should read
for(var i:int = 0; i < 1200; i += 64)
i + 64 will just return 64 each time where i += 64 will increment i each time.
I hope this helps.

DFT with EMGU/OpenCV - I'm doing something wrong

I'm trying to run DFT in 4x4 blocks over this image (look closely, it's small) It may be a bit too small to see, but it's a 4x12 pixel image. The first 4x4 square is a checkerboard pattern with each square having one pixel, the second 4x4 square is the same pattern with each square having two pixels, and the last 4x4 square is a black square.
The problem I have is that the frequency components I get are not what I expect at all. For example, for the first square I expect to have a DC component in the matrix, but it's not there. I figure I must be doing something wrong but I'm new to EMGU so I'm not sure what. Below is my code.
using (Image<Bgr, byte> image = new Image<Bgr, byte>(Openfile.FileName))
using (Image<Gray, float> gray = image.Convert<Gray, float>())
{
int numRectanglesPerRow = image.Width / WIDTH;
int numRectanglesPerColumn = image.Height / HEIGHT;
for (int i = 0; i < numRectanglesPerColumn; i++)
{
for (int j = 0; j < numRectanglesPerRow; j++)
{
Rectangle rectangle = new Rectangle(WIDTH * j, HEIGHT * i, WIDTH, HEIGHT);
Image<Gray, float> subImage = gray.Copy(rectangle);
Matrix<float> dft = new Matrix<float>(subImage.Rows, subImage.Cols, 2);
CvInvoke.cvDFT(subImage, dft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, -1);
//The Real part of the Fourier Transform
Matrix<float> outReal = new Matrix<float>(subImage.Size);
//The imaginary part of the Fourier Transform
Matrix<float> outIm = new Matrix<float>(subImage.Size);
CvInvoke.cvSplit(dft, outReal, outIm, IntPtr.Zero, IntPtr.Zero);
}
}
}