I have an app I am working on that loads data from the server and displays objects on the stage for each record. I have created a library object (with several dynamic text fields) in Flash and exported it as a SWC. When I loop through the data and add a new SWC object for each record, the performance drops completely. There are about 800 records, all with text and background color to set the SWC object color and text fields. Here is some code...
var playerMag:PlayerMag;
for (var i:int=0;i<boardData.Players.length;i++) {
playerMag = new PlayerMag();
playerMag.width = 110;
playerMag.height = 48;
playerMag.fname.text = boardData.Players[i].fname;
playerMag.x = boardData.Players[i].X;
playerMag.y = boardData.Players[i].Y;
addChild(playerMag as MovieClip);
}
When all the playerMag's are on the stage, dragging and scaling by pinch or finger drag is extremely slow.
Any ideas on how to make it faster that I am missing or don't know? Any help is appreciated.
Generally manipulating textfields in mobile is a really bad idea. Your best bet is to populate them, add them to a container, then draw the container into a bitmap and add the bitmap instead of the textfields.
Related
I'm working in Xcode 6 on tiling the iPhone background with many UIImageViews and I'd like to know if this is the most efficient solution.
I know one simple solution would be to create image views in the storyboard and cover the entire screen with them manually. I'd like to do it with code. Here's the code I have currently (5x5 is an okay size since I can scale it up or down to fill the screen with bigger or larger images):
CGRect tiles[5][5];
UIImage *tileImages[5][5];
UIImageView *tileViews[5][5];
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
tiles[i][j] = CGRectMake(50*i,50*j,50,50);
tileImages[i][j] = [UIImage imageNamed:#"tile.png"];
tileViews[i][j] = [[UIImageView alloc] initWithFrame:tiles[i][j]];
tileViews[i][j].image = tileImages[i][j];
[self.view addSubview:tileViews[i][j]];
}
}
Currently all the images are the same, but in the long haul I'm going to make them dependent on various factors.
I have read around and I know that UIImageViews are finicky. Is this the proper and memory efficient way to tile a background with UIImageViews? Is there a better way to do this? Can I manually go in after the tiles are initialized and change an image it's displaying and have it update in real time with just this?
tileView[1][2].image = [UIImage imageNamed:#"anotherTile.png"];
Thanks in advance, I just finished a basic 6-week course in IOS programming at my college so I still find myself trying to appease the Objective C Gods occasionally.
I guess my doubt would be why you need them to be image views. Drawing an image in a view or layer is so easy, and arranging views or layers in a grid is so easy; what are the image views for, when you are not really using or needing any of the power of image views?
I have several apps that display tiled images - one shows 99 bottles in a grid, one shows a grid of tile "pieces" that the user taps in matched pairs to dismiss them, one shows a grid of rectangular puzzle pieces that the user slides to swap them and get them into the right order, and one shows a grid of "cards" that the user taps in triplets to match them - and in none of those cases do I use image views. In one, they are CALayers; in the other cases they are custom UIView subclasses; but in no case do I use UIImageViews.
For something as simple as a grid of images, using UIImageViews seems, as you seem to imply, overkill. If the reason you have resorted to UIImageViews is that you don't know how to make a UIView or a CALayer draw its content, I'd say, stop and learn how to do that before you go any further.
I'm using the dreded AS2 (not by choice) and working with images externally loaded.
I know that
targetClip.forceSmoothing = true;
...exists, but it still doesn't seem to be doing much at all.
The images externally loaded are really big in dimensions and when made smaller in the flash, they pixelate.
Perhaps forceSmoothing is the best method but...
I'm thinking there may be a way to resave the external bitmap resized and use that, instead of resizing a bitmap as a vector.
Any ideas?
Also, I've got an AS3 version of this, so if you know how I can do it in that too, then great. But it seems they do not want to use that yet.
in as2:
add this class to your project BitmapLoader
and use like that:
var loader : BitmapLoader = new BitmapLoader(true);
loader.addListener(this);
loader.loadBitmap("http://foo.tr/example.jpg", this, "doneLoading" );
in as3 :
var loader:Loader = new Loader()
loader.load(new URLRequest("1.jpg"))
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,doneLoad);
function doneLoad(e:Event){
var bitmap:Bitmap = e.target.content as Bitmap
bitmap.smoothing = true
}
How are you loading the image data? If you're doing it with the BitmapData class, you can use a matrix together with the scale() command to shrink it.
http://docs.brajeshwar.com/as2/flash/geom/Matrix.html
http://docs.brajeshwar.com/as2/flash/display/BitmapData.html
I have made a PNG image which will be my button background. In the preload() of my relevant state I load that image. I want a way to have this image placed in the world and be able to set text onto it (and also be clickable but I guess that's a bit unimportant here because I know how to set up event handlers).
I thought I could manage something with
Text text = new Text(x,y,foo,style);
text.texture = <something>
but trying to, for example, create a new Texture() shows a warning "undefined class Texture" in DartEditor, and anyway (as far as I can tell?) Texture doesn't seem to allow giving a source image key/URL..
So could anyone with Phaser experience tell me how I can get an in-game button as I want?
I currently seem to have achieved more or less what I wanted (may have to tweak some values here and there but generally seems alright) with code like this
class MyState
{
preload() {
//...
game.load.image('key','$assetPath/button.png');
//...
}
create() {
Sprite temp2;
temp2 = new Sprite(this.game, x, y, 'button');
BitmapData bmp = game.add.bitmapData(temp2.width, temp2.height);
bmp.draw(temp2);
//Text positioning x,y in fillText() is just my choice of course
bmp.ctx.fillText('Wait', bmp.width / 2, bmp.height / 2);
game.add.sprite(game, someX, someY, bmp);
}
}
EDIT: For what I'm doing there adding the bitmap to game cache wasn't needed; must've been something I was trying when trying to figure it out and forgot to delete.
So I needed to use the BitmapData class. My only little concern with this (although I'm not sure it really is an issue) is how when I create the Sprite temp2 I am giving it a position but of course it is not used in the game, rather the output of drawing the sprite, and then text on top, to bmp is added as a sprite to the game. Does anyone know if there are any real implications of creating that first Sprite and leaving it like so? I'm just wondering because visually it appears it is not an issue since it is not appearing in the "game world".
Also, while this method seems just fine for me at the moment I'm curious as to whether there other ways, like something else that is somehow better and/or more preferred?
First of all, I would like to say that I'm fairly new to AS3, so feel free to correct me when needed.
So I'm trying to create a moving background, made out of different types of isometric tiles, like a floor or a wall, disposen in a grid like fashion.
At first, I tried creating a symbol containing the floor and the wall on different frames, and alternate between the frames as needed. Then I would add multiple instances of this symbol to a container and move the container around. Quickly I realized that this probably wouldn't be an ifficient method, as confirmed by the unsmooth movement of the container. (I gave up on this method).
So I did a little digging around, and then I converted the tile symbol to a png file, created a bitmap container to where I would copyPixels from the png as many times as the map required it.
The problem now is that when I do this:
var pngBitmapData:BitmapData=new tilePng
the bitmapData height and width don't match the height and width of the actual tile. There seem to be some transparent pixels around the tile and I have no idea how to remove them. This causes the tiles to be misaligned on the background's grid, with some small empty spaces around them.
So I have a couple of questions:
Is this an effective way to build the background?
Is there a way to avoid that transparent pixels "problem" ?
Hmm, it's hard to tell without seeing your png.
Are you doing this?
var pngBitmapData:BitmapData = new tilePng();
var bmp:Bitmap = new Bitmap(pngBitmapData);
To initialize your bitmap?
Also, check the anti-aliasing on your bitmap, that could be it. I'd set it to none.
I am using JavaCV for on-the-fly image processing from a webcam. It works great! I can define a region of interest in the picture and crop every image before displaying and it'll still do a full 30 frames per second without problems. Nice!
However, I'm using a CanvasFrame object to display the live image. It works great (and easy), but is TOTALLY USELESS for including in an application. I want to put the live image on a panel (or canvas or whatever) as one element of my application window.
The problem: A CanvasFrame lives in its own frame and disappears behind my window when my window gets focus, and also doesn't move when I move my window.
How can I get the live image onto an element that I can integrate with my normal UI elements?
Again, I need a replacement for CanvasFrame in JavaCV. TIA.
I start a camera thread that grabs in a loop and draws on the CanvasFrame until a UI button is pressed. THIS WORKS FINE.
In response to the UI button press, I stop the thread (which triggers grabber.stop). Then I take the last image, and display that image on a panel. THIS WORKS FINE (I know how to display an image, thanks). I'd be done except CanvasFrame is a separate window which kinda sucks.
So instead I want to start a camera thread that grabs in a loop and does NOT draw on a CanvasFrame. Instead it just keeps an internal copy of the last image. Then to display on my UI, I set a timer (which fires correctly) and just display the latest image on my panel. THIS DOES NOT WORK--the panel remains blank. And yet, how is this case any different from the case that works? The only difference is that the grabber in the camera thread has not been stopped yet. It's fine when the camera is NOT in its grabbing loop, but will NOT display when it is looping. And I'm careful to make cvCopy's of the images I pass to the UI, so there's no problem with contention for the memory.
I will also say that displaying on the CanvasFrame in a loop seems to trigger my Logitech C920 auto-focus, whereas just grabbing a single image and displaying it (which I can do easily as long as the grabber is stopped) does NOT seem to auto-focus.
The upshot is CanvasFrame seems to be doing lots of tricky stuff in the backgraound which cannot be matched by just having grabber.start, grabber.grab, grabber.stop, then display on your own panel.
Sam, I've seen your name in the CanvasFrame source code, so you should know better than anyone what's the difference between my 2 scenarios.
I was looking for a replacement for CanvasFrame that can be used in any UI and now I have one. Here it is, a swing element that can display a live (or still) image:
import java.awt.Graphics;
import java.awt.image.*;
import javax.swing.JPanel;
public class CamImagePanel extends JPanel {
private BufferedImage image;
public CamImagePanel() {
super();
// Note that at this point, image = null
// so be sure to call setImage() before setVisible(true)
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) // Not efficient, but safer.
g.drawImage(image, 0, 0, this);
}
public void setImage(BufferedImage img) {
image = img;
repaint();
}
}
Then, I set a timer in my main event thread to wake up 20 to 30 times per second (30-50 ms) and in the alarm callback method, I simply call mypanel.setImage(latestPhoto); and it's just like a live image.
I have a controller object with it's own thread which fills a buffer with an image from the camera as fast as it can, and I just ask the controller for the latest image. This way, synchronizing isn't required, I can actually ask for the images faster or slower than the camera can make them, and my logic still works fine.
A button on the UI stops the timer and I can leave up the final image on the panel or take the panel down completely with setVisible(false).