Creating an image from a sprite sheet using the original images file name - lua

Creating sprite sheets aka texture atlases rather than using many hundres of individual images is recommended everywhere. I have hundreds of images for a word learning game; but there are hundreds of words, no animation sequences. So having generated the data file and sprite sheet, i am looking for an example of how to create an image when needed from the original image file name (as stored in the sprite sheet data (lua code) file (both created with texture packer).
This much seems right:
local sprite = require("sprite")
local CN_70_tiles_corona = require("CN_70_tiles_corona")
local spriteDataCN = CN_70_tiles_corona.getSpriteSheetData()
local spriteSheet = sprite.newSpriteSheetFromData( "CN_70_tiles_corona.png", spriteDataCN )
before creating the sprite sheet, would create my image with something like this:
t1 = display.newImage(cnTiles[tileNO])
where cnTiles[1], for examples, is a value placed in an array from a sqlite table such as "sit_word100.png".
there is now an entry in my generate lua file below the 'getSpritSheetData' function something like this:
{
name = "sit_word100.png",
spriteColorRect = { x = 0, y = 0, width = 69, height = 69 },
textureRect = { x = 2, y = 2, width = 69, height = 69 },
spriteSourceSize = { width = 69, height = 69 },
spriteTrimmed = false,
textureRotated = false
},
i can see that ALL my image file names are now stored in the data to provide a way to refer to my image within the sprite sheet, but since i do NOT want to use "sprite sets", i can't find an example of just getting the one image when in eed it.
I want something that allows me to refer to my now spritesheet-ified image using the original image name. is this possible? e.g.
t1 = display.newImage(CN_70_tiles_corona.getSpriteSheetData(name = "sit_word100.png")

The easy way is to create sheets with TexturePacker and use SpriteGrabber to take the sprites your need.
It's an awesome add-on to Corona-SDK which can be found here:
http://developer.anscamobile.com/code/spritegrabber-spritesheets-two-lines

Related

Unable to create a working sprite

I am unable to create a working animation sprite for this single area of my app.
I am using Corona SDK and have the following sprite:
This is names mainCharacter.png. I have a double sized version called mainCharacter#2x.png.
I have sheet options, 2 sequences, I'm building an image sheet and passing that to my sprite:
local playerSheetOptions =
{
width = 50,
height = 50,
numFrames = 17,
sheetContentWidth = 500,
sheetContentHeight = 100
}
local playerSequences = {
{
name = "idle",
start = 1,
count = 12,
time = 1200,
loopCount = 0,
loopDirection = "bounce"
},
{
name = "jump",
start = 13,
count = 5,
time = 600,
loopCount = 1
},
}
local playerSheet = graphics.newImageSheet( "resource/images/mainCharacter.png", playerSheetOptions )
local player = display.newSprite(gameSheet, playerSheet, playerSequences)
I am getting the following error:
display.newSprite() requires argument #2 to a table containing sequence data
If I print the relevant data:
print(gameSheet)
print(playerSheet)
print(playerSequences)
I get:
14:27:05.703 userdata: 12445228
14:27:05.703 userdata: 0CF42600
14:27:05.703 table: 0CF41FD0
Where am I going wrong? I have tried simplifying the sequences a lot, but still get the same thing.
Use
local player = display.newSprite(playerSheet, playerSequences)
instead of
local player = display.newSprite(gameSheet, playerSheet, playerSequences)
From Corona documentation
Once the image sheet(s) and sequences are set up, a new sprite object
can be created with the display.newSprite() API:
display.newSprite( [parent,] imageSheet, sequenceData )
For this API, the parent
parameter is optional and represents the display group in which to
insert the sprite. The imageSheet parameter defines the default image
sheet for the sprite, and sequenceData is the table that contains all
of the sequences for the sprite.
Read more about Sprite Animation.

Getting data from a table

Using Tiled I generated a Lua file which contains a table. So I figured that I'd write a for loop which cycles through the table gets the tile id and checks if collision is true and add collision if it was. But, I've been unable to get the tile id's or check they're properties. But it returned a error saying that I tried to index nil value tileData.
Here is the Map file
return {
version = "1.1",
luaversion = "5.1",
-- more misc. data
tilesets = {
{
name = "Tileset1",
firstgid = 1,
tilewidth = 16,
tileheight = 16,
tiles = {
{
id = 0,
properties = {
["Collision"] = false
}
},
}
}
layers = {
{
type = "tilelayer",
name = "Tile Layer 1"
data = {
-- array of tile id's
}
}
}
}
And here is the for loop I wrote to cycle through the table
require("Protyping")
local map = love.filesystem.load("Protyping.lua")()
local tileset1 = map.tilesets
local tileData = tileset1.tiles
local colision_layer = map.layers[1].data
for y=1,16 do
for x=1,16 do
if tileData[colision_layer[x*y]].properties["Colision"] == true then
world:add("collider "..x*y,x*map.tilewidth, y*tileheight,tilewidth,tileheight)
end
end
end
Try this:
tileset1 = map.tilesets[1]
instead of
tileset1 = map.tilesets
lhf's answer (map.tilesets[1] instead of map.tilesets) fixes the error you were getting, but there are at least two other things you'll need to fix for your code to work.
The first is consistent spelling: you have a Collision property in your map data and a Colision check in your code.
The second thing you'll need to fix is the way that the individual tiles are being referenced. Tiled's layer data is made of 2-dimensional tile data laid out in a 1-dimensional array from left-to-right, starting at the top, so the index numbers look like this:
You would think you could just do x * y to get the index, but if you look closely, you'll see that this doesn't work. Instead, you have to do x + (y - 1) * width.
Or if you use zero-based x and y, it looks like this:
Personally, I prefer 0-based x and y (but as I get more comfortable with Lua, that may change, as Lua has 1-based arrays). If you do go with 0-based x and y, then the formula is x + 1 + y * width.
I happen to have just written a tutorial this morning that goes over the Tiled format and has some helper functions that do exactly this (using the 0-based formula). You may find it helpful: https://github.com/prust/sti-pg-example.
The tutorial uses Simple Tiled Implementation, which is a very nice library for working with Tiled lua files. Since you're trying to do collision, I should mention that STI has a plugins for both the bump collision library and the box2d (physics) collision library.

Creating layers named after slices

I have an issue that may well not be possible to solve 'out of the box'. I'm running fireworks 8 and would like to to be able to run the:
Commands->Document->Split to layers
and have the resulting layers created using the name of the slice that it created the layer for. So for example, if I have 3 slices in my png, called 'Head', Shoulder' and 'Arm', I'd like that command to create the layer name that corresponds to the slice name. As it currently stands, when running this command, the default layer names created are sequentially named 'Layer 1', 'Layer 2', 'Layer 3' etc etc.
The reason for this requirement is due to the fact that I then wish to use the Export command to save the individual Layers out to named png files that use the 'Slice names ('Head.png' etc), rather than the default Layer names. Now I know I can manually rename the layers to match the Slices, and Export to a folder as required. However, in my real life scenario, I have over 50 Slices per document that require this treatment and I have 100's of documents at a time to 'batch' process. So my idea was that I would be able to run a command (or create some sort of macro) that would allow me to create the layers with the same name as the slice that they contained.
This would make my life SOO much simpler as I could then totally automate the process based on a set of source images located within a folder structure, rather than opening each file, running the above command, renaming each layer manually (error prone of course) and then running the Export function.
Can anyone offer advice on finding a solution to this?? I hope I'm not the only one to have come across this requirement.
I've added a line to the Split to Layers command here. If you save that as Distribute to Named Layers.jsf in the same folder as the original command (in CS5.5 I found it in Configuration/Commands/Document), I think that should do what you need.
That said, jsf is fairly unpredictable in my experience (for example, that command seems to miss the default name of things like Rectangles until they've been renamed), so I'm not certain if it will work 100% of the time. Also, the script skips over the Web Layer which contains slices in 5.5 - I can't remember if the set up is different in 8. Hopefully that gets you some of the way there though.
FYI - here's what the final programatic fix amounted to (with thanks to david mear)
// This command will take multiple objects and move them to indivdual layers
// and then prompt for a folder location to save the layers as named-layer.png
// files. This is ultra useful if you want to save slices out to individual
// files and wish to have total control over the resulting file names
var curDoc = fw.getDocumentDOM();
// Save the current frame in the document
var curFrameNum = curDoc.currentFrameNum;
// get the total layers minus the web layer
var numLayers = curDoc.layers.length - 1; // skip the web layer.
var curLayerNum;
// default to d:\ for now
var locFolder = fw.browseForFolderURL("select a folder", "file:///d|/");
// 23/3/2013 add dialog box for file
if (locFolder !== null) {
// loop through the current number of layers
for (curLayerNum = numLayers - 1; curLayerNum >= 0; curLayerNum--) {
// get the current layer
var curLayer = curDoc.layers[curLayerNum];
// get the elements on the current layer
var elements = curLayer.frames[curFrameNum].elements;
//if layer is locked cannot distribute so continue to next layer.
if (curLayer.frames[curFrameNum].locked == true)
continue;
// get the number of elements
var numElements = elements.length - 1;
var i;
// loop through the number of elements
for (i = 0; i < numElements; i++) {
// get the current layer number
if (i == 0) curDoc.currentLayerNum = curLayerNum;
// add layers for the number of elements
curDoc.addNewLayer(null, false);
}
// again loop through the number of elements
for (i = 0; i < numElements; i++) {
// set the current layer
curLayer = curDoc.layers[curLayerNum];
// get the elements on the current layer
elements = curLayer.frames[curFrameNum].elements;
// select none
curDoc.selectNone();
// create a new array that will hold the selection
var sel = new Array();
// populate the array
sel[0] = elements[elements.length - 2];
// EDIT - 25/3/2013 rename target layer if element has a name
curDoc.setLayerName(curLayerNum + i + 1, sel[0].name || "");
// select all of the elements of the array in Fireworks
fw.selection = sel;
// move the selection to its new layer
curDoc.moveSelectionToLayer(curLayerNum + i + 1, false, "none", -1);
}
}
// EDIT - 25/3/2013 set to png32 export option
set_export_as_png_32(curDoc);
fw.exportLayers(curDoc, locFolder);
}
function set_export_as_png_32(targetDoc) {
targetDoc.setExportOptions(
{
animAutoCrop: true,
animAutoDifference: true,
applyScale: false,
colorMode: "32 bit",
crop: false,
cropBottom: 0,
cropLeft: 0,
cropRight: 0,
cropTop: 0,
ditherMode: "none",
ditherPercent: 100,
exportFormat: "PNG",
frameInfo: [],
interlacedGIF: false,
jpegQuality: 80,
jpegSelPreserveButtons: false,
jpegSelPreserveText: true,
jpegSelQuality: 90,
jpegSelQualityEnabled: false,
jpegSmoothness: 0,
jpegSubsampling: 0,
localAdaptive: true,
lossyGifAmount: 0,
macCreator: "",
macFileType: "",
name: "PNG32",
numCustomEntries: 0,
numEntriesRequested: 0,
numGridEntries: 6,
optimized: true,
paletteEntries: null,
paletteInfo: null,
paletteMode: "adaptive",
paletteTransparency: "none",
percentScale: 100,
progressiveJPEG: false,
savedAnimationRepeat: 0,
sorting: "none",
useScale: true,
webSnapAdaptive: false,
webSnapTolerance: 14,
xSize: 0,
ySize: 0
}
);
}

Sprite position in Corona SDK

I didn't understand some object position concepts in Corona SDK
I have created sprite sheet:
local spriteSheet = sprite.newSpriteSheet("button.png", 138, 64);
local spriteSet = sprite.newSpriteSet(spriteSheet, 1, 2);
local sp = sprite.newSprite( spriteSet );
and it's positions are strange and sprite is out of screen bounds even I set x and y positions to zero
config.lua is:
application =
{
content =
{
width = 320,
height = 480,
scale = "letterbox"
},
}
I think that problem in "referencePoint"
just say me how to change setReferencePoint of default screen (not image or group ...), just default screen...
Technically you can use a different coordinate system for all your graphics by creating a display group and attach everything to that group, but really it seems like you're asking the wrong question. Rather than trying to change the reference point of the screen, you should be wondering why your sprites aren't positioned correctly.
Please create a new question that focuses on that problem and explains it further, because all you say here is that the positions are "strange". What's that mean?
You can modify your code like below and just check it,it will work:
local spriteSheet = sprite.newSpriteSheetFromData( "button.png",require("button").getSpriteSheetData())
local spriteSet = sprite.newSpriteSet(spriteSheet,1,9);
sprite.add(spriteset,"button",1,9,1000,0);
//button is lua file use button.lua
local sp = sprite.newSprite( spriteSet );
sp:prepare("button");
sp.x = display.screenOriginX+138;
sp.y = display.screenOriginY+64;

how I can place an image just in one cell using npoi

I'm using npoi to generate excel docs. I have a requirement to add images to cells. Using the following code i can insert images into my doc. However the image span many cells. How can i ensure that the image just fits inside once cell.
public ActionResult NPOICreate()
{
try
{
FileStream fs = new FileStream(Server.MapPath(#"\Content\NPOITemplate.xls"), FileMode.Open, FileAccess.ReadWrite);
HSSFWorkbook templateWorkbook = new HSSFWorkbook(fs, true);
var sheet = templateWorkbook.GetSheet("Sheet1");
var patriarch = sheet.CreateDrawingPatriarch();
HSSFClientAnchor anchor;
anchor = new HSSFClientAnchor(0, 0, 0, 0, (short)4, 2, (short)6, 5);
anchor.AnchorType = 2;
var picture = patriarch.CreatePicture(anchor, LoadImage(#"D:\dev\Website/HumpbackWhale.jpg", templateWorkbook));
picture.Resize();
picture.LineStyle = HSSFPicture.LINESTYLE_DASHDOTGEL;
sheet.ForceFormulaRecalculation = true;
MemoryStream ms = new MemoryStream();
templateWorkbook.Write(ms);
TempData["Message"] = "Excel report created successfully!";
return File(ms.ToArray(), "application/vnd.ms-excel", "NPOINewFile.xls");
}
catch (Exception ex)
{
TempData["Message"] = "Oops! Something went wrong.";
return RedirectToAction("NPOI");
}
}
To the best of my knowledge, it isn't possible to assign an image object to a particular cell within Excel.
This is not a limitation of POI/NPOI, but rather the way Excel works: Pictures inserted into a spreadsheet just float (over the spreadsheet grid per se)...
At best one can make believe it is in the cell by ensuring that the size and position of the cell and of the picture match perfectly. There is a property of the picture (See "Format Picture" dialog, Properties section, also accessible through POI I'm sure) which allows to specify whether the picture will move and/or resize itself following actions on rows/cells surrounding it, but in the end, pictures remain a floating object very loosely related to a cell at best.
A common trick to assign a picture to a cell is by way of comments. The picture is then more formally bound to the cell but it is not shown as content but rather a comment data.
See for example this recipe. The idea is to use the background of the comment to be a color with a special fill effect which is the picture we wish to associate with the cell. Here again, there's got to be a way of achieving this programmatically with NPOI, but I cannot affirm this firsthand.
here's something you can try:
You see that property, anchor.AnchorType = 2;? try setting that to 0 or 3 and see what it does. In the C# (NPOI) port, 0 will fit the image in just one cell with option 0.
Here's some example code (used in a C# Asp.net project, just in case someone wanders here that needs it):
HSSFWorkbook hssfworkbook = new HSSFWorkbook();
HSSFSheet sheet1 = hssfworkbook.CreateSheet(sheetName);
//map the path to the img folder
string imagesPath = System.IO.Path.Combine(Server.MapPath("~"), "img");
//grab the image file
imagesPath = System.IO.Path.Combine(imagesPath, "image.png");
//create an image from the path
System.Drawing.Image image = System.Drawing.Image.FromFile(imagesPath);
MemoryStream ms = new MemoryStream();
//pull the memory stream from the image (I need this for the byte array later)
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
//the drawing patriarch will hold the anchor and the master information
HSSFPatriarch patriarch = sheet1.CreateDrawingPatriarch();
//store the coordinates of which cell and where in the cell the image goes
HSSFClientAnchor anchor = new HSSFClientAnchor(20, 0, 40, 20, 3, 10, 4, 11);
//types are 0, 2, and 3. 0 resizes within the cell, 2 doesn't
anchor.AnchorType = 2;
//add the byte array and encode it for the excel file
int index = hssfworkbook.AddPicture(ms.ToArray(), HSSFPicture.PICTURE_TYPE_PNG);
HSSFPicture signaturePicture = patriarch.CreatePicture(anchor, index);
It's possible by three steps.
First, you should insert the picture
Second, add the ClientAnchor to the file to locate the picture to some cells
Third, resize the picture using tricky way otherwise it's hard to make a picture inside a cell

Resources