j2me screen flicker when switching between canvases - java-me

I'm writing a mobile phone game using j2me. In this game, I am using multiple Canvas objects.
For example, the game menu is a Canvas object, and the actual game is a Canvas object too.
I've noticed that, on some devices, when I switch from one Canvas to another, e.g from the main menu to the game, the screen momentarily "flickers". I'm using my own double buffered Canvas.
Is there anyway to avoid this?

I would say, that using multiple canvases is generally bad design. On some phones it will even crash. The best way would really be using one canvas with tracking state of the application. And then in paint method you would have
protected void paint(final Graphics g) {
if(menu) {
paintMenu(g);
} else if (game) {
paintGame(g);
}
}
There are better ways to handle application state with screen objects, that would make the design cleaner, but I think you got the idea :)
/JaanusSiim

Do you use double buffering? If the device itself does not support double buffering you should define a off screen buffer (Image) and paint to it first and then paint the end result to the real screen. Do this for each of your canvases. Here is an example:
public class MyScreen extends Canvas {
private Image osb;
private Graphics osg;
//...
public MyScreen()
{
// if device is not double buffered
// use image as a offscreen buffer
if (!isDoubleBuffered())
{
osb = Image.createImage(screenWidth, screenHeight);
osg = osb.getGraphics();
osg.setFont(defaultFont);
}
}
protected void paint(Graphics graphics)
{
if (!isDoubleBuffered())
{
// do your painting on off screen buffer first
renderWorld(osg);
// once done paint it at image on the real screen
graphics.drawImage(osb, 0, 0, Tools.GRAPHICS_TOP_LEFT);
}
else
{
osg = graphics;
renderWorld(graphics);
}
}
}

A possible fix is by synchronising the switch using Display.callSerially(). The flicker is probably caused by the app attempting to draw to the screen while the switch of the Canvas is still ongoing. callSerially() is supposed to wait for the repaint to finish before attempting to call run() again.
But all this is entirely dependent on the phone since many devices do not implement callSerially(), never mind follow the implementation listed in the official documentation. The only devices I've known to work correctly with callSerially() were Siemens phones.
Another possible attempt would be to put a Thread.sleep() of something huge like 1000 ms, making sure that you've called your setCurrent() method beforehand. This way, the device might manage to make the change before the displayable attempts to draw.
The most likely problem is that it is a device issue and the guaranteed fix to the flicker is simple - use one Canvas. Probably not what you wanted to hear though. :)

It might be a good idea to use GameCanvas class if you are writing a game. It is much better for such purpose and when used properly it should solve your problem.

Hypothetically, using 1 canvas with a sate machine code for your application is a good idea. However the only device I have to test applications on (MOTO v3) crashes at resources loading time just because there's too much code/to be loaded in 1 GameCanvas ( haven't tried with Canvas ). It's as painful as it is real and atm I haven't found a solution to the problem.
If you're lucky to have a good number of devices to test on, it is worth having both approaches implemented and pretty much make versions of your game for each device.

Related

Display notifications correctly in Android Wear

My notifications display correctly when paired with an Android Wear square device - they are just sent to the device (watch) for automatic display to keep the code simple. However, they are in the default center of the screen on Wear round watches and some of the notification info is actually missing from a corner of the round screen notification.
BigTextStyle myStyle = new Notification.BigTextStyle();
.bigText(myText);
Notification.Builder notificationBuilder =
new Notification.Builder(this)
.setStyle(myStyle)
// and so on
It might, however, be a case of adding the following few lines of code (and its class import) somewhere:
Notification.WearableExtender myextend = new Notification.WearableExtender();
.WearableExtender()
.setGravity(Gravity.TOP);
// add other code
.extend(myextend)
Based from this documentation, since some Android Wear devices have square screens, while others have round screens, your watch face should adapt to and take advantage of the particular shape of the screen, as described in the design guidelines.
Android Wear lets your watch face determine the screen shape at runtime. To detect whether the screen is square or round, override the onApplyWindowInsets() method in the CanvasWatchFaceService.Engine class as follows:
private class Engine extends CanvasWatchFaceService.Engine {
boolean mIsRound;
int mChinSize;
#Override
public void onApplyWindowInsets(WindowInsets insets) {
super.onApplyWindowInsets(insets);
mIsRound = insets.isRound();
mChinSize = insets.getSystemWindowInsetBottom();
}
...
}
Devices with round screens can contain an inset (or "chin") at the bottom of the screen. To adapt your design when you draw your watch face, check the value of the mIsRound and mChinSize member variables.
Here are some related threads which might help:
Is there any way to detect if the clock is round?
How to set the Watchface in the center of watch

