Creating your first GUI
Creating GUIs are not easy. For example, here is a script that shows a GUI. The GUI includes a button that heals the player when pressed.
var simpleGUI = null;
var heal = false;
function newLevel(){
// run all the stuff at UI thread
var ctx = com.mojang.minecraftpe.MainActivity.currentMainActivity.get();
ctx.runOnUiThread(new java.lang.Runnable({ run: function() {
try{
simpleGUI = new android.widget.PopupWindow();
var layout = new android.widget.RelativeLayout(ctx);
var button = new android.widget.Button(ctx);
button.setText("Heal!");
button.setOnClickListener(new android.view.View.OnClickListener({
onClick: function(viewarg) {
heal = true;
}
}));
layout.addView(button);
simpleGUI.setContentView(layout);
simpleGUI.setWidth(100);
simpleGUI.setHeight(100);
simpleGUI.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.RED));
simpleGUI.showAtLocation(ctx.getWindow().getDecorView(), android.view.Gravity.LEFT | android.view.Gravity.TOP, 0, 0);
}catch(err){
print("Error: "+err);
}
} }));
}
function leaveGame(){
var ctx = com.mojang.minecraftpe.MainActivity.currentMainActivity.get();
ctx.runOnUiThread(new java.lang.Runnable({ run: function() {
if(simpleGUI != null){
simpleGUI.dismiss();
}
}}));
}
function modTick(){
if(heal){
Player.setHealth(20);
heal = false;
}
}
Whew! That's a lot of code. If you don't know already, this code was created by the fantastic MrARM. He creates mods for MC:PE.
This script is from his modpe-mods repository. It is the first script ever to use a GUI. He is the person who came up with the idea and created a proof-of-concept, which works really well.
Breaking down the code
First, lets look at the modTick
function. It is called 20 times every second.
function modTick(){
if(heal){
Player.setHealth(20);
heal = false;
}
}
All it does is check if heal
is true
. If it is, then it heals the player and sets heal
back to false
. The heal
variable is declared at the beginning of the code.
function newLevel(){
// run all the stuff at UI thread
var ctx = com.mojang.minecraftpe.MainActivity.currentMainActivity.get();
ctx.runOnUiThread(new java.lang.Runnable({ run: function() {
try{
simpleGUI = new android.widget.PopupWindow();
var layout = new android.widget.RelativeLayout(ctx);
var button = new android.widget.Button(ctx);
button.setText("Heal!");
button.setOnClickListener(new android.view.View.OnClickListener({
onClick: function(viewarg) {
heal = true;
}
}));
layout.addView(button);
simpleGUI.setContentView(layout);
simpleGUI.setWidth(100);
simpleGUI.setHeight(100);
simpleGUI.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.RED));
simpleGUI.showAtLocation(ctx.getWindow().getDecorView(), android.view.Gravity.LEFT | android.view.Gravity.TOP, 0, 0);
}catch(err){
print("Error: "+err);
}
} }));
}
Now comes the hard part, the guts of the code. Let's dissect it, together:
function newLevel(){
This makes the GUI show when we're loading into a level.
var ctx = com.mojang.minecraftpe.MainActivity.currentMainActivity.get();
This line of code is very important. It gets the Android context, which is required to make things like widgets and views. Without this object, creating GUIs would be impossible.
ctx.runOnUiThread(new java.lang.Runnable({ run: function() {
This line of code will run the following code on the UI thread. This is also important, because you should only be creating GUIs on the UI thread. Doing so on other threads will probably crash or make something go terribly wrong.
try{
MrARM wrapped the code in a try
-catch
block. This is clever, because if something goes wrong in a UI thread then BlockLauncher just crashes.
simpleGUI = new android.widget.PopupWindow();
Next, we create a PopupWindow
. It is a window that floats above everything else. Note that we do not pass the Android context to the constructor.
var layout = new android.widget.RelativeLayout(ctx);
Next comes the layout. The layout holds all of the child views (things like buttons, text, etc). We pass the context to the constructor.
var button = new android.widget.Button(ctx);
Now, we create a simple button. Passing along the context is also important.
button.setText("Heal!");
This line simply makes the button say "Heal!"
button.setOnClickListener(new android.view.View.OnClickListener({
onClick: function(viewarg) {
heal = true;
}
}));
These lines of code describe what will happen when we push the button. We need to create a new OnClickListener
because that is what Android uses. In this case, it will just set the heal
variable to true.
layout.addView(button);
This line adds the button into the layout. This is important because it wouldn't show up if we didn't.
simpleGUI.setContentView(layout);
This tells the window to use the layout
variable as the main content (what will show up inside).
simpleGUI.setWidth(100);
simpleGUI.setHeight(100);
These lines set how big the GUI will be. You will probably not actually do this; instead you would fetch the metrics for screen size and adjust accordingly, like responsive design.
simpleGUI.setBackgroundDrawable(new android.graphics.drawable.ColorDrawable(android.graphics.Color.RED));
All this line does is make the background of the window red. It's practical to set it to a dark color, like BLACK
.
simpleGUI.showAtLocation(ctx.getWindow().getDecorView(), android.view.Gravity.LEFT | android.view.Gravity.TOP, 0, 0);
This code shows the window at the top left corner of the screen. Gravity
in Android determines how a view will anchor.
}catch(err){
print("Error: "+err);
}
Catches all errors and prints them out if something goes wrong.
}}));
}
Close all braces and end the newLevel
function.
That leaves us with the leaveGame
function. It is called when we leave the level/server.
function leaveGame(){
var ctx = com.mojang.minecraftpe.MainActivity.currentMainActivity.get();
ctx.runOnUiThread(new java.lang.Runnable({ run: function() {
if(simpleGUI != null){
simpleGUI.dismiss();
}
}}));
}
- line 2: Fetches the Android context again.
- line 3: Runs a function in the UI thread, because we can't touch anything UI-related unless we are on that thread.
- line 4: Check if
simpleGUI
is null. Remember that it holds thePopupWindow
. - line 5-6: Check if it's not null, and if it is, dismiss (close) it.
- line 7: Done with
runOnUiThread
- line 8:
leaveGame
ends
In summary, all it does is close out PopupWindow
when we close out of a level.
Advanced Stuff
If you want to start creating more advanced GUIs, then the Android documentation will help you out a lot. It provides methods, details, package names (required in this context), and more. It is super useful.
For example, you can search "android linearlayout" on Google and get back Android documentation.