Класс Sprite
от aNNiMON
В Android нет специальных классов для игровых объектов, как это было в Java ME, но зато в нём есть множество других не менее полезных классов, знание которых поможет упростить разработку игры.
Во-первых, в Android есть специальные классы для точек, прямоугольников, контуров и остальных объектов. Теперь не нужно иметь кучу переменных, чтобы оперировать координатами персонажей, достаточно задать класс Point (для координат типа int) или PointF (для координат типа float).
Во-вторых, возможности рисования в Android куда более богаты, чем в Java ME. Здесь тебе и рисование градиентов, и гибкая работа с изображениями Bitmap, и сглаживание, и поворот, и т.д.
Советую посмотреть на список классов пакета android.graphics.
Вот теперь, давайте напишем реализацию класса Sprite с блекджеком проверкой столкновений и фреймами анимации.
Создадим новый Android проект и MainActivity. У кого с этим трудности, добро пожаловать сюда.
Сразу создадим класс Sprite.
Он должен содержать картинку, которая будет отрисовываться. Но так как мы хотим использовать последовательность картинок, то придётся создать массив и текущий индекс кадра:
Позицию спрайта мы будем хранить не в int x, y, а в специальном классе Point. Также нам потребуется знать размеры спрайта, для корректной проверки столкновений, для этого подойдёт класс Rect:
Это всё, что нам понадобится. Теперь перейдём к методам.
В Java ME у класса Sprite был метод move(int dx, int dy), позволяющий сдвигать спрайт с учётом указанных координат. По-сути, он прибавляет эти значения к текущей позиции спрайта. У класса Point есть метод offset, который как раз сдвигает позицию на заданные значения:
Для установки координат, воспользуемся методом set(int x, int y):
Теперь разберёмся с проверкой столкновений. В классе Rect есть статический метод intersects(Rect r1, Rect r2), позволяющий проверить, пересекаются ли прямоугольники. У нас есть позиция спрайта в mPoint, и есть его размеры в mBounds. Напомню, mBounds просто хранит ширину и высоту (0, 0, width, height). Чтобы получить Rect с реальными позициями спрайта, нужно сдвинуть прямоугольник mBounds на координату x, y. Это делается так же, как и в случае с Point: методом offset:
Напишем методы для проверки столкновений спрайта с другим спрайтом, прямоугольником и точкой:
Как видно, не нужно проверять каждую координату - метод intersects всё делает сам.
И, наконец, отрисовка спрайта. Она выглядит так:
Полный код класса Sprite.java
Теперь создадим GameView. Для примера, выведем несколько статичных спрайтов, которые будут анимировать при их выделении.
Хранить список спрайтов будем в ArrayList, а выделение в Rect.
Инициализация списка спрайтов:
Здесь мы подгружаем из ресурсов два изображения, кладём их в массив pacman и потом передаём в класс Sprite, не забыв выставить новые координаты.
Теперь, отрисовывать несколько спрайтов можно вот таким небольшим кодом:
Анимировать будут лишь выделенные спрайты, для этого мы проверяем столкновение спрайта с прямоугольником и, если столкновение произошло, вызываем метод nextFrame():
Вот результат:
Готовый проект с исходниками:
SpriteDemo.zip
Во-первых, в Android есть специальные классы для точек, прямоугольников, контуров и остальных объектов. Теперь не нужно иметь кучу переменных, чтобы оперировать координатами персонажей, достаточно задать класс Point (для координат типа int) или PointF (для координат типа float).
Во-вторых, возможности рисования в Android куда более богаты, чем в Java ME. Здесь тебе и рисование градиентов, и гибкая работа с изображениями Bitmap, и сглаживание, и поворот, и т.д.
Советую посмотреть на список классов пакета android.graphics.
Вот теперь, давайте напишем реализацию класса Sprite с блекджеком проверкой столкновений и фреймами анимации.
Создадим новый Android проект и MainActivity. У кого с этим трудности, добро пожаловать сюда.
Сразу создадим класс Sprite.
Он должен содержать картинку, которая будет отрисовываться. Но так как мы хотим использовать последовательность картинок, то придётся создать массив и текущий индекс кадра:
- private final Bitmap[] mFrames;
- private int mFrameIndex;
- private final Point mPosition;
- private final Rect mBounds;
Это всё, что нам понадобится. Теперь перейдём к методам.
В Java ME у класса Sprite был метод move(int dx, int dy), позволяющий сдвигать спрайт с учётом указанных координат. По-сути, он прибавляет эти значения к текущей позиции спрайта. У класса Point есть метод offset, который как раз сдвигает позицию на заданные значения:
- public void move(int dx, int dy) {
- mPosition.offset(dx, dy);
- }
- public void setPosition(int x, int y) {
- mPosition.set(x, y);
- }
Теперь разберёмся с проверкой столкновений. В классе Rect есть статический метод intersects(Rect r1, Rect r2), позволяющий проверить, пересекаются ли прямоугольники. У нас есть позиция спрайта в mPoint, и есть его размеры в mBounds. Напомню, mBounds просто хранит ширину и высоту (0, 0, width, height). Чтобы получить Rect с реальными позициями спрайта, нужно сдвинуть прямоугольник mBounds на координату x, y. Это делается так же, как и в случае с Point: методом offset:
- private Rect getBoundsRect() {
- Rect bounds = new Rect(mBounds);
- bounds.offset(mPosition.x, mPosition.y);
- return bounds;
- }
- public boolean collidesWith(Sprite s) {
- return Rect.intersects(getBoundsRect(), s.getBoundsRect());
- }
- public boolean collidesWith(Rect rect) {
- return Rect.intersects(getBoundsRect(), rect);
- }
- public boolean collidesWith(Point point) {
- return Rect.intersects(getBoundsRect(), new Rect(point.x, point.y, point.x, point.y));
- }
И, наконец, отрисовка спрайта. Она выглядит так:
- public void paint(Canvas canvas, Paint paint) {
- canvas.drawBitmap(mFrames[mFrameIndex], mPosition.x, mPosition.y, paint);
- }
Полный код класса Sprite.java
Теперь создадим GameView. Для примера, выведем несколько статичных спрайтов, которые будут анимировать при их выделении.
Хранить список спрайтов будем в ArrayList, а выделение в Rect.
Инициализация списка спрайтов:
- Bitmap pacman1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.pacman_1);
- Bitmap pacman2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.pacman_2);
- Bitmap[] pacman = new Bitmap[] { pacman1, pacman2 };
- mSprites = new ArrayList<Sprite>();
- Random rnd = new Random();
- final int size = rnd.nextInt(10) + 5;
- for (int i = 0; i < size; i++) {
- Sprite spr = new Sprite(pacman);
- spr.setPosition(rnd.nextInt(450), rnd.nextInt(800));
- mSprites.add(spr);
- }
Теперь, отрисовывать несколько спрайтов можно вот таким небольшим кодом:
- for (Sprite sprite : mSprites) {
- sprite.paint(canvas, mPaint);
- }
Анимировать будут лишь выделенные спрайты, для этого мы проверяем столкновение спрайта с прямоугольником и, если столкновение произошло, вызываем метод nextFrame():
- if (!mSelectionRect.isEmpty()) {
- for (Sprite sprite : mSprites) {
- if (sprite.collidesWith(mSelectionRect)) {
- sprite.nextFrame();
- }
- }
- }
Вот результат:
Готовый проект с исходниками:
SpriteDemo.zip