Добрый вечер форумчане! Сегодня хочу представить вашему вниманию второй урок по JME, в котором мы будем создавать имитацию стрельбы из оружия. Итак приступим:
Урок№2.
Ввод.
Сначала, как и в прошлом уроке, создадим новый проект и в создавшемся классе оставим следующее:
Код
package mygame;
import com.jme3.app.SimpleApplication;
public class Main extends SimpleApplication {
public static void main(String[] args) { Main app = new Main(); app.start(); }
@Override public void simpleInitApp() {
}
@Override public void simpleUpdate(float tpf) {
}
}
Теперь, чтобы реализовать ввод с клавиатуры/мыши, необходимо к нашему классу добавить интерфейс ActionListener:
Код
public class Main extends SimpleApplication implements ActionListener
Программа сразу же нам указывается на ошибку и предлагает реализовать все абстрактные методы для этого интерфейса. Мы конечно же соглашаемся и видим, что у нас появился такой метод:
Код
public void onAction(String name, boolean isPressed, float tpf) { throw new UnsupportedOperationException("Not supported yet."); }
Пока оставим его. Теперь создадим событие для нажатия левой кнопки мыши и слушатель этого события. Для этого в метод simpleInitApp() добавим следующее:
Код
inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL");
Теперь создадим новый метод, в котором у нас будут создаваться пули. Я назвал его bulletCreate. В итоге у нас получится следующее:
public class Main extends SimpleApplication implements ActionListener {
public static void main(String[] args) { Main app = new Main(); app.start(); }
@Override public void simpleInitApp() { inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL"); }
@Override public void simpleUpdate(float tpf) {
}
public void onAction(String name, boolean isPressed, float tpf) { throw new UnsupportedOperationException("Not supported yet."); }
void bulletCreate(){
}
}
Теперь сделаем так, чтобы при нажатии левой кнопки мыши у нас вызывался метод bulletCreate():
Код
public void onAction(String name, boolean isPressed, float tpf) { if (name.equals("MouseL") && isPressed){ bulletCreate(); } }
Дабы проверить работоспособность кода создадим BitmapText, в котором будет отображаться некая целочисленная переменная i, которая будет увеличиваться при нажатии кнопки мыши. Чтобы не мучиться с созданием текста, воспользуемся готовым шаблоном, который нас предлагает движок. Справа, в окошке под название "Палитра компонентов", есть вкладка "Interface", в которой имеется компонент "HUDText". Просто, методом drag'n'drop, перетаскиваем его в метод simpleInitApp(). Так будет выглядеть наш метод:
Код
public void simpleInitApp() { inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL"); /** Write text on the screen (HUD) */ guiNode.detachAllChildren(); guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); BitmapText helloText = new BitmapText(guiFont, false); helloText.setSize(guiFont.getCharSet().getRenderedSize()); helloText.setText("Hello World"); helloText.setLocalTranslation(300, helloText.getLineHeight(), 0); guiNode.attachChild(helloText); }
Тут у нас появляется проблема. Мы не сможем взаимодействовать с этим компонентов из другого метода. Нам необходимо, чтобы объект helloText создавался до инициализации методов. Для этого часть BitmapText helloText поставим перед методами, а в методе simpleInitApp() оставим лишь ту часть, где этот компонент инициализируется (как то каряво выразился). После всего этого наш класс будет выглядеть так:
public class Main extends SimpleApplication implements ActionListener { BitmapText helloText; public static void main(String[] args) { Main app = new Main(); app.start();
}
@Override public void simpleInitApp() { inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL"); /** Write text on the screen (HUD) */ guiNode.detachAllChildren(); guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); helloText = new BitmapText(guiFont, false); helloText.setSize(guiFont.getCharSet().getRenderedSize()); helloText.setText("Hello World"); helloText.setLocalTranslation(300, helloText.getLineHeight(), 0); guiNode.attachChild(helloText); }
@Override public void simpleUpdate(float tpf) {
}
public void onAction(String name, boolean isPressed, float tpf) { if (name.equals("MouseL") && isPressed){ bulletCreate(); } }
void bulletCreate(){
}
}
Там же, где создали helloText, создадим целочисленную переменную:
Код
int i = 0;
В методе simpleUpdate(float tpf) будем прибавлять к ней 1 и отображать ее в нашем тексте:
Код
public void simpleUpdate(float tpf) { i++; helloText.setText("i= "+i); }
Запускаем и... Все работает, можно продолжать. Теперь будем создавать сферу, которая у нас будет пулей. Но есть одна особенность, мы его будем добавлять в некий контейнер. Подробнее про ArrayList'ы вы сможете узнать из документации по библиотеки java.util. С контейнером поступим также как и текстом, т.е. создадим его вне методов, а инициализируем в методе simpleInitApp().
public class Main extends SimpleApplication implements ActionListener { BitmapText helloText; int i = 0; ArrayList<Geometry> ar; public static void main(String[] args) { Main app = new Main(); app.start(); }
@Override public void simpleInitApp() { ar = new ArrayList<Geometry>(); inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL"); /** Write text on the screen (HUD) */ guiNode.detachAllChildren(); guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); helloText = new BitmapText(guiFont, false); helloText.setSize(guiFont.getCharSet().getRenderedSize()); helloText.setLocalTranslation(300, helloText.getLineHeight(), 0); guiNode.attachChild(helloText); }
@Override public void simpleUpdate(float tpf) { i++; helloText.setText("i= "+i); }
public void onAction(String name, boolean isPressed, float tpf) { if (name.equals("MouseL") && isPressed){ bulletCreate(); } }
void bulletCreate(){
}
}
Мы создали контейнер(лист), в котором будут содержаться объекты типа Geometry. Но нашу геометрию надо на что-то "натягивать", для этого создадим объект типа Sphere. Создавать его будем по той же схеме что и контейнер:
public class Main extends SimpleApplication implements ActionListener { BitmapText helloText; int i = 0; ArrayList<Geometry> ar; Sphere s; public static void main(String[] args) { Main app = new Main(); app.start(); }
@Override public void simpleInitApp() { s = new Sphere(14,14,1); ar = new ArrayList<Geometry>(); inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL"); /** Write text on the screen (HUD) */ guiNode.detachAllChildren(); guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); helloText = new BitmapText(guiFont, false); helloText.setSize(guiFont.getCharSet().getRenderedSize()); helloText.setLocalTranslation(300, helloText.getLineHeight(), 0); guiNode.attachChild(helloText); }
@Override public void simpleUpdate(float tpf) { i++; helloText.setText("i= "+i); }
public void onAction(String name, boolean isPressed, float tpf) { if (name.equals("MouseL") && isPressed){ bulletCreate(); } }
void bulletCreate(){
}
}
Теперь будем заполнять наш контейнер сферами, но для начала, так же перед методами, создадим материал строчкой:
Код
Material m;
А в методе bulletCreate() пишем следующее:
Код
m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); ar.add(new Geometry("bullet",s)); for (Geometry g : ar){ g.setMaterial(m); rootNode.attachChild(g); }
Цикл for нужен для того, чтобы в нем мы могли обращаться непосредственно к объектам из нашего контейнера. Сейчас наш класс выглядит так:
public class Main extends SimpleApplication implements ActionListener { BitmapText helloText; int i = 0; ArrayList<Geometry> ar; Sphere s; Material m; public static void main(String[] args) { Main app = new Main(); app.start(); }
@Override public void simpleInitApp() { s = new Sphere(14,14,1); ar = new ArrayList<Geometry>(); inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL"); /** Write text on the screen (HUD) */ guiNode.detachAllChildren(); guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); helloText = new BitmapText(guiFont, false); helloText.setSize(guiFont.getCharSet().getRenderedSize()); helloText.setLocalTranslation(300, helloText.getLineHeight(), 0); guiNode.attachChild(helloText); }
@Override public void simpleUpdate(float tpf) { i++; helloText.setText("i= "+i); }
public void onAction(String name, boolean isPressed, float tpf) { if (name.equals("MouseL") && isPressed){ bulletCreate(); } }
void bulletCreate(){ m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); ar.add(new Geometry("bullet",s)); for (Geometry g : ar){ g.setMaterial(m); rootNode.attachChild(g); } }
}
Если его выполнить, то при каждом нажатии левой кнопки мыши у нас каждая новая сфера накладывается на другую. Давайте заставим их двигаться по направлению камеры. Для этого создадим новый вектор:
Код
Vector3f dir = new Vector3f();
А в метод bulletCreate() напишем:
Код
dir = cam.getDirection().normalizeLocal();
Т.е. при каждом нажатии кнопки мыши задаем ему вектор направления камеры. Вектор есть, теперь давайте сделаем так, чтобы шары двигались по его направлению. В методе simpleUpdate(float tpf) пишем:
Код
for (Geometry g : ar){ g.move(dir); }
Теперь запускаем проект и любуемся. Теперь для пущего эффекта давайте сделаем так, чтобы у наших пуль постоянно менялся цвет. В тот же цикле for пишем:
public class Main extends SimpleApplication implements ActionListener { BitmapText helloText; ArrayList<Geometry> ar; Sphere s; Material m; Vector3f dir; public static void main(String[] args) { Main app = new Main(); app.start(); }
@Override public void simpleInitApp() { s = new Sphere(14,14,1); ar = new ArrayList<Geometry>(); inputManager.addMapping("MouseL", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); inputManager.addListener(this, "MouseL"); /** Write text on the screen (HUD) */ guiNode.detachAllChildren(); guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); helloText = new BitmapText(guiFont, false); helloText.setSize(guiFont.getCharSet().getRenderedSize()); helloText.setLocalTranslation(300, helloText.getLineHeight(), 0); guiNode.attachChild(helloText); }
@Override public void simpleUpdate(float tpf) {
for (Geometry g : ar){ g.move(dir); m.setColor("Color", ColorRGBA.randomColor());
} }
public void onAction(String name, boolean isPressed, float tpf) { if (name.equals("MouseL") && isPressed){ bulletCreate(); } }
void bulletCreate(){ dir = new Vector3f(cam.getDirection().normalizeLocal()); m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); ar.add(new Geometry("bullet",s)); for (Geometry g : ar){ g.setMaterial(m); rootNode.attachChild(g); } }
}
На этом сегодняшний урок закончен. Жду ваших замечаний, пожеланий и предложений. Спасибо за внимание
Также если вы считаете, что данный материал мог быть интересен и полезен кому-то из ваших друзей, то вы бы могли посоветовать его, отправив сообщение на e-mail друга:
Игровые объявления и предложения:
Если вас заинтересовал материал «Урок по JMonkeyEngine №2 - Input», и вы бы хотели прочесть что-то на эту же тему, то вы можете воспользоваться списком схожих материалов ниже. Данный список сформирован автоматически по тематическим меткам раздела.
Предлагаются такие схожие материалы:
Если вы ведёте свой блог, микроблог, либо участвуете в какой-то популярной социальной сети, то вы можете быстро поделиться данной заметкой со своими друзьями и посетителями.
Уроки на Русском переведенные в официальной Вики: http://hub.jmonkeyengine.org/wiki/doku.php/документация:jme3_ru Если есть желающие можете перевести то что еще не успели перевести.
Это конечно все интересно, но не очень познавательно, все это есть в справке, было бы очень круто если бы уроки по jmonkeyengine ,были посвящены 2d на android, думаю со мной согласятся многие