Play sound when other object(ball) hit cube

using UnityEngine;
using System.Collections;
public class audio : MonoBehaviour
{
public AudioClip hitsound;
void Update ()
{
}
void OnTriggerEnter2D (Collider2D other)
{
if (other.tag == "Ball")
{
GetComponent.<AudioSource>().PlayOneShot (hitsound);
}
}
}
I assign .mp3 file to inspector, and also, I added Audio Source component but I can't hear hit sound. Cubes which need to be destroyed is moving during game. I added that script and audio source component on parts which are not moving and when ball hit that non-moving parts, sound is playing (every time).
I hope that someone can help me with this.
Thanks and kind regards
YOU HAVE A TYPO
GetComponent.<
SHOULD BE
GetComponent<
Doesn't the . after GetComponent give you an error?
Anyway, make sure your colliders are set as triggers (checkbox on component).
Also I think Unity recommend using CompareTag() instead of ==.
It's worth putting a Debug.Log into the OnTriggerEnter2D to see if that is even firing.
Finally, make sure your colliders are the 2D versions, not just the regular colliders.

Scala swing panel disappears when trying to change contents (only when running a Thread)

So I'm writing a boid simulation program as a project for school. My program supports multiple different groups of these boids that don't flock with other groups, they all have different settings which I do by adding a BoxPanel to the main GUI of the program when a new tribe is made, and those BoxPanels have a settings button that opens a new frame with the groups settings.
This works perfectly when I start the program up and add all the pre defined tribes that are in the code. Now I made a new part of the GUI that let's you make new groups of these boids and adds them while the simulation is running, and here is when the problems start for me.
For some weird reason it adds the group just fine, with the right settings in to the simulation but it wont add the BoxPanels to the main GUI. It makes the whole settings bar that I have in the side of my simulation disappear completely. I tested this out and if I add the tribes in the beginning of my calculation thread it does the same thing, so this seems to be a problem with multiple threads and swing. Any ideas what is causing this or how to fix this? I am completely perplexed by this.
tl;dr: The code below for adding tribes works fine when I haven't started the thread but if I try to use it after starting the thread the optionPanel appears empty.
Here's the code that adds the BoxPanels to the main gui:
def addTribe(tribe: Tribe) = {
tribeFrames += new TribeSettingFrame(tribe)
tribeBoxPanels += new TribeBoxPanel(tribe)
this.refcontents
}
private def refcontents = {
top.optionPanel.contents.clear()
top.optionPanel.contents += new BoxPanel(Orientation.Vertical) {
tribeBoxPanels.foreach(contents += _.tribeBoxPanel)
}
top.optionPanel.contents += new BoxPanel(Orientation.Horizontal) {
contents += top.addTribeButton
}
top.optionPanel.contents += new BoxPanel(Orientation.Horizontal) {
contents += top.vectorDebugButton
}
}
new Thread(BoidSimulation).start()
Oh and I tested if it really adds the contents that it should by printing out the sizes of the contents, and everything matches fine, it just won't draw them.
EDIT: After some digging around it really seems to be a thing with updating swing from a Thread. A lot of places suggest to use SwingWorker but from the info I gathered about it I don't think it would fit in my program since it is a continuous simulation and and I would have to keep making new SwingWorkers every frame.
EDIT2: Tried calling the method from the thread like this:
SwingUtilities.invokeLater(new Runnable() {
override def run() {
GUI2D.addTribe(tribe)
}
});
Didn't make any difference. I am starting to think that this is a problem with how I use TribeBoxPanel and TribeSettingFrame. These are objects that both contain only one method that returns the wanted BoxPanel or Frame. Is this implementation bad? If so what is the better way of creating dynamic BoxPanels and Frames?
Swing is not thread-safe.
Repeat after me.
Swing is not thread-safe.
Hear the chorus? Swing is not thread safe There is official documentation.
There is a very simple workaround given as well.
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
// your stuff
}
});
In Scala, this is supported as:
Swing.invokeLater(/* your stuff */)
First you should let the UI thread handle all UI manipulation.
The simple way should be following Scala-Code:
Swing.onEDT { GUI2D.addTribe(tribe) }
But as you already noted, this won't solve your problem. I had a very similar problem where I only changed the text content of a Swing.Label and it sometimes simply disappeared.
It turned out that it only disappeared, when the text was too long to display it inside the Area which the Label initially reserved for itself. So one way around your Problem could be to give the optionPanel a bigger initial size when you create it.
Swing.onEDT { top.optionPanel.preferredSize = new Dimension(width,height) }
I'm not quite sure whether this has to be set before the component is first drawn (before Frame.open() is called).

