Как мы писали арифметическую головоломку на LibGDX под ведроид. Часть 2
Историю создания и все предисловия вы можете найти в первой части статьи: http://pikabu.ru/story/kak_myi_pisali_arifmeticheskuyu_golov.... В этой статье будет больше конкретики. Хотелось бы рассказать о том, каким образом реализованы уровни в игре, и начнём с основополагающей сущности – треугольника.
С треугольником всё довольно просто. У него есть значение value, которое используется для последующих подсчётов сумы в пунктирной области, также по этому значению выбирается подходящая текстура для актёра. К слову, как и полагается, все текстуры упакованы в атласы. Также, у треугольника есть boolean переменная, которая определяет, скрыт ли треугольник (влияет только на подбор текстуры, если скрыт – текстура со знаком вопроса).
Итак, класс треугольника как он есть:
public class Triangle extends Actor {
public GdxGameCore game;
private int value;
private int placeNumber;
private boolean isHidden;
private TextureAtlas.AtlasRegion texture;
public void draw(Batch batch, float parentAlpha) {
batch.draw(texture, getX(), getY(), getWidth(), getHeight());
super.draw(batch, parentAlpha);
}
/**
* Конструктор для создания объекта Triangle
* @param value - числовое значение треугольника (0-9)
* @param isHidden - флаг скрытия теугольника (0 - не скрыт, 1- скрыт)
* @param placeNumber - положение треугольника на площадке уровня
*/
public Triangle (int value, boolean isHidden, int placeNumber, GdxGameCore game) {
this.game = game;
this.value = value;
this.isHidden = isHidden;
this.placeNumber = placeNumber;
/*
* Определение текстуры
*/
if (isHidden) {
this.texture = game.hidden;
} else {
switch (value) {
case 0:
this.texture = game.zero;
break;
case 1:
this.texture = game.one;
break;
case 2:
this.texture = game.two;
break;
case 3:
this.texture = game.three;
break;
case 4:
this.texture = game.four;
break;
case 5:
this.texture = game.five;
break;
case 6:
this.texture = game.six;
break;
case 7:
this.texture = game.seven;
break;
case 8:
this.texture = game.eight;
break;
case 9:
this.texture = game.nine;
break;
}
}
}
public boolean isHidden() {
return isHidden;
}
public int getPlaceNumber() {
return placeNumber;
}
public int getValue() {
return value;
}
public TextureAtlas.AtlasRegion getTexture() {
return texture;
}
public String toString() {
return super.toString();
}
}
Следующим шагом хочу рассказать о кнопке, с помощью которой осуществляется движение группы треугольников (по кругу, в заданном направлении). Класс кнопки также очень прост. У него есть переменная направления движения, с помощью которой мы определяем, в какую сторону прокручивать группу треугольников. По этой же переменной подбирается и текстура актёра.
Собственно, класс кнопки:
public class MoveButton extends Actor{
final GdxGameCore game;
private int direction;
private TextureAtlas.AtlasRegion texture, texturePressed;
private boolean isPressed = false;
public void draw(Batch batch, float parentAlpha) {
if (!isPressed) {
batch.draw(texture, getX(), getY(), getWidth(), getHeight());
} else {
batch.draw(texturePressed, getX(), getY(), getWidth(), getHeight());
}
super.draw(batch, parentAlpha);
}
/**
* Конструктор кнопки движения
* (Подбирает нужную текстуру и генерирует актёра)
* @param direction - направление (0 - влево, 1 - вправо)
*/
public MoveButton (int direction, GdxGameCore game) {
this.game = game;
this.direction = direction;
if (direction == 0) {
// LEFT BUTTON TEXTURE
this.texture = game.move_left;
this.texturePressed = game.move_left_pressed;
} else {
// RIGHT BUTTON TEXTURE
this.texture = game.move_right;
this.texturePressed = game.move_right_pressed;
}
}
public int getDirection() {
return direction;
}
public void setPressed () {
isPressed = true;
this.act(0.3f);
isPressed = false;
this.act(0.3f);
}
public TextureAtlas.AtlasRegion getTexture() {
return texture;
}
public String toString() {
return super.toString();
}
}
Далее, хочу рассказать о классе уровня. Класс уровня вмещает в себе конструктор, который создаёт объекты треугольников и кнопок, а также, ограничения на количество движений и времени. В классе есть три различных конструктора под каждую из трёх сложностей. В классе игры (GameScreen) осуществляется работа с объектом Level, что довольно удобно. Особых пояснений, думаю, не требуется, поэтому, просто покажу код:
public class Level {
GdxGameCore game;
private int levelNum;
// HARDNESS 1
private int triangle_1, triangle_2, triangle_3, triangle_4, triangle_5, triangle_6;
private boolean b_hide_1, b_hide_2, b_hide_3, b_hide_4, b_hide_5, b_hide_6;
private int btn_1, btn_2, btn_3; // 0 - LEFT, 1 - RIGHT;
// HARDNESS 2
private int triangle_7, triangle_8, triangle_9, triangle_10;
private int hide_1, hide_2, hide_3, hide_4, hide_5, hide_6;
private int hide_7, hide_8, hide_9, hide_10;
private boolean b_hide_7, b_hide_8, b_hide_9, b_hide_10;
private int btn_4, btn_5, btn_6; // 0 - LEFT, 1 - RIGHT;
// Ограничения
private int time_sec;
private int moves;
private int goal;
private List <Triangle> triangles;
private List <MoveButton> moveButtons;
/**
* HARDNESS EASY
* @param levelNum - номер уровня
* @param triangle_1 - значение треугольника
* @param triangle_2 - значение треугольника
* @param triangle_3 - значение треугольника
* @param triangle_4 - значение треугольника
* @param triangle_5 - значение треугольника
* @param triangle_6 - значение треугольника
* @param time_sec - ограничение во времени в секундах
* @param moves - ограничение в движениях
* @param goal - цель (необходимая сумма в главном треугольнике)
* @param btn_1 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_2 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_3 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param game - основной класс core модуля
*/
public Level (int levelNum, int triangle_1, int triangle_2, int triangle_3, int triangle_4,
int triangle_5, int triangle_6, int time_sec, int moves, int goal, int btn_1, int btn_2,
int btn_3, GdxGameCore game) {
this.game = game;
this.levelNum = levelNum;
this.triangle_1 = triangle_1;
this.triangle_2 = triangle_2;
this.triangle_3 = triangle_3;
this.triangle_4 = triangle_4;
this.triangle_5 = triangle_5;
this.triangle_6 = triangle_6;
this.time_sec = time_sec;
this.moves = moves;
this.goal = goal;
this.btn_1 = btn_1;
this.btn_2 = btn_2;
this.btn_3 = btn_3;
Triangle tr1 = new Triangle(triangle_1, false, 1, game);
Triangle tr2 = new Triangle(triangle_2, false, 2, game);
Triangle tr3 = new Triangle(triangle_3, false, 3, game);
Triangle tr4 = new Triangle(triangle_4, false, 4, game);
Triangle tr5 = new Triangle(triangle_5, false, 5, game);
Triangle tr6 = new Triangle(triangle_6, false, 6, game);
MoveButton mb1 = new MoveButton(btn_1, game);
MoveButton mb2 = new MoveButton(btn_2, game);
MoveButton mb3 = new MoveButton(btn_3, game);
triangles = new ArrayList<Triangle>();
triangles.add(tr1);
triangles.add(tr2);
triangles.add(tr3);
triangles.add(tr4);
triangles.add(tr5);
triangles.add(tr6);
moveButtons = new ArrayList<MoveButton>();
moveButtons.add(mb1);
moveButtons.add(mb2);
moveButtons.add(mb3);
}
/**
* HARDNESS MEDIUM
* @param levelNum - номер уровня
* @param triangle_1 - значение треугольника
* @param triangle_2 - значение треугольника
* @param triangle_3 - значение треугольника
* @param triangle_4 - значение треугольника
* @param triangle_5 - значение треугольника
* @param triangle_6 - значение треугольника
* @param hide_1 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_2 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_3 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_4 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_5 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_6 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param time_sec - ограничение во времени в секундах
* @param moves - ограничение в движениях
* @param goal - цель (необходимая сумма в главном треугольнике)
* @param btn_1 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_2 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_3 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param game - - основной класс core модуля
*/
public Level (int levelNum, int triangle_1, int triangle_2, int triangle_3, int triangle_4,
int triangle_5, int triangle_6, int hide_1, int hide_2, int hide_3, int hide_4,
int hide_5, int hide_6, int time_sec, int moves, int goal, int btn_1, int btn_2,
int btn_3, GdxGameCore game) {
this.game = game;
this.levelNum = levelNum;
this.triangle_1 = triangle_1;
this.triangle_2 = triangle_2;
this.triangle_3 = triangle_3;
this.triangle_4 = triangle_4;
this.triangle_5 = triangle_5;
this.triangle_6 = triangle_6;
this.hide_1 = hide_1;
this.hide_2 = hide_2;
this.hide_3 = hide_3;
this.hide_4 = hide_4;
this.hide_5 = hide_5;
this.hide_6 = hide_6;
this.time_sec = time_sec;
this.moves = moves;
this.goal = goal;
this.btn_1 = btn_1;
this.btn_2 = btn_2;
this.btn_3 = btn_3;
checkHidden(6);
Triangle tr1 = new Triangle(triangle_1, b_hide_1, 1, game);
Triangle tr2 = new Triangle(triangle_2, b_hide_2, 2, game);
Triangle tr3 = new Triangle(triangle_3, b_hide_3, 3, game);
Triangle tr4 = new Triangle(triangle_4, b_hide_4, 4, game);
Triangle tr5 = new Triangle(triangle_5, b_hide_5, 5, game);
Triangle tr6 = new Triangle(triangle_6, b_hide_6, 6, game);
MoveButton mb1 = new MoveButton(btn_1, game);
MoveButton mb2 = new MoveButton(btn_2, game);
MoveButton mb3 = new MoveButton(btn_3, game);
triangles = new ArrayList<Triangle>();
triangles.add(tr1);
triangles.add(tr2);
triangles.add(tr3);
triangles.add(tr4);
triangles.add(tr5);
triangles.add(tr6);
moveButtons = new ArrayList<MoveButton>();
moveButtons.add(mb1);
moveButtons.add(mb2);
moveButtons.add(mb3);
}
/**
* HARDNESS HARD
* @param levelNum - номер уровня
* @param triangle_1 - значение треугольника
* @param triangle_2 - значение треугольника
* @param triangle_3 - значение треугольника
* @param triangle_4 - значение треугольника
* @param triangle_5 - значение треугольника
* @param triangle_6 - значение треугольника
* @param triangle_7 - значение треугольника
* @param triangle_8 - значение треугольника
* @param triangle_9 - значение треугольника
* @param triangle_10 - значение треугольника
* @param hide_1 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_2 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_3 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_4 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_5 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_6 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_7 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_8 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_9 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param hide_10 - флаг скрытия треугольника (0 - не скрыт, 1 - скрыт)
* @param time_sec - ограничение во времени в секундах
* @param moves - ограничение в движениях
* @param goal - цель (необходимая сумма в главном треугольнике)
* @param btn_1 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_2 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_3 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_4 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_5 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param btn_6 - флаг кнопки движения (0 - влево, 1 - вправо)
* @param game - основной класс core модуля
*/
public Level (int levelNum, int triangle_1, int triangle_2, int triangle_3, int triangle_4,
int triangle_5, int triangle_6, int triangle_7, int triangle_8, int triangle_9,
int triangle_10, int hide_1, int hide_2, int hide_3, int hide_4, int hide_5,
int hide_6, int hide_7, int hide_8, int hide_9, int hide_10, int time_sec,
int moves, int goal, int btn_1, int btn_2, int btn_3, int btn_4, int btn_5,
int btn_6, GdxGameCore game) {
this.game = game;
this.levelNum = levelNum;
this.triangle_1 = triangle_1;
this.triangle_2 = triangle_2;
this.triangle_3 = triangle_3;
this.triangle_4 = triangle_4;
this.triangle_5 = triangle_5;
this.triangle_6 = triangle_6;
this.triangle_7 = triangle_7;
this.triangle_8 = triangle_8;
this.triangle_9 = triangle_9;
this.triangle_10 = triangle_10;
this.hide_1 = hide_1;
this.hide_2 = hide_2;
this.hide_3 = hide_3;
this.hide_4 = hide_4;
this.hide_5 = hide_5;
this.hide_6 = hide_6;
this.hide_7 = hide_7;
this.hide_8 = hide_8;
this.hide_9 = hide_9;
this.hide_10 = hide_10;
this.time_sec = time_sec;
this.moves = moves;
this.goal = goal;
this.btn_1 = btn_1;
this.btn_2 = btn_2;
this.btn_3 = btn_3;
this.btn_4 = btn_4;
this.btn_5 = btn_5;
this.btn_6 = btn_6;
checkHidden(10);
Triangle tr1 = new Triangle(triangle_1, b_hide_1, 1, game);
Triangle tr2 = new Triangle(triangle_2, b_hide_2, 2, game);
Triangle tr3 = new Triangle(triangle_3, b_hide_3, 3, game);
Triangle tr4 = new Triangle(triangle_4, b_hide_4, 4, game);
Triangle tr5 = new Triangle(triangle_5, b_hide_5, 5, game);
Triangle tr6 = new Triangle(triangle_6, b_hide_6, 6, game);
Triangle tr7 = new Triangle(triangle_7, b_hide_7, 7, game);
Triangle tr8 = new Triangle(triangle_8, b_hide_8, 8, game);
Triangle tr9 = new Triangle(triangle_9, b_hide_9, 9, game);
Triangle tr10 = new Triangle(triangle_10, b_hide_10, 10, game);
MoveButton mb1 = new MoveButton(btn_1, game);
MoveButton mb2 = new MoveButton(btn_2, game);
MoveButton mb3 = new MoveButton(btn_3, game);
MoveButton mb4 = new MoveButton(btn_4, game);
MoveButton mb5 = new MoveButton(btn_5, game);
MoveButton mb6 = new MoveButton(btn_6, game);
triangles = new ArrayList<Triangle>();
triangles.add(tr1);
triangles.add(tr2);
triangles.add(tr3);
triangles.add(tr4);
triangles.add(tr5);
triangles.add(tr6);
triangles.add(tr7);
triangles.add(tr8);
triangles.add(tr9);
triangles.add(tr10);
moveButtons = new ArrayList<MoveButton>();
moveButtons.add(mb1);
moveButtons.add(mb2);
moveButtons.add(mb3);
moveButtons.add(mb4);
moveButtons.add(mb5);
moveButtons.add(mb6);
}
/**
* Переобразование значений 1 & 0 в тип boolean для создания объектов треугольников
* @param triangleQuantity - кол-во треугольников на площадке уровня
*/
public void checkHidden (int triangleQuantity) {
if (triangleQuantity == 6) {
// HARDNESS MEDIUM
if (hide_1 == 0) {
b_hide_1 = false;
} else {
b_hide_1 = true;
}
if (hide_2 == 0) {
b_hide_2 = false;
} else {
b_hide_2 = true;
}
if (hide_3 == 0) {
b_hide_3 = false;
} else {
b_hide_3 = true;
}
if (hide_4 == 0) {
b_hide_4 = false;
} else {
b_hide_4 = true;
}
if (hide_5 == 0) {
b_hide_5 = false;
} else {
b_hide_5 = true;
}
if (hide_6 == 0) {
b_hide_6 = false;
} else {
b_hide_6 = true;
}
} else {
// HARDNESS HARD
if (hide_1 == 0) {
b_hide_1 = false;
} else {
b_hide_1 = true;
}
if (hide_2 == 0) {
b_hide_2 = false;
} else {
b_hide_2 = true;
}
if (hide_3 == 0) {
b_hide_3 = false;
} else {
b_hide_3 = true;
}
if (hide_4 == 0) {
b_hide_4 = false;
} else {
b_hide_4 = true;
}
if (hide_5 == 0) {
b_hide_5 = false;
} else {
b_hide_5 = true;
}
if (hide_6 == 0) {
b_hide_6 = false;
} else {
b_hide_6 = true;
}
if (hide_7 == 0) {
b_hide_7 = false;
} else {
b_hide_7 = true;
}
if (hide_8 == 0) {
b_hide_8 = false;
} else {
b_hide_8 = true;
}
if (hide_9 == 0) {
b_hide_9 = false;
} else {
b_hide_9 = true;
}
if (hide_10 == 0) {
b_hide_10 = false;
} else {
b_hide_10 = true;
}
}
}
public int getLevelNum() {
return levelNum;
}
public int getGoal() {
return goal;
}
public int getMoves() {
return moves;
}
public int getTime_sec() {
return time_sec;
}
public List<Triangle> getTriangles() {
return triangles;
}
public List<MoveButton> getMoveButtons() {
return moveButtons;
}
public String toString() {
return super.toString();
}
}
В данном методе происходит перемещение треугольников, происходит оно по нажатию на определенную кнопку, которая передает треугольники которые стоят возле неё.
Мы запоминаем координаты треугольников и потом меняем их местами.
После этого они еще меняются местами в массиве, при помощи Коллекций.
public void swapTrianglesLeft(Triangle triangle1, Triangle triangle2, Triangle triangle3){
// sound
game.playMoveSound();
float tr1X, tr1Y, tr2X, tr2Y, tr3X, tr3Y;
tr1X = triangle1.getX();
tr1Y = triangle1.getY();
tr2X = triangle2.getX();
tr2Y = triangle2.getY();
tr3X = triangle3.getX();
tr3Y = triangle3.getY();
triangle1.addAction(Actions.moveTo(tr3X, tr3Y, 0.5f));
triangle2.addAction(Actions.moveTo(tr1X, tr1Y, 0.5f));
triangle3.addAction(Actions.moveTo(tr2X, tr2Y, 0.5f));
}
Надеюсь, эта статья была более конструктивной, чем предыдущая, и интересно дополнила её. Спасибо за внимание, ставьте плюсик, если понравилось и, конечно же, всем добра :)
Ссылка на Play Market: https://play.google.com/store/apps/details?id=com.dailytoys....