Android – рисование лабиринта на холсте с плавным движением символов

В настоящее время я создаю игру на основе плитки, которая по существу рисует лабиринт с использованием 2 наборов логических массивов, чтобы определить, где нужно нарисовать каждую стену.

У меня есть все, что нужно, только с 5 x 5 секцией лабиринта (общий размер лабиринта 30 х 30). Тем не менее, проблема, с которой я сталкиваюсь, – это когда я перемещаю персонажа, весь экран прыгает, это связано с тем, что следующий раздел лабиринта рисуется, чтобы поддерживать соотношение сторон 5 х 5. Я пробовал разные вещи, чтобы попытаться сделать этот прогон плавно, но, похоже, просто не может этого сделать.

Может ли кто-нибудь посоветовать или направить меня на некоторые ссылки / примеры, чтобы я мог заставить лабиринт и движения персонажей все происходить гладко. Ниже приведен базовый код относительно основного цикла, который в настоящее время рисует лабиринт и 2 булевых массива, которые он ссылается, чтобы нарисовать стены.

// THE CODE TO DRAW THE MAZE AND ITS WALLS for(int i = 0; i < 5; i++) { for(int j = 0; j < 5; j++) { float x = j * totalCellWidth; float y = i * totalCellHeight; if(currentY != 0) indexY = i + currentY - 1; else indexY = i + currentY; if(currentX != 0) indexX = j + currentX - 1; else indexX = j + currentX; // Draw Verticle line (y axis) if (indexY < vLength && indexX < vLines[indexY].length && vLines[indexY][indexX]) { RectOuterBackground.set((int)x + (int)cellWidth, (int)y, (int)x + (int)cellWidth + 15, (int)y + (int)cellHeight + 15); canvas.drawBitmap(walls, null, RectOuterBackground, null); } // Draws Horizontal lines (x axis) if (indexY < hLength && indexX < hLines[indexY].length && hLines[indexY][indexX]) { RectOuterBackground.set((int)x, (int)y + (int)cellHeight,(int)x + (int)cellWidth + 15,(int)y + (int)cellHeight + 15); canvas.drawBitmap(walls, null, RectOuterBackground, null); } } } // THE 2 BOOLEAN ARRAYS THE FORLOOP REFERENCES boolean[][] vLines = new boolean[][]{ {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true }, {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true }, {true ,true ,true ,false,false,false,true ,false,false,true ,true }, {true ,true ,true ,false,false,true ,false,true ,true ,true ,true }, {true ,true ,false,true ,false,false,true ,false,false,true ,true }, {true ,true ,false,true ,true ,false,false,false,true ,true ,true }, {true ,true ,true ,false,false,false,true ,true ,false,true ,true }, {true ,true ,false,true ,false,false,true ,false,false,true ,true }, {true ,true ,false,true ,true ,true ,true ,true ,false,true ,true }, {true ,true ,false,false,false,true ,false,false,false,true ,true }, {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true }, {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true } }; boolean[][] hLines = new boolean[][]{ {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true }, {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true }, {true ,true ,false,false,true ,true ,false,false,true ,false,true ,true }, {true ,true ,false,false,true ,true ,false,true ,false,false,true ,true }, {true ,true ,true ,true ,false,true ,true ,false,true ,true ,true ,true }, {true ,true ,false,false,true ,false,true ,true ,false,false,true ,true }, {true ,true ,false,true ,true ,true ,true ,false,true ,true ,true ,true }, {true ,true ,true ,false,false,true ,false,false,true ,false,true ,true }, {true ,true ,false,true ,false,false,false,true ,false,true ,true ,true }, {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true }, {true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true ,true } }; 

Я готов полностью переписать этот раздел кода, если я могу заставить его рисовать плавно, однако, попробовав несколько разных вариантов, не получится гладким, у меня всегда есть прыжок.

Я пытался также заставить его работать с переводом canvas, вытягивая лабиринт whoel, затем масштабируйте его так, чтобы отображалось только 5 x 5, а затем просто перемещало масштабированную секцию, используя перевод, сохраняя символ в центре Экран, обеспечивающий плавное движение. Однако я просто не мог заставить перевод двигаться спокойно.