Java Thread Safety v Displaying a Dialog from separate Thread

Hi noticed some code in our application when I first started Java programming. I had noticed it created a dialog from a separate thread, but never batted an eye lid as it 'seemed to work'. I then wrapped this method up through my code to display dialogs.
This is as follows:
public class DialogModalVisibleThread
extends Thread {
private JDialog jDialog;
public DialogModalVisibleThread(JDialog dialog, String dialogName) {
this.setName("Set " + dialogName + " Visable");
jDialog = dialog;
}
#Override
public void run() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
}
Usage:
WarnUserDifferenceDialog dialog = new WarnUserDifferenceDialog( _tableDifferenceCache.size() );
DialogModalVisibleThread dmvt = new DialogModalVisibleThread( dialog, "Warn User About Report Diffs");
dmvt.start();
Now, as far as I am now aware, you should never create or modify swing components from a separate thread. All updates must be carried out on the Event Dispatch Thread. Surely this applies to the above code?
EDT on WikiPedia
However, the above code has worked.
But lately, there have been countless repaint issues. For example, click on a JButton which then calls DialogModalVisibleThread to display a dialog. It caused buttons alongside the clicked button not to redraw properly.
The repaint problem is more frequent on my machine and not the other developers machine. The other developer has a laptop with his desktop extended onto a 21" monitor - the monitor being his main display. He is running Windows 7 with Java version 1.6.0_27.
I am running on a laptop with Windows 7 and Java version 1.6.0_24. I have 2 additional monitors with my desktop extended onto both.
In the meantime I am going to upgrade to Java 1.6 update 27.
I wondered if the above code could cause repaint problems or are there any other people out there with related paint issues?
Are there any easy ways to diagnose these problems?
Thanks
So, you're breaking a rule, having problems, and wondering if these problems could be cause by the fact that you broke the rule. The answer is Yes. Respect the rules!
To detect the violations, you might be interested by the following page: http://weblogs.java.net/blog/2006/02/16/debugging-swing-final-summary
The easiest way to check if your problems are being caused by breaking the rules is to fix them (You should fix them anyway :-)
Just use SwingWorker.invokeLater() from the thread you want to update to UI from to easily adhere to Swing's contract. Something like this should do the trick:
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
});
}
EDIT: You should make the 'jDialog' variable final for this to work.

AndEngine FPS Drops With Each Sprite

I am working with AndEngine for an app project and I have hit a major snag in regards to my frame rate. I have a few decently sized sprites to place on the screen, each being 512x768, and it seems that each one of these I add takes a very noticeable chunk of my FPS away.
Even if the image being used is nothing but a blank PNG, there is an equivalent amount of loss. I have searched around and tried everything that made sense, but nothing seems to have improved it at all, and the lack of documentation for AndEngine doesn't simplify matters any.
My only real guess at the reason is that the sprites must be entirely recreating themselves every call. I could be entirely wrong, but it's the only logical reason I can think of. Despite that, I am not sure how to stop this from happening (Still assuming it is the problem at all of course).
The code I am using to create everything is the same as every example I've seen, so I doubt that is the problem, but just in case my sprites are setup more or less like the following :
public void onLoadResources(){
this.mTexAtlas = new BitmapTextureAtlas(1024, 1024, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mTexBottom = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mTexAtlas, this, "bottom.png", 0, 0);
this.getEngine().getTextureManager().loadTexture(this.mTexAtlas);
}
public Scene onLoadScene(){
mTexBottom = new Sprite(spriteX, spriteY, spriteWidth, spriteHeight, mTexAtlas);
scene.attachChild(mTexBottom, childCount++);
}
It's not my exact code, for clarity reasons, but that is how all of the examples I have seen look, so that's pretty much how mine looks. Oh, and the texture atlas is 1024 wide because I am putting two images on each, at least for right now.
At this point I am willing to try anything to get it going a little better, so any ideas at all would be great.
I think you are using the wrong variables in the wrong places, could you try it like this?
public void onLoadResources(){
this.mTexAtlas = new BitmapTextureAtlas(1024, 1024, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mTexBottom = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mTexAtlas, this, "bottom.png", 0, 0);
this.getEngine().getTextureManager().loadTexture(this.mTexAtlas);
}
public Scene onLoadScene(){
Sprite theSprite = new Sprite(spriteX, spriteY, spriteWidth, spriteHeight, mTexBottom );
scene.attachChild(theSprite, childCount++);
}
How big is your Camera? I mean how big are your Sprites compared to the screen?
You should try to avoid drawing the screen more than once. Drawing a couple of Sprites that cover the whole screen is probably the worst thing you could do.

Resources