I'm a flash developer with no previous Java experience, just starting to learn android development. I'm trying to make a simple kid's flash cards app, consisting of a load of images of animals, and a load of sounds that they make.
Currently I have the images in a gallery view, storing them in an array. I also have an array of the sounds. So each image and the corresponding sound are in the same position in the array, so it's easy to play the right sound for the right image.
Now I want to shuffle the cards so that they appear in a different order each time the app is started up. I managed to shuffle the arrays into a random order, but kept the images and sounds in the same positions in each array but I can feel this getting messy and I'm sure this isn't the best way to go about this problem.
If this were a flash movie, I'd use objects to link the images and sounds and stick the objects in an array. Can anyone help me with some code which would achieve the same thing for android? Bear in mind I'm a complete beginner with Java and have gotten this far with tutorials and basic concepts being the same as AS3.
I'd use objects to link the images and sounds and stick the objects in an array.
Me too. Just create a class to wrap animals and sounds:
class SomeNiceName{
private final Bitmap animal;
// I'm guessing the sound is in the resources
// folder, thus you only need an integer to reference it
private final int sound;
public Animal(Bitmap animal, int sound){
this.animal = animal;
this.sound = sound;
}
public Bitmap getAnimal(){
return animal;
}// missing getter for sound
}
In this case I'm using an immutable object which is convenient in this case. Then you can create an array of those animals, o better yet a list:
// array
SomeNiceName[] array = new SomeNiceName[blah];
array[0] = new SomeNiceName(someBitmap, theSound);
// or with lists:
List<SomeNiceName> list = new ArrayList<SomeNiceName>();
list.add(new SomeNiceName(someBitmap, theSound));
The only thing you would have to "disorder" in this case is one array.
As Christian said you can of course use class in your Android application.
But, since mobile devices haven't huge processing capabilities like desktops or laptops -yet-, I advice you to read the articles below before running your OOP habits ;)
Object Creation
Getters/Setters? Not here!
For items above and more...
Related
I am currently working on a simple mp3 player as an app on my android phone. I am going through all the files on my sd card and my internal storage to find everything with the extension: ".mp3".
Simple and works fine.
I then fill out a list with all the resulting song names and when clicked, they start playing. Working fine as well BUT
I now tried this on my personal phone with 700+ songs on it and the lists are done in less than a second but now the lists are to populate a ScrollView in a foreach loop with the results. And this takes for ever:
private void PopulateScrollView(List<string> content)
{
LinearLayout root = (LinearLayout)FindViewById(Resource.Id.scrollview);
mp3 = new List<MP3object>();
foreach (string obj in content)
{
WriteMetaDataToFileList(obj);
TextView txt = new TextView(this);
reader.SetDataSource(obj);
txt.Text = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
txt.TextSize = 20;
txt.Gravity = Android.Views.GravityFlags.Center;
root.AddView(txt);
txt.Click += delegate
{
PlayMusic(Android.Net.Uri.Parse(obj));
firstStart = false;
txt_CurrentSong.Text = CurrentActiveSongUri.ToString();
btn_StartOrPause.Text = Resources.GetString(Resource.String.Pause);
};
}
}
So, I am wonderin. What am I doing differently then my "normal" music player on my phone? I open it, and all the songs are already filled inside a ScrollView, almost NO waiting time. Appearently, going through the loop 700+ times to fill it up with the songs is way too much work, but it has to be done, right? Or am I seeing something wrong here? Some help would be AWESOME! :)
Thank you.
*** EDIT:
Also, I noted that every app that lists my files on my phone is quick as hell listing even 1000+ files in a scrollview. Clearly, my way is the incorrect way to fill a scrollview with static items from my phone. Any other ways of doing this? thank you :)
The problem you're hitting is that ScrollView is not made to be used with long lists of data. You're forcing Android to generate, lay out, and maintain a huge number of views. Instead you should look into the RecyclerView.
RecyclerView is made to handle long lists of data elements, like your use-case of mp3 files. It handles the large amount of data by only creating the elements needed to display items that are currently on the screen (plus a couple additional items to help with smooth scrolling). This greatly reduces the memory and cpu pressure on the system and allows for the responsiveness you see in other apps. Those other apps are most likely using RecyclerView or a similar pattern.
I recommend reading through Google's guide on the RecyclerView (linked above, but also here for convenience) to learn how to use it. I'd also recommend using RecyclerView's built-in list-item selection functionality to handle user taps instead of your TextView.click event. Both can work, but the selection functionality will likely be more convenient as RecyclerView handles the hard parts for you.
I'm working in an Android game using libGDX framework while a learn from their wiki and Learning Libgdx Game Development book. The author of the book defines an Assets class to load game assets using an AssetManager. Every time the game is resumed the assets need to be reloaded so he use a call to Assets.intance.init(new AssetManager()) what reload the assets and create new objects to store textures references.
When I do this in my game, after resume, all I have are black boxes where I had nice textures so I suppose that the problem here is that I'm using the old references. I put here part of the code from the book:
AssetManager#init
public void init(AssetManager assetManager) {
/* Dispose previous asset manager */
if (this.assetManager != null) {
this.assetManager.dispose();
}
this.assetManager = assetManager;
assetManager.setErrorListener(this);
assetManager.load(Constants.TEXTURE_ATLAS, TextureAtlas.class);
/* Start loading assets and wait until finished */
assetManager.finishLoading();
Array<String> assetNames = assetManager.getAssetNames();
Gdx.app.debug(TAG, "Assets loaded: " + assetNames.size);
for (String assetName : assetNames) {
Gdx.app.debug(TAG, "Asset: " + assetName);
}
TextureAtlas atlas = assetManager.get(Constants.TEXTURE_ATLAS);
/* Create game resource objects. Here I get what I need from the atlas */
player = new AssetPlayer(atlas);
enemy = new AssetEnemy(atlas);
}
When I create my game objets I use Assets.instance.player and Assets.instance.enemy to store a reference to textures as the author of the book does so this could be the problem. The thing is that aftere re-read the book, I don't see how he solve this problem.
I'm pretty sure that I can solve the problem changing references in my game objects but all is becoming so messy. My real question is, how should I manage game assets in my game? I've been searching a lot for game examples but most of them don't use an AssetManager but instead static variables to textures.
Should I keep references of textures in game objects? It is really necessary to reload assets on resume? How could I reload textures in my game objects when all the objects are inside a worldController that don't know when a game is being resumed?
You're doing it correctly, as far as I can tell, at this level. You really do need to reload the textures, as your OpenGL context was lost, and all "pointers" into OpenGL-internal state are stale.
As you point out, because your AssetManager.player property points to a new object, anything that cached an old pointer is stale after a restart, and that is probably the source of your problems. (Though its hard to say for certain.)
If you look at the Libgdx SuperJump demo, they also cache all their asset pointers in static fields, but notice that the render calls effectively look up the texture every call. See WorldRenderer.renderBob(). One alternative would be to do a pass over your objects after (re)-loading assets to have them "refresh" their pointers the assets they use.
Have you tried not to call Assets.intance.init(new AssetManager()) on resume method (and also not to call Assets.intance.dispose() on pause method)?
Please read this link:
https://github.com/libgdx/libgdx/wiki/Managing-your-assets
At the end (Resuming with a Loading Screen) it says:
On Android your app can be paused and resumed. Managed OpenGL resources like Textures
need to be reloaded in that case, which can take a bit of time. If you want to
display a loading screen on resume, you can do the following after you created your
AssetManager.
Texture.setAssetManager(manager);
In your ApplicationListener.resume() method you can then switch to your loading screen and call AssetManager.update() again until everything is back to normal.
If you don't set the AssetManager as shown in the last snippet, the usual managed texture mechanism will kick in, so you don't have to worry about anything.
So, I believe that the author's approach is no longer necessary.
You only need to call Assets.intance.dispose() on dispose method in your "Game" class (I mean, the class that implements ApplicationListener).
I am developing a small libgdx game. I want to create sqlite database for storing game scores.
But i am not able to do the same as that i used in the activity. How to implement the same
Thanks in advance
Using a Database just to store scores seems to be a bit overpowered. Furthermore it won't be cross-platform compatible anymore, which is one of the major advantages with LibGDX.
I'd suggest you to do this either via:
an XML file: LibGDX: XML
a JSON file: LibGDX: JSON
Preferences: Preferences
With Preferences you would just store something like "level"="score".
With XML or JSON you could do much more, e. g. have a little class like the following:
public class Highscore {
private String username;
private String level;
private int score;
}
And then you would just write an array of those to JSON/XML and read it in as an array the next time you start the app. For a limited amount of highscores, this should be implemented pretty quickly and should not be a performance issue. Just load the list once on startup, and only update it when you detect a new highscore.
I've decided to create an Android touch screen game. I am a complete and utter beginner and am learning as I go.
My game has a little elephant that moves up when you press and hold on the screen and falls when there is no contact with the screen. The aim is to collect as many peanuts that fly past as possible to gain the highest score. Pretty simple, you'd think so.
So far, I've managed to get to the point where the elephant can collide with a peanut and the peanut disappears.
My issue right now is, I can't create more than one peanut, with the same instance name of "peanut" because only the one will work and the others will not be recognized. I've done a good ole google search and nothing has really given me the right way to go. Could someone give me a clear answer of what to do or where to go from here?
If you need any more info, the code or a picture of what i've got so far to help you understand just let me know :)
Samantha
Instance name must be unique, and you cannot use instance name to find a set of movie clips. You should instead use an array, and at creating a peanut add it there too using say push(), and at collecting a peanut, splice it out.
In fact, whenever you get a multi-instance class with similar functionality (aka "collect"), use an Array to store references to all of these, so you will always know that ALL of your instances are accessible through that array.
How to work with arrays
A sample code:
var peanuts:Array=new Array();
function addPeanut(x:Number,y:Number):void {
var peanut:Peanut=new Peanut(); // make a peanut, you do this somewhere already
peanut.x=x;
peanut.y=y;
peanuts.push(peanut); // this is where the array plays its role
game.addChild(peanut); // let it be displayed. The "game" is whatever container
// you already have to contain all the peanuts.
}
function removePeanut(i:int):void {
// give it index in array, it's better than giving the peanut
var peanut:Peanut=peanuts[i]; // get array reference of that peanut
peanuts.splice(i,1); // remove the reference from the array by given index
game.removeChild(peanut); // and remove the actual peanut from display
}
function checkForPeanuts():void {
// call this every so often, at least once after all peanuts and player move
for (var i:int=peanuts.length-1; i>=0; i--) {
// going through all the peanuts in the array
var peanut:Peanut=peanuts[i];
if (player.hitTestObject(peanut)) {
// of course, get the proper reference of "player"!
// YAY got one of the peanuts!
// get some scoring done
// get special effects, if any
removePeanut(i); // remove the peanut
}
}
}
I am working on an Android app, where media(audio/video/images) could be stored either internally/externally. I would be facing the following scenarios
Case I
Setting dynamically images from the random value broadcasted by the app.
Right now, I am managing it as
if(rowData.strName.equals("football")){
imageView.setImageResource(R.drawable.football);
}else if(rowData.strName.equals("chess")){
imageView.setImageResource(R.drawable.chess);
Problem As of now, I am having few records so managing else if loop in not big headache, but later it could turn out to be one.
Case II
Downloading a media from internet, saving it in external storage and loading it on an imageview as an when required
Problem Incase, the image has already been downloaded(app keeps track of downloaded image), the user ejects the card, then I plan to use
try{
}catch(FileNotFoundException e){
imageView.setImageResource(R.drawable.no_media);//media from the app
}
Case III
I will be having a listView of a category.Each Category contains certain sub-category names,their images(inbuilt & to be downloaded externally) & their description.Each sub-category has sub records with each record having its own one or image(inbuilt & to be downloaded externally),description and media files(both audio and video).
I am confused on what Collection class shall I use for this case and how to begin with? For data that is to be retrieved from the server(online), I plan to use XMLParsing. Please suggest me the best way to achieve the problem.
Wow! This is really three questions. If only I could get three times the rep :)
Case I
Use a Map to store and retrieve stuff. Saves you writing lots of if/else statements.
Map<String,Integer> drawableMap = new HashMap<String,Integer>();
drawableMap.put("football", R.drawable.football);
// Then later to retrieve...
imageView.setImageResource(drawableMap.get("football"));
Case II
OK, this seems fine. Though for most of my image loading I use existing libraries like Universal Image Loader or Volley. These may do what you need, I'm not sure.
Case III
I would take an OO approach and model the data appropriately. You don't have to choose "a" Collection class to use. Create a Category class. Create a SubCategory class. Have the Category class "have" SubCategories, etc. Take it from there.
XML parsing is fine, I'm not sure what you're expecting to be suggested. You may also like to consider JSON, a popular data format.