AS3 Embed images class and then get these images into another class? - image

For example, right now I have a class called "Balls.as". Here I load 10 different balls-images. You know, like this:
[Embed(source = "/ball1.png")]
[Embed(source = "/ball2.png")]
The problem is that if I spawn 5 balls, these balls images gonna get embeded 5 * 5 times right? Correct me if I'm wrong! So I though, can't I have a ballimageloading class? That loads these images once, and then in Balls.as I can load whatever ball i want for the moment?

You won't need to "load" them, they are embedded. You just have to instantiate the images. It's a good idea to have one class that manage shared ressources, as such:
public class TextureAssets
{
[Embed(source = "../lib/ball1.png")]
private static var Ball1:Class;
[Embed(source = "../lib/ball2.png")]
private static var Ball2:Class;
public static var ball1Texture:BitmapData;
public static var ball2Texture:BitmapData;
public static function init():void
{
ball1Texture = (new Ball1() as Bitmap).bitmapData;
ball2Texture = (new Ball2() as Bitmap).bitmapData;
}
Then you would call TextureAssets.init() once (in the Main.as for example)
and when you need the bitmapData: use new Bitmap(TextureAssets.ball1Texture)
This way your program needs uses only memory required for one bitmapData instead of having many which ends up being the same.
If you need to perform operations on a bitmapData while keeping the original you can use:
var modified:bitmapData = TextureAssets.ballTexture.clone();
Also, if you are instantiating all balls images from within one class it's a good idea to drop static access and instead initialise the bitmapDatas in the constructor, create a new TextureAssets() and call the textures through the variable
(Static field access is slower than direct (.) access : http://jacksondunstan.com/articles/1690)

The best practice is to have an Assets class which will contain static embeded images, like this:
[Embed(source="ball1.png")]
public static var BallImage1:Class;
Then all you'll have to do is declare a variable for your loaded Bitmap and use it, like so:
protected var mBall1:Bitmap = new Assets.BallImage1() as Bitmap;
This will create a Bitmap instance of your loaded image and you can then add it to the display list. Loading will happen only once per image and you'll have all your images at your fingertips, accessible from every class you have.

Related

How can I add "proper" images (not Icons) to my JFrame/JPanel/JComponents (Swing) (Kotlin)

Language: Kotlin,
GUI Library: Swing,
IDE: IntelliJ IDEA
I know that there are similarly phrased questions, but note that I want to add multiple images, not just one, to any type of JComponent that holds other components. For example, I am not concerned with adding an image to a JLabel, I already know how to do that. I want to know how to add an image to a JFrame, JPanel, Container, etc.; all things that hold other Components (and have an add(Component) function). Finally, I don't want that workaround where you add the image to a JLabel with no text and then add that to the container. I would like to just use the Image class or a subset like BufferedImage or URL.
I want to be able to call the add() method from the Container class, jFrame.add(component) for example, where component is some sort of image. I want this to result in an image being displayed on the screen.
The ImageIcon class is not a Component so this can't be input on its own. I think I would have to create some sort of custom Image class that extends from Component or JComponent, but I don't know what I would have to override to get that to display an image on screen when added to another JComponent. There are multiple solutions to this, but to clarify, I don't want some kind of "middle man" where I add a JLabel or JButton or something that only contains an Icon. I don't want to display icons anyway, I want to display full-sized images anywhere on the screen. I will provide a possible example of what I want the final result to look like.
class MyApp() {
fun init() {
var jFrame = JFrame()
jFrame.add(Image("filepath/image.png"))
//Some other JFrame boiler plate
jFrame.isVisible = true
}
}
fun main() {
MyApp().init()
}
The unclear part is the Image class, and whether that's a custom class that inherits JImage, or some already defined class or method I don't know about. I know about ImageIO and BufferedImage and ImageIcon, but none of them directly go into this method, as they don't inherit Component or JComponent.
EDIT:
I tried using Camickr's second solution, but it didn't work. I will post the code to see if a made a simple mistake.
import java.awt.Image as AWTImage
import java.awt.Image.*
//Including these imports as I used name alias so I had to say what it was from.
open class JImage(var point: Point = Point(0, 0), image: AWTImage): JComponent() {
var image: ImageIcon = ImageIcon(image)
override fun paintComponent(g: Graphics?) {
super.paint(g)
g?.drawImage(image.image, point.x.toInt(), point.y.toInt(), null)
}
}
class SplashScreen(image: JImage): Frame() {
init {
//jFrame.isUndecorated = true
jFrame.add(image)
}
}
class MyApp {
fun init() {
var jFrame = SplashScreen(JImage(image = ImageIO.read(Loader().getClassLoader().getResourceAsStream("resources/images/splashscreen/SplashScreen.png"))).getScaledInstance(Size(1000, 1000*3/5)))
jFrame.isVisible = true
}
}
fun main() {
MyApp().init()
}
FINAL EDIT:
Okay, so I did make a simple mistake when trying this solution. I overrode paintComponent() but then inside it, I called super.paint(). Additionally, I realized I didn't have to use the ImageIcon class, which I didn't want to do anyway. This is the Image class I have come up with.
open class JImage(var point: Point = Point(0, 0), var image: AWTImage): JComponent() {
fun getScaledInstance(size: Size, scalingMethods: ScalingMethods = ScalingMethods.DEFAULT): JImage {
val scale: Int = when(scalingMethods) {
ScalingMethods.DEFAULT -> SCALE_DEFAULT
ScalingMethods.FAST -> SCALE_FAST
ScalingMethods.AREA_AVERAGING -> SCALE_AREA_AVERAGING
ScalingMethods.REPLICATE -> SCALE_REPLICATE
ScalingMethods.SMOOTH -> SCALE_SMOOTH
}
return JImage(point, image.getScaledInstance(size.width.toInt(), size.height.toInt(), scale))
}
override fun paintComponent(g: Graphics?) {
super.paintComponent(g)
g?.drawImage(image, point.x.toInt(), point.y.toInt(), null)
}
}
I want to know how to add an image to a JFrame, JPanel, Container, etc.
You don't add an image to a JFrame, JPanel etc. As you said an image is not a component. You add the image to a JLabel and add the label to the panel. This is the easiest and more direct way to display an image at its actual size.
Don't know if Kotlin is any different, but the other option is to do custom painting and paint the image on a JPanel by overriding the paintComponent(…) method and using the Graphics.drawImage(…) method and then add the panel to the frame. Read the Swing tutorial on Custom Painting for painting basics.
You can also check out Background Panel for an example that paints an image as a background of the panel. The image can be:
painted at its real size
scaled to fill the panel
tiled to fill the panel
Just note that the image should NOT be read in the paintComponent() method as painting code should be efficient.

Android Viewpager to load images from SD Card

Guys Im using the following custom code to load 20 images from resources and present in a viewpager
public class CustomPagerAdapter extends PagerAdapter {
int[] mResources = {
R.drawable.slide1,
R.drawable.slide2,
R.drawable.slide3,
R.drawable.slide4,
R.drawable.slide5,
R.drawable.slide6,
R.drawable.slide7,
R.drawable.slide8,
R.drawable.slide9,
R.drawable.slide10,
R.drawable.slide11,
R.drawable.slide12,
R.drawable.slide13,
R.drawable.slide14,
R.drawable.slide15,
R.drawable.slide16,
R.drawable.slide17,
R.drawable.slide18,
R.drawable.slide19,
R.drawable.slide20,
};
Context mContext;
LayoutInflater mLayoutInflater;
public CustomPagerAdapter(Context context) {
mContext = context;
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mResources.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((LinearLayout) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View itemView = mLayoutInflater.inflate(R.layout.pager_item, container, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.imageView);
imageView.setImageResource(mResources[position]);
container.addView(itemView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout) object);
}
}
This works fine but I want to put the jpgs in a directory on the device so that they can be changed without recompiling the app
I think I need to get the images into the mResource array. I can get the path but not sure what format the code should be instead of using the draw-able lines
i have read articles on here but none make sense to me I am really new to this and the code looks nothing like the code I am using
can anyone point me in the right direction?
Any help is greatly appreciated
Mark
Yes, you can certainly do so. I will try to explain you the process step-by-step,
Step 1
Have a File object pointing to the path, like,
File directory = new File("path-to-directory");
Ensure that the path is to the directory with the images,
Step 2
List all the files inside the directory using listFiles() method, like
File[] allImages = directory.listFiles();
Now you have an array of all the files just like int[] mResources. The only difference being, now you have actual file references, while previously you had resource ids.
Step 3
You can just display the images in the ViewPager just like you did previously. But this is a bit tricky and can take you a considerable amount of time and code to get an image properly displayed from File.
You also need to take care of caching, so that when you load a previously loaded image again, it gets it from the cache.
To do all this, I recommend you to use this library (recommended by Google), Glide.
Setting an image is one line of code,
Glide.with(context).from(file).into(imageView);
That's it. Now you have your images displayed in a ViewPager from a directory in the device.

How to cache TextureAtlas results?

When using a TextureAtlas to create a Sprite with the createSprite method, the LibGDX documentation says: This method uses string comparison to find the region and constructs a new sprite, so the result should be cached rather than calling this method multiple times.
How do I cache these results? Is it just a variable I create to store the created sprite? If so then how do I create different copies of the same sprite?
Each time you use the createSprite method, a new Sprite gets created. Usually you'd have one sprite per enemy for example. Let's say that you have a class Frog which is one of your enemies. It should look like this (pseudo-code):
public class Frog {
private Sprite sprite;
public Frog(TextureAtlas atlas) {
sprite = atlas.createSprite("frog");
}
public void update(float deltaTime) {
// update the sprite position
}
public void render(Batch batch) {
sprite.draw(batch);
}
}
Now each Frog would have its own Sprite. This is necessary, since all frogs can be in different places. The position will be configured via the Sprite. You will create the sprite just once in the constructor and all of those sprites share the same TextureRegion of the same TextureAtlas, which will result in a good performance, since there won't be many texture switches on the graphics card, when you render your frogs.

Tools/Guide to Creating an Image Looper in GWT

I'm setting out to create a weather model display tool (web application), and from what I've seen, I'm really liking the idea of using Google Web Tools, and especially the SmartGWT toolkit. My one biggest sticking point at this point is finding some way to create a sort of image "looper" (displaying all images in a particular "set" one after another, not unlike a slide show). For reference, I need functionality (at least on a basic level) similar to this: http://rapidrefresh.noaa.gov/hrrrconus/jsloop.cgi?dsKeys=hrrr:&runTime=2012053007&plotName=cref_sfc&fcstInc=60&numFcsts=16&model=hrrr&ptitle=HRRR%20Model%20Fields%20-%20Experimental&maxFcstLen=15&fcstStrLen=-1&resizePlot=1&domain=full&wjet=1 (though it certainly need not be exactly like that).
Does anyone know of (ideally) some sort of GWT module that can do image looping? Or if not, does it sound like something an intermediate programmer could figure out without too much trouble (I'm willing to accept a challenge), even if I've never explicitly used GWT before? I'm sure I could whip together something that pulls each image in as it goes through a loop, but prefetching them would be even more ideal.
Please comment if you need clarification on anything!
As far as I'm aware there's not a pre-fab solution to do this, although maybe SmartGWT has something I don't know about. In any case, it won't be too hard to roll your own. Here's some code to get you started:
public class ImageLooper extends Composite {
// List of images that we will loop through
private final String[] imageUrls;
// Index of the image currently being displayed
private int currentImage = 0;
// The image element that will be displayed to the user
private final Image image = new Image();
// The Timer provides a means to execute arbitrary
// code after a delay or at regular intervals
private final Timer imageUpdateTimer = new Timer() {
public void run() {
currentImage = (currentImage + 1) % images.length;
image.setUrl(imageUrls[currentImage]);
}
}
// Constructor. I'll leave it to you how you're going to
// build your list of image urls.
public ImageLooper(String[] imageUrls) {
this.imageUrls = imageUrls;
// Prefetching the list of images.
for (String url : imageUrls)
Image.prefetch(url);
// Start by displaying the first image.
image.setUrl(imageUrls[0]);
// Initialize this Composite on the image. That means
// you can attach this ImageLooper to the page like you
// would any other Widget and it will show up as the
// image.
initWidget(image);
}
// Call this method to start the animation
public void playAnimation() {
// Update the image every two seconds
imageUpdateTimer.scheduleRepeating(2000);
}
// Call this method to stop the animation
public void stopAnimation() {
imageUpdateTimer.cancel();
}
}
One annoying thing with this implementation is that you have no way of knowing when your list of images has finished loading; Image.prefetch doesn't have a callback to help you here.

Service layer for an UI with multiple screens

I am building a winforms screen. On the screen, it will show
Category1
Sub-1-1
Sub-1-2
Sub-1-3
Category2
Sub-2-1
Click on the sub-1-1 will popup an screen and show the data related to sub-1-1; same for sub-1-2, ... etc. So there will be totally five forms (1 main form + 4 popup forms for the sample above (the actually will have about 30 sub categories)).
I have models for Categories, sub-1-1, sub-1-2, ..., sub-2-1. I am writing a service layer. Should I do,
public class ServiceLayer
{
CategoriesModel GetCategories();
Sub11Model GetSub11();
Sub12Model GetSub12();
Sub13Model GetSub13();
Sub21Model GetSub21();
.....
}
Or each form has its now service class instance?
public class ICategoryService { ... }
public class ISubCategoryService<T>
{
T GetSub();
}
var sub11 = new SubService<Sub11Model>();
var sub12 = new SubService<Sub12Model>();
var sub13 = new SubService<Sub13Model>();
var sub21 = new SubService<Sub21Model>();
....
The first one looks like a GOD class and will probably violate most of the SOLID principles. It will make the code hard to refactor, even if it's just a facade.
You should of course use smaller interfaces which is only handling one responsibility.

Resources