Вот полный класс лабиринта. Он рисует представление для координат viewX и viewY, которые можно перемещать либо плавно (как в ответе Будьны), либо с умножением размеров ячеек.

 import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.RectF; public class Maze { private RectF drawRect = new RectF(); private Bitmap[] bitmaps; private int[][] tileType; private float screenWidth, screenHeight; /** * Initialize a new maze. * @param wallBitmap The desired bitmaps for the floors and walls * @param isWall The wall data array. Each true value in the array represents a wall and each false represents a gap * @param xCellCountOnScreen How many cells are visible on the screen on the x axis * @param yCellCountOnScreen How many cells are visible on the screen on the y axis * @param screenWidth The screen width * @param screenHeight The screen height */ public Maze(Bitmap[] bitmaps, int[][] tileType, float xCellCountOnScreen, float yCellCountOnScreen, float screenWidth, float screenHeight){ this.bitmaps = bitmaps; this.tileType = tileType; this.screenWidth = screenWidth; this.screenHeight = screenHeight; drawRect.set(0, 0, screenWidth / xCellCountOnScreen, screenHeight / yCellCountOnScreen); } /** * Get the type of the cell. x and y values are not coordinates! * @param x The x index of the cell * @param y The y index of the cell * @return The cell type */ public int getType(int x, int y){ if(y < tileType.length && x < tileType[y].length) return tileType[y][x]; return 0; } public float getCellWidth(){ return drawRect.width(); } public float getCellHeight(){ return drawRect.height(); } /** * Draws the maze. View coordinates should have positive values. * @param canvas Canvas for the drawing * @param viewX The x coordinate of the view * @param viewY The y coordinate of the view */ public void drawMaze(Canvas canvas, float viewX, float viewY){ int tileX = 0; int tileY = 0; float xCoord = -viewX; float yCoord = -viewY; while(tileY < tileType.length && yCoord <= screenHeight){ // Begin drawing a new column tileX = 0; xCoord = -viewX; while(tileX < tileType[tileY].length && xCoord <= screenWidth){ // Check if the tile is not null if(bitmaps[tileType[tileY][tileX]] != null){ // This tile is not null, so check if it has to be drawn if(xCoord + drawRect.width() >= 0 && yCoord + drawRect.height() >= 0){ // The tile actually visible to the user, so draw it drawRect.offsetTo(xCoord, yCoord); // Move the rectangle to the coordinates canvas.drawBitmap(bitmaps[tileType[tileY][tileX]], null, drawRect, null); } } // Move to the next tile on the X axis tileX++; xCoord += drawRect.width(); } // Move to the next tile on the Y axis tileY++; yCoord += drawRect.height(); } } } 

Чтобы использовать этот класс, сначала инициализируйте его в своей функции onCreate, как это

 // 0 == floor, 1 == wall, 2 == different looking wall int[][] maze = { {0, 0, 0, 0, 0}, {0, 1, 2, 1, 0}, {0, 0, 0, 1, 0}, {1, 1, 2, 1, 0}, {0, 0, 0, 0, 0} }; Bitmap[] bitmaps = { BitmapFactory.decodeResource(getResources(), R.drawable.floor), BitmapFactory.decodeResource(getResources(), R.drawable.firstwall) BitmapFactory.decodeResource(getResources(), R.drawable.secondwall) }; // Chance the 480 and 320 to match the screen size of your device maze = new Maze(bitmaps, maze, 5, 5, 480, 320); 

И затем нарисуйте его в своей onDraw или аналогичной функции, подобной этой

 maze.draw(canvas, viewX, viewY); 

Функции getType (int x, int y), getCellWidth () и getCellHeight () должны помочь вам реализовать любые взаимодействия с лабиринтом. Вы также можете добавить свои собственные функции в класс. Вы также можете изменить этот класс, чтобы отметить любые начальные и конечные фрагменты. Я не сделаю для тебя всю игру 🙂

Если вы установите свой символ в координаты (x, y) и нарисуйте его в координатах (x – viewX, y – viewY), вы можете иметь фиксированное положение для него относительно лабиринта, где бы ни находился вид.

Надеюсь, это поможет!

Используйте LibGDX или другой движок Android, такой как AndEngine (я не использовал этот). Разработка игры с использованием только Android-библиотеки очень сложна и подвержена ошибкам (вам нужно написать много кода шаблона, который уже сделан для вас в игровых движках). LibGDX может упростить вашу задачу разными способами:

  • Это графический API реализован в OenGL (у вас не будет проблем с производительностью в простой 2D-игре, такой как ваша)
  • Он имеет хорошую поддержку для игр на основе 2D-плитки ( https://code.google.com/p/libgdx-users/wiki/Tiles )
  • Это кросс-платформенный движок. Поддерживаемые платформы – iOS, BlackBerry, Desktop (Windows, Linux и Mac) и HTML 5.

Один из подходов, который вы можете рассмотреть, – это держать персонажа в центре экрана в любое время. Вместо того, чтобы перемещать своего персонажа, только перемещайте смещение в лабиринте. Этот метод распространен во многих старых (и, возможно, новых) ролевых играх.

Как насчет рисования всего растрового изображения лабиринта в OpenGL ES – Просмотр и настройка положения окна просмотра / камеры? Это даст вам возможность приятных эффектов при движении по лабиринту и абсолютно гладкой.