I am trying to create a simple game based on the 2D game framework as described in the 2011 Apress book, "Beginning Android Games" by Mario Zechner. Maybe that helps, maybe it doesn't, but either way:
I only have one activity for the whole game. Everything is rendered onto a bitmap, which is then sent to a SurfaceView, and what is sent to the SurfaceView will change based on what screen the game is on.
I want to implement a simple highscore system that lets users enter their name into an EditView on the main menu screen. I've been able to combine the SurfaceView and the EditView with a RelativeLayout, but the problem is getting rid of the EditView once the user moves past the main menu screen.
There is much more to this class, but here's a snipet of what I feel is important:
public abstract class AndroidGame extends Activity implements Game{
public EditText et;
public RelativeLayout rl;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
et = new EditText(this);
renderView = new AndroidFastRenderView(this, frameBuffer);
rl = new RelativeLayout(this);
rl.addView(renderView);
rl.addView(et);
setContentView(rl);
}
}
The above is the only activity for the game. The AndroidFastRenderView class extends SurfaceView. The problem I'm having is that while I need the SurfaceView to persist through the whole game, I need EditText to only persist for a short while, then disappear based on touch events.
I try to call RelativeLayout.removeView(et) from my class MainMenuScreen, which is responsible for constructing the bitmap sent to the SurfaceView as well as listening for touch events. But I get an uncaught exception that says I can't edit views that are defined in one thread from another.
I'm sorry for the novel, but I've been trying to solve this myself for hours with no luck. I feel like this is a very simple thing I'm just not getting. Any help is much appreciated!
Hm... I think only UI Thread can Add and delete views. Try to call the Thread like this:
runOnUiThread(new Runnable(){
public void run() {
/* STUFF To do in Thread */
//Delete the view...
rl.removeView(et);
}});
Hope it helps :)
Related
I am making a 2d game with Canvas in Android.
I have read the documentation of Canvas and I find out that we can create a class that extends View class, like this:
Class MyDraw extends View{
}
and use it as setContentView() in another class, like this:
class HomeActivity extends AppCompatActivity{
void onCreate(Bundle savedInstanceState) {
setContentView(new MyDraw());
}
So my question is: What is the difference between upper code and use MyDraw class as an object without setContentView(new MyDraw()), like this:
class HomeActivity extends AppCompatActivity{
void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_home));
MyDraw myDraw = new MyDraw(context);
myDraw.draw()
}
Which one is better performance?
And when we should use which one?
Performance will be the same here, but there is a very important difference.
If you want to show your canvas, then you need to get it into the content view, so either as the top level view or as a child of it. But in your two examples, only the first one would be shown.
Game engine will be better for performance :)
But, If you want to make it by youself consider using at least SurfaceView https://developer.android.com/reference/android/view/SurfaceView because It provides async drawing to Canvas.
Or you may want to draw it using OpenGL via GLSurfaceView, but this is completely different story
I am trying to show logs on a overlay over all activities. I found this https://stackoverflow.com/a/19037235/3370924 answer which implements the overlay in the application class. I have added a TextView to the LinearLayout to show my logs.
At first it works but then I get the error android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
when I have opened a new Activity and I am trying to add a new string to the TextView.
Usually i use runOnUiThread() but this method is not available in Application class. Can anyone please help me?
If we pretend that your TextView is called tv, do:
tv.post(new Runnable() {
#Override
public void run() {
// put your update-the-TextView code here
}
});
I have a bit of a problem I cannot solve, since it might a bug or something like that. I would like to make a chart with androidplot, and it works really good, but of course it needs some time to draw it (using hundreds of data), so I use a progress dialog to indicate the loading. But what happens is really weird.
I can define the appearance of the activity when it's loading and when it's loaded. When its loading I define a textview in the background setting its text to "loading" and if it is loaded, that textview contains lots of datas, text etc.
onCreate
{
Thread thread = new Thread(new Runnable() {
public void run() {
-------what needs to be appeared after its loaded ----
Textview -> 12,3245,456,78,789
}
----what is on the screen while the progressbar is on---
TextView -> loading..
}
But most of the time after the progress dialog disappears, nothing happens, the textview still says "loading" and rarely it loads the datas and makes the data appear and changes the textview. What I noticed that the more data I would like to appear the rarelier it stays at the loading phase. Of course everytime the loading progessbar appeers then disappears.
Any Suggestion? It is really weird because I use it in a tablayout and other tabs never do this, always make the data appear.
Thanks in advance!
UP: Okay, its always the first tab, whatever it contains, so the first tab is somehow wrong...
The Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI
from a worker thread—you must do all manipulation to your user interface from
the UI thread. Thus, there are simply two rules to Android's single thread model:
1. Do not block the UI thread
2. Do not access the Android UI toolkit from outside the UI thread
read this for more information on how to access UI elements from outside.
edit::
use AsyncTask ::
onCreate
{
new myLoading().execute();
}
class myLoading extends AsyncTask<Void, Void, Void>
{
protected Void doInBackground(Void ... ) {
.......... do all the loading here .........
}
protected void onPostExecute(Void ) {
Textview -> 12,3245,456,78,789
}
}
I figured out some workaround. I dont have any clue about the solution, my only guess is the loading screen somehow overtake the arrival of all the data and so the chart cannot be drawn. or whatever...
I put a thread.sleep(1000) and now it works.
I'm fairly new to Java & Android, so I have little idea what I am doing.
My test program successfully creates view objects, so now I am trying to organize my code.
I want to make a separate class to manage my GUI, but it always fails.
Basic info about my gui class:
package horc.gui;
...
public class GUI{
private Context context;
From my main activity, I constructed that gui class with the app context.
gui=new GUI(getApplicationContext()); // gui is a var of type GUI, & this sets the context of the class
The problem is when I make/modify a view object that is in the class from outside, it throws an exception.
My main activity...
package horc.test;
...
GUI gui;
LinearLayout test=gui.newLinear("ff", "v"); // <-- this sets fill parent for width/height
// & vertical orientation of the vertical layout.
// Doesnt work for the reason stated above.
// I cannot manage any view objects from a separate class.
gui.lastText.setText("##########"); // <-- a variable in the class to hold the view object I am manipulating
setContentView(t);
...calls this class function:
public TextView newText(String text){
TextView test=new TextView(context);
lastLinear.addView(test);
return test;
}
I tested this similar body within the main activity & it worked fine. It only fails when I do anything from outside that gui class.
Is there a common issue that people run into when managing view objects in separate classes? I have absolutely no idea what I am doing at this point. Coming from C++, java seems like a nutty language. I cannot plan things the way I would in C++.
instead of
gui=new GUI(getApplicationContext());
try
gui=new GUI(MyActivity.this);
Please put your activity name instead of MyActivity
Just want to start out by saying this seems like a great site, hope you guys can help!
I'm trying to use the structure laid out in LunarLander to create a simple game in which the user can drag some bitmaps around on the screen (the actual game is more complex, but that's not important). I ripped out the irrelevant parts of LanderLander, and set up my own bitmap drawing, something like
BoardThread (an inner class of BoardView):
run()
{
while(mRun)
{
canvas = lockSurfaceHolder...
syncronized(mSurfaceHolder)
{
/* drawStuff using member position fields
in BoardView */
}
unlockSurfaceHolder
}
}
My drawStuff simply walks through some arrays and throws bitmaps onto the canvas. All that works fine. Then I wanted to start handling touch events so that when the user presses a bitmap, it is selected, when the user unpresses a bitmap, it is deselected, and if a bitmap is selected during a touch move event, the bitmap is dragged. I did this stuff by listening for touch events in the BoardView's parent, BoardActivity, and passing them down into the BoardView. Something like
In BoardView
handleTouchEvent(MotionEvent e)
{
synchronized(mSurfaceHolder)
{
/* Modify shared member fields in BoardView
so BoardThread can render the bitmaps */
}
}
This ALSO works fine. I can drag my tiles around the screen no problem.
However, every once in a while, when the app first starts up and I trigger my first touch event, the handleTouchEvent stops executing at the synchronized line (as viewed in DDMS). The drawing loop is active during this time (I can tell because a timer changes onscreen), and it usually takes several seconds or more before a bunch of touch events come through the pipeline and everything is fine again.
This doesn't seem like deadlock to me, since the draw loop is constantly going in and out of its syncronized block. Shouldn't this allow the event handling thread to grab a lock on mSurfaceHolder? What's going on here? Anyone have suggestions for improving how I've structured this?
Some other info. This "hang" only ever occurs on first touch event after activity start. This includes on orientation change after restoreState has been called. Also, I can remove EVERYTHING within the syncronized block in the event handler, and it will still get hung up at the syncronized call.
Thanks!
So Rob Green from rbgrn helped me get a little more info on this. I ended up using a concurrent queue to deliver touch events to my game thread, but I still had hanging issues when saveInstanceState got called, so I'm now calling Thread.sleep(16) at the bottom of every iteration of my game thread's while loop. Full discussion here.