на Главную Вход Регистрация Забыли пароль ?

skype: megainformatic, телеграм: megainformatic, онлайн-чат (megainformatic live chat), форма обратной связи

Онлайн Школа Компьютерных Наук Андрея Синицина

Онлайн Школа Компьютерных Наук Андрея Синицина - автор

Добро пожаловать в нашу школу ! Давайте вместе откроем путь к новым перспективам !!!

Создание игры на java и libgdx - урок 3 - генерация пола для сцены, взятие бонусов





enterra игра

если кликать картинку она будет последовательно меняться в размерах от 640 до 1280 пиксель.
В предыдущей статье - Создание игры на java и libgdx - урок 2 - анимация спрайта, перемещения в сцене рассматривалось как анимировать персонажа и управлять его перемещениями сцены. Мы пойдем дальше в развитии нашей игры и научимся генерировать плитки пола у сцены, а затем реализуем взятие персонажем бонусов, которые также будут генерироваться в сцене, в разных её местах. Начнём с того, что наш персонаж сейчас всегда отображает анимацию хотьбы, даже если не нажата ни одна клавиша и он не перемещается. Как это исправить ? Введем новую переменную private boolean heroMoving; в методе create инициализируем её - heroMoving = false; Добавим в обработчики keyDown и keyUp такой код - heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; В итоге обработчики примут вид -
@Override public boolean keyDown (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = true; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = true; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = true; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = true; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; } @Override public boolean keyUp (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = false; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = false; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = false; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = false; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; }
И нам остается в методе render изменить строку - inkyWalkRightCurrentFrame = inkyWalkRightAnimation.getKeyFrame(stateTime, true); она должна принять такой вид - inkyWalkRightCurrentFrame = inkyWalkRightAnimation.getKeyFrame(stateTime, heroMoving); Теперь анимация хотьбы будет работать только если нажата клавиша перемещений. Однако вы заметите такой нюанс: при начальном старте игры 1 раз анимация сработает сама по себе. А дальше уже будет работать только по нажатию клавиш - если персонаж двигается. Чтобы этого не происходило изменим строку - stateTime += Gdx.graphics.getDeltaTime(); на такой код - if ( heroMoving ) { stateTime += Gdx.graphics.getDeltaTime(); } Таким образом таймер stateTime будет обновляться только если персонаж перемещается по нажатию клавиш wasd или стрелок. В остальных случаях он обновляться не будет и потому даже при начальном старте игры ничего происходить не будет. enterra игра
если кликать картинку она будет последовательно меняться в размерах от 640 до 1280 пиксель.
Если со всем этим вы разобрались, будем двигаться дальше. Перейдем к генерации плиток пола. Для пола будут использоваться 3 вида плиток. 1 тот что уже есть и еще 2 таких - enterra игра - плитки для пола - вид 1 enterra игра - плитки для пола - вид 2 Сохраните их себе, поместите в папки \my_java_game\assets\assets\textures\scenes\scene_1\ \my_java_game\out\artifacts\my_java_game_jar\assets\assets\textures\scenes\scene_1\ проекта и будем двигаться дальше Переменную Texture img; везде по коду переименуем в scene1FloorTexture для этого удобно воспользоваться функцией автозамены - Edit > Find > Replace Для вывода 2х новых видов плиток пола добавим такой код: в метод create: после строки - scene1FloorTexture = new Texture("assets/textures/scenes/scene_1/floor3.jpg"); добавим - scene1Floor2Texture = new Texture("assets/textures/scenes/scene_1/floor_1.jpg"); scene1Floor3Texture = new Texture("assets/textures/scenes/scene_1/floor_2.jpg"); и поскольку у нас переменные scene1Floor2Texture scene1Floor3Texture не объявлены. Объявим их - Texture scene1Floor2Texture; Texture scene1Floor3Texture; Также нужно не забыть освободить память выделенную для загрузки данных ресурсов - в методе dispose добавим код - scene1Floor2Texture.dispose(); scene1Floor3Texture.dispose(); Для генерации плиток пола вызовом из метода create - т. е. однократно при старте игры напишем такой метод - private void initScene1Floor() { } и обязательно добавим его вызов в методе create: public void create () { //... initScene1Floor(); } Прежде чем мы напишем код для метода initScene1Floor нужно выполнить ряд подготовительных действий. внутри кода класса MyJavaGame объявим класс class EnterraFloor { public Vector2 pos; public int type; }; это будет нужно для того, чтобы задавать координаты элементов для плиток пола и их вид. Т. е. переменная pos как раз будет отвечать за координаты в сцене, а type - определять вид плитки. Далее нужно объявить переменные EnterraFloor[] scene1FloorElements; private int scene1FloorElementsNum; scene1FloorElements будет представлять динамический массив из элементов EnterraFloor, а в переменной scene1FloorElementsNum мы будем задавать размер данного массива - т. е. сколько элементов будет в нём. Напишем реализацию метода initScene1Floor private void initScene1Floor() { int floorStep = 512; scene1FloorElementsNum = 49; int floorElementsRows = (int)Math.floor(Math.sqrt(scene1FloorElementsNum)); int floorElementsCols = scene1FloorElementsNum / floorElementsRows; Vector2 initPoint = new Vector2(0, 0); initPoint.x = -floorStep*(floorElementsCols-(floorElementsCols-3)); initPoint.y = -floorStep*(floorElementsRows-(floorElementsCols-3)); scene1FloorElements = new EnterraFloor[scene1FloorElementsNum]; MathUtils.random.setSeed(System.currentTimeMillis()); for (int i = 0; i < scene1FloorElementsNum; i++) { scene1FloorElements[i] = new EnterraFloor(); } int itemIndex = 0; for (int i = 0; i < floorElementsRows; i++) { for (int j = 0; j < floorElementsCols; j++) { scene1FloorElements[itemIndex].pos = new Vector2(initPoint.x, initPoint.y); scene1FloorElements[itemIndex].type = MathUtils.random(1, 3); initPoint.x = initPoint.x + floorStep; if ( initPoint.x > (floorStep*2-1) ) initPoint.x = -floorStep*(floorElementsCols-2); itemIndex++; } initPoint.y = initPoint.y + floorStep; if ( initPoint.y > (floorStep*2-1) ) initPoint.y = -floorStep*(floorElementsRows-2); } } В вывод элементов пола в сцене - private void drawFloor() { for (int i = 0; i < scene1FloorElementsNum; i++) { if ( scene1FloorElements[i].type == 1 ) batch.draw(scene1FloorTexture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 2 ) batch.draw(scene1Floor2Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 3 ) batch.draw(scene1Floor3Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); } } вызов drawFloor добавим в методе render перед строкой кода - batch.draw(scene1FloorTexture, sceneScrollPos.x, sceneScrollPos.y); в итоде эта часть кода будет выглядеть так: batch.begin(); drawFloor(); //мы добавили вывод пола сюда, потому что сначала выводим пол, а потом остальные объекты в сцене batch.draw(scene1FloorTexture, sceneScrollPos.x, sceneScrollPos.y); batch.draw(inkyWalkRightCurrentFrame, 560, 300); font.draw(batch, " hx: " + (int)Math.floor(sceneScrollPos.x) + " hy: "+(int)Math.floor(sceneScrollPos.y), 10, 15); batch.end(); Ваша игра теперь будет выглядеть так - полный код файла \my_java_game\core\src\com\mygdx\game\MyJavaGame.java у вас должен выглядеть так -
package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.ScreenUtils; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.Input.Keys; public class MyJavaGame extends ApplicationAdapter implements InputProcessor { SpriteBatch batch; Texture scene1FloorTexture; Texture scene1Floor2Texture; Texture scene1Floor3Texture; public Animation inkyWalkRightAnimation; Texture inkyWalkRightTextureAnim; private static final int INKY_WALK_FRAME_COLS = 8, INKY_WALK_FRAME_ROWS = 6; private float stateTime; Vector2 sceneScrollPos; private boolean heroMoveLeft; private boolean heroMoveRight; private boolean heroMoveUp; private boolean heroMoveDown; private float elapsedTime; private float MoveSpeed; BitmapFont font; private boolean heroMoving; class EnterraFloor { public Vector2 pos; public int type; }; EnterraFloor[] scene1FloorElements; private int scene1FloorElementsNum; @Override public void create () { batch = new SpriteBatch(); scene1FloorTexture = new Texture("assets/textures/scenes/scene_1/floor3.jpg"); scene1Floor2Texture = new Texture("assets/textures/scenes/scene_1/floor_1.jpg"); scene1Floor3Texture = new Texture("assets/textures/scenes/scene_1/floor_2.jpg"); inkyWalkRightTextureAnim = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/inky_walk_right.png")); //inkyWalkRightTextureAnim = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/inky_walk_anim_test_2.png")); TextureRegion[][] tmp = TextureRegion.split(inkyWalkRightTextureAnim, inkyWalkRightTextureAnim.getWidth() / INKY_WALK_FRAME_COLS, inkyWalkRightTextureAnim.getHeight() / INKY_WALK_FRAME_ROWS); TextureRegion[] inkyWalkRighFrames = new TextureRegion[INKY_WALK_FRAME_COLS * INKY_WALK_FRAME_ROWS]; int index = 0; for (int i = 0; i < INKY_WALK_FRAME_ROWS; i++) { for (int j = 0; j < INKY_WALK_FRAME_COLS; j++) { inkyWalkRighFrames[index++] = tmp[i][j]; } } inkyWalkRightAnimation = new Animation(0.03f, inkyWalkRighFrames); stateTime = 0.0f; sceneScrollPos = new Vector2(0, 0); heroMoveLeft = false; heroMoveRight = false; heroMoveUp = false; heroMoveDown = false; elapsedTime = 0.0f; MoveSpeed = 225.5f; font = new BitmapFont(); font.setColor(0.9f, 0.9f, 0.7f, 1.0f); heroMoving = false; Gdx.input.setInputProcessor(this); initScene1Floor(); } private void MoveHero() { if ( heroMoveLeft ) { sceneScrollPos.x = sceneScrollPos.x + elapsedTime * MoveSpeed; } if ( heroMoveRight ) { sceneScrollPos.x = sceneScrollPos.x - elapsedTime * MoveSpeed; } if ( heroMoveUp ) { sceneScrollPos.y = sceneScrollPos.y - elapsedTime * MoveSpeed; } if ( heroMoveDown ) { sceneScrollPos.y = sceneScrollPos.y + elapsedTime * MoveSpeed; } } @Override public boolean keyDown (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = true; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = true; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = true; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = true; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; } @Override public boolean keyUp (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = false; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = false; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = false; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = false; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; } @Override public boolean keyTyped (char character) { return false; } @Override public boolean scrolled (float amountX, float amountY) { return false; } public boolean touchDragged (int screenX, int screenY, int pointer) { return false; } @Override public boolean touchUp (int screenX, int screenY, int pointer, int button) { return false; } public boolean touchDown (int screenX, int screenY, int pointer, int button) { return false; } public boolean mouseMoved (int screenX, int screenY) { return false; } private void initScene1Floor() { int floorStep = 512; scene1FloorElementsNum = 49; int floorElementsRows = (int)Math.floor(Math.sqrt(scene1FloorElementsNum)); int floorElementsCols = scene1FloorElementsNum / floorElementsRows; Vector2 initPoint = new Vector2(0, 0); initPoint.x = -floorStep*(floorElementsCols-(floorElementsCols-3)); initPoint.y = -floorStep*(floorElementsRows-(floorElementsCols-3)); scene1FloorElements = new EnterraFloor[scene1FloorElementsNum]; MathUtils.random.setSeed(System.currentTimeMillis()); for (int i = 0; i < scene1FloorElementsNum; i++) { scene1FloorElements[i] = new EnterraFloor(); } int itemIndex = 0; for (int i = 0; i < floorElementsRows; i++) { for (int j = 0; j < floorElementsCols; j++) { scene1FloorElements[itemIndex].pos = new Vector2(initPoint.x, initPoint.y); scene1FloorElements[itemIndex].type = MathUtils.random(1, 3); initPoint.x = initPoint.x + floorStep; if ( initPoint.x > (floorStep*2-1) ) initPoint.x = -floorStep*(floorElementsCols-2); itemIndex++; } initPoint.y = initPoint.y + floorStep; if ( initPoint.y > (floorStep*2-1) ) initPoint.y = -floorStep*(floorElementsRows-2); } } private void drawFloor() { for (int i = 0; i < scene1FloorElementsNum; i++) { if ( scene1FloorElements[i].type == 1 ) batch.draw(scene1FloorTexture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 2 ) batch.draw(scene1Floor2Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 3 ) batch.draw(scene1Floor3Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); } } TextureRegion inkyWalkRightCurrentFrame; @Override public void render () { ScreenUtils.clear(0.0f, 0.0f, 0.0f, 1.0f); if ( heroMoving ) { stateTime += Gdx.graphics.getDeltaTime(); } elapsedTime = Gdx.graphics.getDeltaTime(); inkyWalkRightCurrentFrame = inkyWalkRightAnimation.getKeyFrame(stateTime, heroMoving); MoveHero(); batch.begin(); drawFloor(); batch.draw(scene1FloorTexture, sceneScrollPos.x, sceneScrollPos.y); batch.draw(inkyWalkRightCurrentFrame, 560, 300); font.draw(batch, " hx: " + (int)Math.floor(sceneScrollPos.x) + " hy: "+(int)Math.floor(sceneScrollPos.y), 10, 15); batch.end(); if(Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) Gdx.app.exit(); } @Override public void dispose () { batch.dispose(); scene1FloorTexture.dispose(); inkyWalkRightTextureAnim.dispose(); font.dispose(); scene1Floor2Texture.dispose(); scene1Floor3Texture.dispose(); } }
Поясню некоторые моменты. scene1FloorElementsNum = 49; //пол у нас будет состоять из 49 плиток в сцене. 7 х 7 т. е. 7 в длину и 7 в ширину. int floorStep = 512; //задает шаг плитки в пикселях. Так как все плитки пола у нас //квадратные 512х512 пикселей. строки int floorElementsRows = (int)Math.floor(Math.sqrt(scene1FloorElementsNum)); int floorElementsCols = scene1FloorElementsNum / floorElementsRows; вычисляют количество элементов по вертикали и горизонтали. Если задать в качестве значения scene1FloorElementsNum число из которого можно извлечь квадратный корень без остатка, то можем вывести в сцене любое удовлятворяющее данному условию количество плиток - от 4 до бесконечности (в разумных пределах конечно). Попробуйте проверить этот момент. Вообще для лучшего понимания кода советую его не просто копи-пастить, а пробовать изменять для своих целей, но так, чтобы вы понимали что делаете. Чтобы персонаж быстрее или медленее перемещался в сцене - меняем значение переменной MoveSpeed = 225.5f; Например попробуйте изменить на 1500.0f Скорость движения я упомянул тут не случайно, т. к. с быстрой скоростью вам будет легче быстро осмотреть всю сцену ))) и да, метод initScene1Floor сейчас не является универсальным. Для 64 плиток будет все ок, а вот для 4 - нет. Попробуйте самостоятельно выяснить в чем проблема и исправить её. Остальной код пояснять не буду, попробуйте разобраться сами что и как он делает. Кратко можно сказать следующее: плитки пола 3-х видов генерируются случайно и пол будет создан из A x B элементов по горизонтали и вертикали. Причем число scene1FloorElementsNum нужно задавать именно как квадрат числа плиток для пола по вертикали или горизонтали. Также, поскольку координата каждой плитки при выводе в методе drawFloor вычисляется относительно координат сцены sceneScrollPos то это как раз и дает эффект скролла плиток пола при движениях персонажа по вертикали, горизонтали или диагонали. Далее мы изучим как сгенерировать в сцене бонусы для пуль и реализовать их сбор персонажем. В качестве бонусов для пуль мы используем две такие картинки - enterra игра - анимированный бонус для зеленых пуль enterra игра - анимированный бонус для красных пуль Скачайте их себе и разместите в папках \my_java_game\assets\assets\textures\scenes\scene_1\ \my_java_game\out\artifacts\my_java_game_jar\assets\assets\textures\scenes\scene_1\ проекта При контакте с данными элементами персонаж игрока будет получать данный вид пуль. Реализация контакта происходит за счёт использования объектов Rectangle и метода overlap. Т. е. для объекта персонажа и бонусов нужно определить области Rectangle и методом overlap проверять когда области пересекаются. Так мы сможем реализовать столкновение персонажа с бонусами пуль для их сбора. А в дальнейшем по-аналогии будут реализованы и столкновения с пулями, которые персонаж Инки будет выстреливать в Бо-Босса и наоборот - столкновения персонажа Инки с пулями Бо-Босса. Для бонусов добавим такой код - Vector2[] scene1BulletBonuses; //массив который будет хранить координаты бонусов в сцене int[] scene1BulletBonusesType; //тут будут храниться типы этих бонусов private int scene1BulletBonusesNum; //будем задавать количество бонусов Rectangle[] scene1BulletBonusesCollisionRects; //определим области столкновений для бонусов Rectangle inkyCollisionRect; //область для столкновений с персонажем Инки создадим метод private void generateBulletBonuses() { } для генерации бонусов пуль с таким кодом - private void generateBulletBonuses() { scene1BulletBonusesNum = 6; scene1BulletBonuses = new Vector2[scene1BulletBonusesNum]; scene1BulletBonusesType = new int[scene1BulletBonusesNum]; scene1BulletBonusesCollisionRects = new Rectangle[scene1BulletBonusesNum]; for (int i = 0; i < scene1BulletBonusesNum/2; i++) { scene1BulletBonuses[i] = new Vector2(0, 0); scene1BulletBonuses[i].x = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonuses[i].y = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonusesType[i] = 1; //red bullet bonus scene1BulletBonusesCollisionRects[i] = new Rectangle(0, 0, 30, 30); scene1BulletBonusesCollisionRects[i].x = scene1BulletBonuses[i].x; scene1BulletBonusesCollisionRects[i].y = scene1BulletBonuses[i].y; } for (int i = scene1BulletBonusesNum/2; i < scene1BulletBonusesNum; i++) { scene1BulletBonuses[i] = new Vector2(0, 0); scene1BulletBonuses[i].x = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonuses[i].y = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonusesType[i] = 2; //green bullet bonus scene1BulletBonusesCollisionRects[i] = new Rectangle(0, 0, 30, 30); scene1BulletBonusesCollisionRects[i].x = scene1BulletBonuses[i].x; scene1BulletBonusesCollisionRects[i].y = scene1BulletBonuses[i].y; } } метод generateRandomNum опишем так - private int generateRandomNum(int min, int max) { return min + (int) (Math.random() * max); } вызов generateBulletBonuses() добавим в методе create: public void create () { //... generateBulletBonuses(); } для отрисовки анимированных бонусов добавим такие переменные - поля класса MyJavaGame Texture getRedBulletBonusTexture; public Animation redBulletBonusAnimation; private static final int BULLET_BONUS_FRAME_COLS = 4, BULLET_BONUS_FRAME_ROWS = 4; Texture getGreenBulletBonusTexture; public Animation greenBulletBonusAnimation; и загрузим данные в эти поля - в методе create добавим код - getRedBulletBonusTexture = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/false.png")); tmp = TextureRegion.split(getRedBulletBonusTexture, getRedBulletBonusTexture.getWidth() / BULLET_BONUS_FRAME_COLS, getRedBulletBonusTexture.getHeight() / BULLET_BONUS_FRAME_ROWS); TextureRegion[] getRedBulletBonusFrames = new TextureRegion[BULLET_BONUS_FRAME_COLS * BULLET_BONUS_FRAME_ROWS]; index = 0; for (int i = 0; i < BULLET_BONUS_FRAME_ROWS; i++) { for (int j = 0; j < BULLET_BONUS_FRAME_COLS; j++) { getRedBulletBonusFrames[index++] = tmp[i][j]; } } redBulletBonusAnimation = new Animation(0.04f, getRedBulletBonusFrames); getGreenBulletBonusTexture = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/true.png")); tmp = TextureRegion.split(getGreenBulletBonusTexture, getGreenBulletBonusTexture.getWidth() / BULLET_BONUS_FRAME_COLS, getGreenBulletBonusTexture.getHeight() / BULLET_BONUS_FRAME_ROWS); TextureRegion[] getGreenBulletBonusFrames = new TextureRegion[BULLET_BONUS_FRAME_COLS * BULLET_BONUS_FRAME_ROWS]; index = 0; for (int i = 0; i < BULLET_BONUS_FRAME_ROWS; i++) { for (int j = 0; j < BULLET_BONUS_FRAME_COLS; j++) { getGreenBulletBonusFrames[index++] = tmp[i][j]; } } greenBulletBonusAnimation = new Animation(0.04f, getGreenBulletBonusFrames); для вывода пуль в сцене добавим метод - private void drawBulletBonuses() { for (int i = 0; i < scene1BulletBonusesNum; i++) { if ( scene1BulletBonusesType[i] == 1) { batch.draw(redBulletBonusCurrentFrame, sceneScrollPos.x+scene1BulletBonuses[i].x, sceneScrollPos.y+scene1BulletBonuses[i].y); } if ( scene1BulletBonusesType[i] == 2) { batch.draw(greenBulletBonusCurrentFrame, sceneScrollPos.x+scene1BulletBonuses[i].x, sceneScrollPos.y+scene1BulletBonuses[i].y); } } } и сделаем его вызов в методе render разместив после строки - drawFloor(); drawBulletBonuses(); //т. к. бонусы пуль должны быть под ногами персонажа и над полом сцены Еще нужно добавить переменные для хранения текущего кадра анимации у бонусов - TextureRegion redBulletBonusCurrentFrame; TextureRegion greenBulletBonusCurrentFrame; и код для выставления текущего кадра - redBulletBonusCurrentFrame = redBulletBonusAnimation.getKeyFrame(stateTime, true); greenBulletBonusCurrentFrame = greenBulletBonusAnimation.getKeyFrame(stateTime, true); в методе render. Полный код файла \my_java_game\core\src\com\mygdx\game\MyJavaGame.java у вас сейчас должен выглядеть так:
package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.utils.ScreenUtils; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.Input.Keys; public class MyJavaGame extends ApplicationAdapter implements InputProcessor { SpriteBatch batch; Texture scene1FloorTexture; Texture scene1Floor2Texture; Texture scene1Floor3Texture; public Animation inkyWalkRightAnimation; Texture inkyWalkRightTextureAnim; private static final int INKY_WALK_FRAME_COLS = 8, INKY_WALK_FRAME_ROWS = 6; private float stateTime; private float stateTime2; Vector2 sceneScrollPos; private boolean heroMoveLeft; private boolean heroMoveRight; private boolean heroMoveUp; private boolean heroMoveDown; private float elapsedTime; private float MoveSpeed; BitmapFont font; private boolean heroMoving; class EnterraFloor { public Vector2 pos; public int type; }; EnterraFloor[] scene1FloorElements; private int scene1FloorElementsNum; Vector2[] scene1BulletBonuses; int[] scene1BulletBonusesType; private int scene1BulletBonusesNum; Rectangle[] scene1BulletBonusesCollisionRects; Rectangle inkyCollisionRect; Texture getRedBulletBonusTexture; public Animation redBulletBonusAnimation; private static final int BULLET_BONUS_FRAME_COLS = 4, BULLET_BONUS_FRAME_ROWS = 4; Texture getGreenBulletBonusTexture; public Animation greenBulletBonusAnimation; private int generateRandomNum(int min, int max) { return min + (int) (Math.random() * max); } private void generateBulletBonuses() { scene1BulletBonusesNum = 6; scene1BulletBonuses = new Vector2[scene1BulletBonusesNum]; scene1BulletBonusesType = new int[scene1BulletBonusesNum]; scene1BulletBonusesCollisionRects = new Rectangle[scene1BulletBonusesNum]; for (int i = 0; i < scene1BulletBonusesNum/2; i++) { scene1BulletBonuses[i] = new Vector2(0, 0); scene1BulletBonuses[i].x = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonuses[i].y = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonusesType[i] = 1; //red bullet bonus scene1BulletBonusesCollisionRects[i] = new Rectangle(0, 0, 30, 30); scene1BulletBonusesCollisionRects[i].x = scene1BulletBonuses[i].x; scene1BulletBonusesCollisionRects[i].y = scene1BulletBonuses[i].y; } for (int i = scene1BulletBonusesNum/2; i < scene1BulletBonusesNum; i++) { scene1BulletBonuses[i] = new Vector2(0, 0); scene1BulletBonuses[i].x = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonuses[i].y = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonusesType[i] = 2; //green bullet bonus scene1BulletBonusesCollisionRects[i] = new Rectangle(0, 0, 30, 30); scene1BulletBonusesCollisionRects[i].x = scene1BulletBonuses[i].x; scene1BulletBonusesCollisionRects[i].y = scene1BulletBonuses[i].y; } } @Override public void create () { batch = new SpriteBatch(); scene1FloorTexture = new Texture("assets/textures/scenes/scene_1/floor3.jpg"); scene1Floor2Texture = new Texture("assets/textures/scenes/scene_1/floor_1.jpg"); scene1Floor3Texture = new Texture("assets/textures/scenes/scene_1/floor_2.jpg"); inkyWalkRightTextureAnim = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/inky_walk_right.png")); //inkyWalkRightTextureAnim = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/inky_walk_anim_test_2.png")); TextureRegion[][] tmp = TextureRegion.split(inkyWalkRightTextureAnim, inkyWalkRightTextureAnim.getWidth() / INKY_WALK_FRAME_COLS, inkyWalkRightTextureAnim.getHeight() / INKY_WALK_FRAME_ROWS); TextureRegion[] inkyWalkRighFrames = new TextureRegion[INKY_WALK_FRAME_COLS * INKY_WALK_FRAME_ROWS]; int index = 0; for (int i = 0; i < INKY_WALK_FRAME_ROWS; i++) { for (int j = 0; j < INKY_WALK_FRAME_COLS; j++) { inkyWalkRighFrames[index++] = tmp[i][j]; } } inkyWalkRightAnimation = new Animation(0.03f, inkyWalkRighFrames); stateTime = 0.0f; stateTime2 = 0.0f; sceneScrollPos = new Vector2(0, 0); heroMoveLeft = false; heroMoveRight = false; heroMoveUp = false; heroMoveDown = false; elapsedTime = 0.0f; MoveSpeed = 1500.0f;//225.5f; font = new BitmapFont(); font.setColor(0.9f, 0.9f, 0.7f, 1.0f); heroMoving = false; Gdx.input.setInputProcessor(this); initScene1Floor(); generateBulletBonuses(); getRedBulletBonusTexture = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/false.png")); tmp = TextureRegion.split(getRedBulletBonusTexture, getRedBulletBonusTexture.getWidth() / BULLET_BONUS_FRAME_COLS, getRedBulletBonusTexture.getHeight() / BULLET_BONUS_FRAME_ROWS); TextureRegion[] getRedBulletBonusFrames = new TextureRegion[BULLET_BONUS_FRAME_COLS * BULLET_BONUS_FRAME_ROWS]; index = 0; for (int i = 0; i < BULLET_BONUS_FRAME_ROWS; i++) { for (int j = 0; j < BULLET_BONUS_FRAME_COLS; j++) { getRedBulletBonusFrames[index++] = tmp[i][j]; } } redBulletBonusAnimation = new Animation(0.04f, getRedBulletBonusFrames); getGreenBulletBonusTexture = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/true.png")); tmp = TextureRegion.split(getGreenBulletBonusTexture, getGreenBulletBonusTexture.getWidth() / BULLET_BONUS_FRAME_COLS, getGreenBulletBonusTexture.getHeight() / BULLET_BONUS_FRAME_ROWS); TextureRegion[] getGreenBulletBonusFrames = new TextureRegion[BULLET_BONUS_FRAME_COLS * BULLET_BONUS_FRAME_ROWS]; index = 0; for (int i = 0; i < BULLET_BONUS_FRAME_ROWS; i++) { for (int j = 0; j < BULLET_BONUS_FRAME_COLS; j++) { getGreenBulletBonusFrames[index++] = tmp[i][j]; } } greenBulletBonusAnimation = new Animation(0.04f, getGreenBulletBonusFrames); } private void MoveHero() { if ( heroMoveLeft ) { sceneScrollPos.x = sceneScrollPos.x + elapsedTime * MoveSpeed; } if ( heroMoveRight ) { sceneScrollPos.x = sceneScrollPos.x - elapsedTime * MoveSpeed; } if ( heroMoveUp ) { sceneScrollPos.y = sceneScrollPos.y - elapsedTime * MoveSpeed; } if ( heroMoveDown ) { sceneScrollPos.y = sceneScrollPos.y + elapsedTime * MoveSpeed; } } @Override public boolean keyDown (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = true; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = true; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = true; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = true; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; } @Override public boolean keyUp (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = false; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = false; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = false; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = false; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; } @Override public boolean keyTyped (char character) { return false; } @Override public boolean scrolled (float amountX, float amountY) { return false; } public boolean touchDragged (int screenX, int screenY, int pointer) { return false; } @Override public boolean touchUp (int screenX, int screenY, int pointer, int button) { return false; } public boolean touchDown (int screenX, int screenY, int pointer, int button) { return false; } public boolean mouseMoved (int screenX, int screenY) { return false; } private void initScene1Floor() { int floorStep = 512; scene1FloorElementsNum = 64;//49; int floorElementsRows = (int)Math.floor(Math.sqrt(scene1FloorElementsNum)); int floorElementsCols = scene1FloorElementsNum / floorElementsRows; Vector2 initPoint = new Vector2(0, 0); initPoint.x = -floorStep*(floorElementsCols-(floorElementsCols-3)); initPoint.y = -floorStep*(floorElementsRows-(floorElementsCols-3)); scene1FloorElements = new EnterraFloor[scene1FloorElementsNum]; MathUtils.random.setSeed(System.currentTimeMillis()); for (int i = 0; i < scene1FloorElementsNum; i++) { scene1FloorElements[i] = new EnterraFloor(); } int itemIndex = 0; for (int i = 0; i < floorElementsRows; i++) { for (int j = 0; j < floorElementsCols; j++) { scene1FloorElements[itemIndex].pos = new Vector2(initPoint.x, initPoint.y); scene1FloorElements[itemIndex].type = MathUtils.random(1, 3); initPoint.x = initPoint.x + floorStep; if ( initPoint.x > (floorStep*2-1) ) initPoint.x = -floorStep*(floorElementsCols-2); itemIndex++; } initPoint.y = initPoint.y + floorStep; if ( initPoint.y > (floorStep*2-1) ) initPoint.y = -floorStep*(floorElementsRows-2); } } private void drawFloor() { for (int i = 0; i < scene1FloorElementsNum; i++) { if ( scene1FloorElements[i].type == 1 ) batch.draw(scene1FloorTexture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 2 ) batch.draw(scene1Floor2Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 3 ) batch.draw(scene1Floor3Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); } } TextureRegion inkyWalkRightCurrentFrame; private void drawBulletBonuses() { for (int i = 0; i < scene1BulletBonusesNum; i++) { if ( scene1BulletBonusesType[i] == 1) { batch.draw(redBulletBonusCurrentFrame, sceneScrollPos.x+scene1BulletBonuses[i].x, sceneScrollPos.y+scene1BulletBonuses[i].y); } if ( scene1BulletBonusesType[i] == 2) { batch.draw(greenBulletBonusCurrentFrame, sceneScrollPos.x+scene1BulletBonuses[i].x, sceneScrollPos.y+scene1BulletBonuses[i].y); } } } TextureRegion redBulletBonusCurrentFrame; TextureRegion greenBulletBonusCurrentFrame; @Override public void render () { ScreenUtils.clear(0.0f, 0.0f, 0.0f, 1.0f); if ( heroMoving ) { stateTime += Gdx.graphics.getDeltaTime(); } elapsedTime = Gdx.graphics.getDeltaTime(); inkyWalkRightCurrentFrame = inkyWalkRightAnimation.getKeyFrame(stateTime, heroMoving); stateTime2 += Gdx.graphics.getDeltaTime(); redBulletBonusCurrentFrame = redBulletBonusAnimation.getKeyFrame(stateTime2, true); greenBulletBonusCurrentFrame = greenBulletBonusAnimation.getKeyFrame(stateTime2, true); MoveHero(); batch.begin(); drawFloor(); drawBulletBonuses(); batch.draw(scene1FloorTexture, sceneScrollPos.x, sceneScrollPos.y); batch.draw(inkyWalkRightCurrentFrame, 560, 300); font.draw(batch, " hx: " + (int)Math.floor(sceneScrollPos.x) + " hy: "+(int)Math.floor(sceneScrollPos.y), 10, 15); batch.end(); if(Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) Gdx.app.exit(); } @Override public void dispose () { batch.dispose(); scene1FloorTexture.dispose(); inkyWalkRightTextureAnim.dispose(); font.dispose(); scene1Floor2Texture.dispose(); scene1Floor3Texture.dispose(); } }
Перемещаясь по сцене Вы увидите в случайных местах анимированные бонусы пуль. Вот как это может выглядеть - Всего в сцене должно быть 6 бонусов пуль - 3 зеленых и 3 красных. И обратите внимание, что я добавил переменную stateTime2 и использую её в строках кода - redBulletBonusCurrentFrame = redBulletBonusAnimation.getKeyFrame(stateTime2, true); greenBulletBonusCurrentFrame = greenBulletBonusAnimation.getKeyFrame(stateTime2, true); поскольку stateTime обновляется лишь когда персонаж перемещается. Нам осталось реализовать проверку столкновений персонажа с бонусами пуль для их сбора. Для проверки столкновений с бонусами добавим такой метод - private void testPlayerCollisionWithBulletBonuses() { Rectangle bulletBonusRect = new Rectangle(0, 0, 30, 30); for (int i = 0; i < scene1BulletBonusesNum; i++) { bulletBonusRect.x = sceneScrollPos.x + scene1BulletBonusesCollisionRects[i].x; bulletBonusRect.y = sceneScrollPos.y + scene1BulletBonusesCollisionRects[i].y; if ( inkyCollisionRect.overlaps(bulletBonusRect)) { if ( scene1BulletBonusesType[i] > 0 ) { if ( inkyGetBulletBonusType == scene1BulletBonusesType[i]) inkyHaveBullets += 50; else inkyHaveBullets = 50; inkyGetBulletBonusType = scene1BulletBonusesType[i]; if ( scene1BulletBonusesType[i] == 1 ) { //redBulletBonusSoundPlayId = redBulletBonusSound.play(); //redBulletBonusSound.setVolume(redBulletBonusSoundPlayId, soundVolume); } if ( scene1BulletBonusesType[i] == 2 ) { //greenBulletBonusSoundPlayId = greenBulletBonusSound.play(); //greenBulletBonusSound.setVolume(greenBulletBonusSoundPlayId, soundVolume); } scene1BulletBonusesType[i] = 0; //bullet is get by player inkyGetBulletBonusCount++; int totalGetBulletBonusCount = inkyGetBulletBonusCount;// + boBossGetBulletBonusCount; if ( totalGetBulletBonusCount == scene1BulletBonusesNum) { generateBulletBonuses(); } } } } } Также нужно добавить поля - private int inkyGetBulletBonusType; private int inkyGetBulletBonusCount; private int inkyHaveBullets; и в методе create инициализировать их: inkyGetBulletBonusType = 0; inkyGetBulletBonusCount = 0; inkyHaveBullets = 0; А вызов метода testPlayerCollisionWithBulletBonuses() добавить в методе render. Также в методе create добавить строки: inkyCollisionRect = new Rectangle(); inkyCollisionRect.x = 500;//inkyScreenPos.x; inkyCollisionRect.y = 350;//inkyScreenPos.y; inkyCollisionRect.width = 20; inkyCollisionRect.height = 70; Полный код игры у вас теперь должен выглядеть так -
package com.mygdx.game; import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.utils.ScreenUtils; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.Input.Keys; public class MyJavaGame extends ApplicationAdapter implements InputProcessor { SpriteBatch batch; Texture scene1FloorTexture; Texture scene1Floor2Texture; Texture scene1Floor3Texture; public Animation inkyWalkRightAnimation; Texture inkyWalkRightTextureAnim; private static final int INKY_WALK_FRAME_COLS = 8, INKY_WALK_FRAME_ROWS = 6; private float stateTime; private float stateTime2; Vector2 sceneScrollPos; private boolean heroMoveLeft; private boolean heroMoveRight; private boolean heroMoveUp; private boolean heroMoveDown; private float elapsedTime; private float MoveSpeed; BitmapFont font; private boolean heroMoving; class EnterraFloor { public Vector2 pos; public int type; }; EnterraFloor[] scene1FloorElements; private int scene1FloorElementsNum; Vector2[] scene1BulletBonuses; int[] scene1BulletBonusesType; private int scene1BulletBonusesNum; Rectangle[] scene1BulletBonusesCollisionRects; Rectangle inkyCollisionRect; Texture getRedBulletBonusTexture; public Animation redBulletBonusAnimation; private static final int BULLET_BONUS_FRAME_COLS = 4, BULLET_BONUS_FRAME_ROWS = 4; Texture getGreenBulletBonusTexture; public Animation greenBulletBonusAnimation; private int generateRandomNum(int min, int max) { return min + (int) (Math.random() * max); } private int inkyGetBulletBonusType; private int inkyGetBulletBonusCount; private int inkyHaveBullets; private void generateBulletBonuses() { scene1BulletBonusesNum = 6; scene1BulletBonuses = new Vector2[scene1BulletBonusesNum]; scene1BulletBonusesType = new int[scene1BulletBonusesNum]; scene1BulletBonusesCollisionRects = new Rectangle[scene1BulletBonusesNum]; for (int i = 0; i < scene1BulletBonusesNum/2; i++) { scene1BulletBonuses[i] = new Vector2(0, 0); scene1BulletBonuses[i].x = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonuses[i].y = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonusesType[i] = 1; //red bullet bonus scene1BulletBonusesCollisionRects[i] = new Rectangle(0, 0, 30, 30); scene1BulletBonusesCollisionRects[i].x = scene1BulletBonuses[i].x; scene1BulletBonusesCollisionRects[i].y = scene1BulletBonuses[i].y; } for (int i = scene1BulletBonusesNum/2; i < scene1BulletBonusesNum; i++) { scene1BulletBonuses[i] = new Vector2(0, 0); scene1BulletBonuses[i].x = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonuses[i].y = -generateRandomNum(0, 12) * 128 + generateRandomNum(0, 12) * 128; scene1BulletBonusesType[i] = 2; //green bullet bonus scene1BulletBonusesCollisionRects[i] = new Rectangle(0, 0, 30, 30); scene1BulletBonusesCollisionRects[i].x = scene1BulletBonuses[i].x; scene1BulletBonusesCollisionRects[i].y = scene1BulletBonuses[i].y; } } @Override public void create () { batch = new SpriteBatch(); scene1FloorTexture = new Texture("assets/textures/scenes/scene_1/floor3.jpg"); scene1Floor2Texture = new Texture("assets/textures/scenes/scene_1/floor_1.jpg"); scene1Floor3Texture = new Texture("assets/textures/scenes/scene_1/floor_2.jpg"); inkyWalkRightTextureAnim = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/inky_walk_right.png")); //inkyWalkRightTextureAnim = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/inky_walk_anim_test_2.png")); TextureRegion[][] tmp = TextureRegion.split(inkyWalkRightTextureAnim, inkyWalkRightTextureAnim.getWidth() / INKY_WALK_FRAME_COLS, inkyWalkRightTextureAnim.getHeight() / INKY_WALK_FRAME_ROWS); TextureRegion[] inkyWalkRighFrames = new TextureRegion[INKY_WALK_FRAME_COLS * INKY_WALK_FRAME_ROWS]; int index = 0; for (int i = 0; i < INKY_WALK_FRAME_ROWS; i++) { for (int j = 0; j < INKY_WALK_FRAME_COLS; j++) { inkyWalkRighFrames[index++] = tmp[i][j]; } } inkyWalkRightAnimation = new Animation(0.03f, inkyWalkRighFrames); stateTime = 0.0f; stateTime2 = 0.0f; sceneScrollPos = new Vector2(0, 0); heroMoveLeft = false; heroMoveRight = false; heroMoveUp = false; heroMoveDown = false; elapsedTime = 0.0f; MoveSpeed = 1500.0f;//225.5f; font = new BitmapFont(); font.setColor(0.9f, 0.9f, 0.7f, 1.0f); heroMoving = false; Gdx.input.setInputProcessor(this); initScene1Floor(); generateBulletBonuses(); getRedBulletBonusTexture = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/false.png")); tmp = TextureRegion.split(getRedBulletBonusTexture, getRedBulletBonusTexture.getWidth() / BULLET_BONUS_FRAME_COLS, getRedBulletBonusTexture.getHeight() / BULLET_BONUS_FRAME_ROWS); TextureRegion[] getRedBulletBonusFrames = new TextureRegion[BULLET_BONUS_FRAME_COLS * BULLET_BONUS_FRAME_ROWS]; index = 0; for (int i = 0; i < BULLET_BONUS_FRAME_ROWS; i++) { for (int j = 0; j < BULLET_BONUS_FRAME_COLS; j++) { getRedBulletBonusFrames[index++] = tmp[i][j]; } } redBulletBonusAnimation = new Animation(0.04f, getRedBulletBonusFrames); getGreenBulletBonusTexture = new Texture(Gdx.files.internal("assets/textures/scenes/scene_1/true.png")); tmp = TextureRegion.split(getGreenBulletBonusTexture, getGreenBulletBonusTexture.getWidth() / BULLET_BONUS_FRAME_COLS, getGreenBulletBonusTexture.getHeight() / BULLET_BONUS_FRAME_ROWS); TextureRegion[] getGreenBulletBonusFrames = new TextureRegion[BULLET_BONUS_FRAME_COLS * BULLET_BONUS_FRAME_ROWS]; index = 0; for (int i = 0; i < BULLET_BONUS_FRAME_ROWS; i++) { for (int j = 0; j < BULLET_BONUS_FRAME_COLS; j++) { getGreenBulletBonusFrames[index++] = tmp[i][j]; } } greenBulletBonusAnimation = new Animation(0.04f, getGreenBulletBonusFrames); inkyGetBulletBonusType = 0; inkyGetBulletBonusCount = 0; inkyHaveBullets = 0; inkyCollisionRect = new Rectangle(); inkyCollisionRect.x = 500;//inkyScreenPos.x; inkyCollisionRect.y = 350;//inkyScreenPos.y; inkyCollisionRect.width = 20; inkyCollisionRect.height = 70; } private void MoveHero() { if ( heroMoveLeft ) { sceneScrollPos.x = sceneScrollPos.x + elapsedTime * MoveSpeed; } if ( heroMoveRight ) { sceneScrollPos.x = sceneScrollPos.x - elapsedTime * MoveSpeed; } if ( heroMoveUp ) { sceneScrollPos.y = sceneScrollPos.y - elapsedTime * MoveSpeed; } if ( heroMoveDown ) { sceneScrollPos.y = sceneScrollPos.y + elapsedTime * MoveSpeed; } } @Override public boolean keyDown (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = true; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = true; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = true; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = true; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; } @Override public boolean keyUp (int keycode) { if ( keycode == Keys.A || keycode == Keys.LEFT || keycode == Keys.NUMPAD_4 ) { heroMoveLeft = false; } if ( keycode == Keys.D || keycode == Keys.RIGHT || keycode == Keys.NUMPAD_6 ) { heroMoveRight = false; } if ( keycode == Keys.W || keycode == Keys.UP || keycode == Keys.NUMPAD_8 ) { heroMoveUp = false; } if ( keycode == Keys.S || keycode == Keys.DOWN || keycode == Keys.NUMPAD_2 ) { heroMoveDown = false; } heroMoving = heroMoveLeft || heroMoveRight || heroMoveUp || heroMoveDown; return false; } @Override public boolean keyTyped (char character) { return false; } @Override public boolean scrolled (float amountX, float amountY) { return false; } public boolean touchDragged (int screenX, int screenY, int pointer) { return false; } @Override public boolean touchUp (int screenX, int screenY, int pointer, int button) { return false; } public boolean touchDown (int screenX, int screenY, int pointer, int button) { return false; } public boolean mouseMoved (int screenX, int screenY) { return false; } private void initScene1Floor() { int floorStep = 512; scene1FloorElementsNum = 64;//49; int floorElementsRows = (int)Math.floor(Math.sqrt(scene1FloorElementsNum)); int floorElementsCols = scene1FloorElementsNum / floorElementsRows; Vector2 initPoint = new Vector2(0, 0); initPoint.x = -floorStep*(floorElementsCols-(floorElementsCols-3)); initPoint.y = -floorStep*(floorElementsRows-(floorElementsCols-3)); scene1FloorElements = new EnterraFloor[scene1FloorElementsNum]; MathUtils.random.setSeed(System.currentTimeMillis()); for (int i = 0; i < scene1FloorElementsNum; i++) { scene1FloorElements[i] = new EnterraFloor(); } int itemIndex = 0; for (int i = 0; i < floorElementsRows; i++) { for (int j = 0; j < floorElementsCols; j++) { scene1FloorElements[itemIndex].pos = new Vector2(initPoint.x, initPoint.y); scene1FloorElements[itemIndex].type = MathUtils.random(1, 3); initPoint.x = initPoint.x + floorStep; if ( initPoint.x > (floorStep*2-1) ) initPoint.x = -floorStep*(floorElementsCols-2); itemIndex++; } initPoint.y = initPoint.y + floorStep; if ( initPoint.y > (floorStep*2-1) ) initPoint.y = -floorStep*(floorElementsRows-2); } } private void drawFloor() { for (int i = 0; i < scene1FloorElementsNum; i++) { if ( scene1FloorElements[i].type == 1 ) batch.draw(scene1FloorTexture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 2 ) batch.draw(scene1Floor2Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); if ( scene1FloorElements[i].type == 3 ) batch.draw(scene1Floor3Texture, (int)Math.floor(sceneScrollPos.x+scene1FloorElements[i].pos.x), (int)Math.floor(sceneScrollPos.y+scene1FloorElements[i].pos.y)); } } TextureRegion inkyWalkRightCurrentFrame; private void drawBulletBonuses() { for (int i = 0; i < scene1BulletBonusesNum; i++) { if ( scene1BulletBonusesType[i] == 1) { batch.draw(redBulletBonusCurrentFrame, sceneScrollPos.x+scene1BulletBonuses[i].x, sceneScrollPos.y+scene1BulletBonuses[i].y); } if ( scene1BulletBonusesType[i] == 2) { batch.draw(greenBulletBonusCurrentFrame, sceneScrollPos.x+scene1BulletBonuses[i].x, sceneScrollPos.y+scene1BulletBonuses[i].y); } } } private void testPlayerCollisionWithBulletBonuses() { Rectangle bulletBonusRect = new Rectangle(0, 0, 30, 30); for (int i = 0; i < scene1BulletBonusesNum; i++) { bulletBonusRect.x = sceneScrollPos.x + scene1BulletBonusesCollisionRects[i].x; bulletBonusRect.y = sceneScrollPos.y + scene1BulletBonusesCollisionRects[i].y; if ( inkyCollisionRect.overlaps(bulletBonusRect)) { if ( scene1BulletBonusesType[i] > 0 ) { if ( inkyGetBulletBonusType == scene1BulletBonusesType[i]) inkyHaveBullets += 50; else inkyHaveBullets = 50; inkyGetBulletBonusType = scene1BulletBonusesType[i]; if ( scene1BulletBonusesType[i] == 1 ) { //redBulletBonusSoundPlayId = redBulletBonusSound.play(); //redBulletBonusSound.setVolume(redBulletBonusSoundPlayId, soundVolume); } if ( scene1BulletBonusesType[i] == 2 ) { //greenBulletBonusSoundPlayId = greenBulletBonusSound.play(); //greenBulletBonusSound.setVolume(greenBulletBonusSoundPlayId, soundVolume); } scene1BulletBonusesType[i] = 0; //bullet is get by player inkyGetBulletBonusCount++; int totalGetBulletBonusCount = inkyGetBulletBonusCount;// + boBossGetBulletBonusCount; if ( totalGetBulletBonusCount == scene1BulletBonusesNum) { generateBulletBonuses(); } } } } } TextureRegion redBulletBonusCurrentFrame; TextureRegion greenBulletBonusCurrentFrame; @Override public void render () { ScreenUtils.clear(0.0f, 0.0f, 0.0f, 1.0f); if ( heroMoving ) { stateTime += Gdx.graphics.getDeltaTime(); } elapsedTime = Gdx.graphics.getDeltaTime(); inkyWalkRightCurrentFrame = inkyWalkRightAnimation.getKeyFrame(stateTime, heroMoving); stateTime2 += Gdx.graphics.getDeltaTime(); redBulletBonusCurrentFrame = redBulletBonusAnimation.getKeyFrame(stateTime2, true); greenBulletBonusCurrentFrame = greenBulletBonusAnimation.getKeyFrame(stateTime2, true); MoveHero(); testPlayerCollisionWithBulletBonuses(); batch.begin(); drawFloor(); drawBulletBonuses(); batch.draw(scene1FloorTexture, sceneScrollPos.x, sceneScrollPos.y); batch.draw(inkyWalkRightCurrentFrame, 560, 300); font.draw(batch, " hx: " + (int)Math.floor(sceneScrollPos.x) + " hy: "+(int)Math.floor(sceneScrollPos.y), 10, 15); batch.end(); if(Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) Gdx.app.exit(); } @Override public void dispose () { batch.dispose(); scene1FloorTexture.dispose(); inkyWalkRightTextureAnim.dispose(); font.dispose(); scene1Floor2Texture.dispose(); scene1Floor3Texture.dispose(); } }
Теперь при контакте с бонусами пуль, они будут исчезать. А как только все бонусы пуль в сцене закончатся, будут опять сгенерированы новые. В методе render для целей отладки можно вывести количество собранных бонусов. Вот так - font.draw(batch, " hx: " + (int)Math.floor(sceneScrollPos.x) + " hy: "+(int)Math.floor(sceneScrollPos.y)+ " bonuses: "+inkyGetBulletBonusCount, 10, 15); Также вы заметите, что некоторые строки кода закомментированы, например //redBulletBonusSoundPlayId = redBulletBonusSound.play(); //redBulletBonusSound.setVolume(redBulletBonusSoundPlayId, soundVolume); Эти строки служат для воспроизведения звука при взятии бонуса. Добавлением звуков мы займемся в следующем уроке. Следует отметить, что если вся полученная информация вам понятна, то вы вполне можете создать игру самостоятельно, даже не читая материал последующих уроков. Вам лишь нужно будет гуглить те темы и вопросы, которые потребуется. А так уже вполне достаточно знаний, чтобы создавать и развивать какую-то свою игру. В следующих уроках будут рассмотрены темы: - воспроизведение в игре звуков и музыки; - экран опций для регулировки громкостии музыки и звуков, а также уровня сложности игры; - оружие персонажа и его повороты; - стрельба пулями-шариками; - столкновения с пулями-шариками; - создание Босса уровня; - реализация перемещений Босса; - реализация стрельбы Босса пулями; - сбор Боссом бонусов игры; - другие вопросы и взаимодействия в игре. Создание игры на java и libgdx - урок 4 - воспроизведение в игре звуков и музыки
оцените статью:
0
Понравилось!
0
Не понравилось!
 

Оставленные комментарии


megainformatic 2006 - 2024 карта сайта




Посетили страницу: 107