Статьи

Разработка игр для Android — Sprite Animation

Если вы следили за сериалом до сих пор, мы довольно хорошо знаем, как обрабатывать прикосновения, отображать изображения и перемещать их.

Но движущееся изображение — это довольно скучное зрелище, так как выглядит действительно фальшивым и дилетантским. Чтобы дать персонажам немного жизни, нам нужно сделать больше, чем это. Вот что такое анимация. Камень — неодушевленный предмет, и даже если он брошен, он не меняет свою форму. Человек, с другой стороны, очень оживлен. Попробуйте бросить одну, и вы увидите дергающиеся конечности и даже крики в воздухе.

Давайте просто прибегнем к изучению ходьбы, которая сама по себе довольно сложна. Вообразите человека, пересекающего ваш путь (только в 2D). Вы заметите различные проявления тела. Левая нога впереди, правая рука впереди, в то время как задние конечности находятся сзади. Это медленно изменяется, так что левая нога остается позади, в то время как правая прогрессирует вместе с телом. Но в один прекрасный момент цикл повторяется. Если вы не закрываете глаза, вы видите, что человек прогрессирует плавно. Если вы закрываете глаза и немного закрываете их, а затем снова открываете, человек уже ушел и находится в другом положении. Попробуйте мигнуть довольно быстро, и вы увидите что-то вроде старых черно-белых комедий. Это низкая частота кадров. Подробнее о FPS здесь .

На самом деле мы хотим, чтобы этот урок шел с низкой частотой кадров, как это.

Ходьба, представленная выше, немного хитрая, но это сорванная версия спрайтов с острова обезьян. Она Элейн Марли.
Это называется спрайт . Это простое двухмерное изображение или анимация.
Чтобы иметь возможность воссоздать вышеупомянутую анимацию, нам нужен каждый кадр из цикла ходьбы.

Это изображение шириной 150 пикселей, каждый кадр шириной 30 пикселей.
Чтобы проиллюстрировать это лучше, проверьте следующее изображение.

Чтобы получить вышеуказанную анимацию в Android (или iPhone или в любой другой программе в этом отношении), нам нужно загрузить каждый кадр как отдельное изображение и отображать их через равные промежутки времени один за другим. ИЛИ мы можем загрузить большое изображение, содержащее все кадры, и использовать методы, предоставляемые android, нарезать и нарезать их на лету и отображать только соответствующий кадр.
Сделать это тривиально. Мы знаем, что у нас есть 5 кадров, и каждый кадр имеет ширину 30 пикселей. Мы определяем прямоугольник (это будет наш выбор), который имеет ширину одного кадра и высоту изображения.
На следующем рисунке показано, как я вырезал первые два кадра. Остальное нужно заполнить.

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

Нам понадобится объект для анимации. Мы используем Elaine с острова обезьян, поэтому я буду использовать класс ElaineAnimated.java .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public class ElaineAnimated {</span> открытый класс ElaineAnimated {</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private static final String TAG = ElaineAnimated.class.getSimpleName();</span> приватная статическая конечная строка TAG = ElaineAnimated.class.getSimpleName ();</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private Bitmap bitmap;</span> частное растровое изображение;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the animation sequence</span> // последовательность анимации</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private Rect sourceRect;</span> приватный Rect sourceRect;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the rectangle to be drawn from the animation bitmap</span> // прямоугольник, который нужно нарисовать из растрового изображения анимации</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private int frameNr;</span> private int frameNr;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// number of frames in animation</span> // количество кадров в анимации</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private int currentFrame;</span> private int currentFrame;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the current frame</span> // текущий кадр</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private long frameTicker;</span> приватный длинный frameTicker;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the time of the last frame update</span> // время последнего обновления кадра</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private int framePeriod;</span> private int framePeriod;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// milliseconds between each frame (1000/fps)</span> // миллисекунды между каждым кадром (1000 / кадр / с)</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private int spriteWidth;</span> private int spriteWidth;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the width of the sprite to calculate the cut out rectangle</span> // ширина спрайта для вычисления вырезанного прямоугольника</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private int spriteHeight;</span> private int spriteHeight;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the height of the sprite</span> // высота спрайта</span>
 
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private int x;</span> private int x;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the X coordinate of the object (top left of the image)</span> // координата X объекта (верхний левый угол изображения)</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private int y;</span> private int y;</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// the Y coordinate of the object (top left of the image)</span> // координата Y объекта (верхний левый угол изображения)</span>
 
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Частные атрибуты комментируются, но стоит упомянуть некоторые.

  • точечный рисунок — это файл png, содержащий все кадры. Второе изображение в этой статье.
  • sourceRect — это прямоугольник выбора. Это синее окно на изображении выше. Прямоугольник перемещает каждый кадр на следующий.
  • frameTicker это временная метка java последнего изменения кадра в последовательности ходьбы. Обратите внимание, что это не игровой FPS, а ходячий FPS. Если мы хотим, чтобы Элейн выполнила полный цикл ходьбы за секунду, мы устанавливаем частоту кадров для ходьбы 5, потому что у нас 5 кадров. Чтобы получить действительно плавную анимацию, нам нужно 30 кадров, но сейчас это не главное.
  • framePeriod — это время в миллисекундах, которое представляет период времени, в течение которого отображается кадр. Если цикл завершается за 1 секунду, то есть для 5 кадров период составит 0,2 секунды. То есть каждый кадр будет отображаться в течение 0,2 секунды.

Конструктор выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public ElaineAnimated(Bitmap bitmap, int x, int y, int width, int height, int fps, int frameCount) {</span> public ElaineAnimated (Растровое растровое изображение, int x, int y, int width, int height, int fps, int frameCount) {</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">this.bitmap = bitmap;</span> this.bitmap = bitmap;</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">this.x = x;</span> this.x = x;</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">this.y = y;</span> this.y = y;</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">currentFrame = 0;</span> currentFrame = 0;</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">frameNr = frameCount;</span> frameNr = frameCount;</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">spriteWidth = bitmap.getWidth() / frameCount;</span> spriteWidth = bitmap.getWidth () / frameCount;</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">spriteHeight = bitmap.getHeight();</span> spriteHeight = bitmap.getHeight ();</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">sourceRect = new Rect(0, 0, spriteWidth, spriteHeight);</span> sourceRect = new Rect (0, 0, spriteWidth, spriteHeight);</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">framePeriod = 1000 / fps;</span> framePeriod = 1000 / кадров в секунду;</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">frameTicker = 0l;</span> frameTicker = 0l;</span>
   <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

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

У Элейн будет собственный метод обновления, поскольку она является анимированным объектом, ей нужно хорошо выглядеть, и она отвечает за перетаскивание ног. Поскольку период цикла обновления игры и период Элейн могут отличаться (в данном случае), мы передаем фактическое время игры как переменную, поэтому мы знаем, когда нам нужно отобразить следующий кадр.
Например, игра работает очень быстро, и обновление вызывается каждые 20 миллисекунд, и нам нужно обновлять кадр каждые 200 мсек, тогда прогресс кадра будет происходить при каждом 10-м обновлении игры.

Вот код:

01
02
03
04
05
06
07
08
09
10
11
12
13
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void update(long gameTime) {</span> публичное обновление void (long gameTime) {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">if (gameTime > frameTicker + framePeriod) {</span> if (gameTime> frameTicker + framePeriod) {</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">frameTicker = gameTime;</span> frameTicker = gameTime;</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// increment the frame</span> // увеличиваем кадр</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">currentFrame++;</span> currentFrame ++;</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">if (currentFrame >= frameNr) {</span> if (currentFrame> = frameNr) {</span>
            <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">currentFrame = 0;</span> currentFrame = 0;</span>
        <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// define the rectangle to cut out sprite</span> // определяем прямоугольник для вырезания спрайта</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">this.sourceRect.left = currentFrame * spriteWidth;</span> this.sourceRect.left = currentFrame * spriteWidth;</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">this.sourceRect.right = this.sourceRect.left + spriteWidth;</span> this.sourceRect.right = this.sourceRect.left + spriteWidth;</span>
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Обновление вызывается с главной игровой панели (проверьте предыдущие записи, как это работает). Это метод обновления класса MainGamePanel .

1
2
3
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void update() {</span> public void update () {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">elaine.update(System.currentTimeMillis());</span> elaine.update (System.currentTimeMillis ());</span>
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Метод обновления прост (Элейн). Он увеличивает кадр, если время передачи (то есть системное время, когда был вызван метод обновления) больше, чем в последний раз ( frameTicker ) обновления кадра, плюс период следующего обновления.
Если следующий кадр выходит за пределы последнего, мы сбрасываем цикл.

Ведь та область, из которой будет вырезано изображение, определяется как sourceRect .
Вот и все. Теперь давайте перейдем к его отображению.

1
2
3
4
5
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void draw(Canvas canvas) {</span> публичный ничья (холст холст) {</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// where to draw the sprite</span> // где нарисовать спрайт</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">Rect destRect = new Rect(getX(), getY(), getX() + spriteWidth, getY() + spriteHeight);</span> Rect destRect = new Rect (getX (), getY (), getX () + spriteWidth, getY () + spriteHeight);</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">canvas.drawBitmap(bitmap, sourceRect, destRect, null);</span> canvas.drawBitmap (bitmap, sourceRect, destRect, null);</span>
   <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Вот и все. Мы устанавливаем целевой прямоугольник, где рисовать вырезанное изображение. Это в позиции Элейн (X и Y установлены в конструкторе).

1
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">canvas.drawBitmap(bitmap, sourceRect, destRect, null);</span> canvas.drawBitmap (bitmap, sourceRect, destRect, null);</span>

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

Розыгрыш вызывается из метода рендера игровой панели, запускаемого игровым циклом (проверьте предыдущие записи).

MainGamePanel.java немного отличается от предыдущего раздела. Я избавился от всех дроидов и добавил только Элейн.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">private ElaineAnimated elaine;</span> частная ElaineAnimated elaine;</span>
 
   <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public MainGamePanel(Context context) {</span> public MainGamePanel (Context context) {</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">//* ... removed ... */</span> // * ... удалено ... * /</span>
 
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// create Elaine and load bitmap</span> // создаем Elaine и загружаем растровое изображение</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">elaine = new ElaineAnimated(</span> elaine = новый ElaineAnimated (</span>
               <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">BitmapFactory.decodeResource(getResources(), R.drawable.walk_elaine)</span> BitmapFactory.decodeResource (getResources (), R.drawable.walk_elaine)</span>
               <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">, 10, 50 // initial position</span> , 10, 50 // начальная позиция</span>
               <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">, 30, 47 // width and height of sprite</span> , 30, 47 // ширина и высота спрайта</span>
               <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">, 5, 5);</span> , 5, 5);</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// FPS and number of frames in the animation</span> // FPS и количество кадров в анимации</span>
 
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// create the game loop thread</span> // создаем игровой цикл</span>
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">thread = new MainThread(getHolder(), this);</span> thread = new MainThread (getHolder (), this);</span>
 
       <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">//* ... removed ... */</span> // * ... удалено ... * /</span>
   <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Элейн создается в конструкторе панели и получает начальное положение (X = 10, Y = 50). Я передаю ширину и высоту спрайта, но это все равно игнорируется, но вы можете изменить код.
FPS очень важен и количество кадров тоже. FPS говорит, сколько кадров нужно показать за одну секунду. Последний параметр — это количество кадров в цикле.

Классы потока и активности не изменились вообще. Вы можете найти их в загрузке, так как они достаточно длинные, чтобы их можно было вставить. Изображение называется walk_elaine.png, и оно было скопировано в / res / drawable-mdpi /, чтобы android мог его автоматически подобрать.

Если вы запустите приложение, вы увидите, как Элейн выполняет циклы ходьбы в одном месте. Мы должны были использовать прыжки, так как это может быть выполнено в одном месте, но вы поняли идею.

Элейн Уолкинг

усиление

Чтобы сделать некоторые аккуратные добавления, измените метод рисования Элейн, чтобы он отображал исходное изображение, содержащее спрайты, из которых извлечены кадры.

1
2
3
4
5
6
7
8
9
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">public void draw(Canvas canvas) {</span> публичный ничья (холст холст) {</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">// where to draw the sprite</span> // где нарисовать спрайт</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">Rect destRect = new Rect(getX(), getY(), getX() + spriteWidth, getY() + spriteHeight);</span> Rect destRect = new Rect (getX (), getY (), getX () + spriteWidth, getY () + spriteHeight);</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">canvas.drawBitmap(bitmap, sourceRect, destRect, null);</span> canvas.drawBitmap (bitmap, sourceRect, destRect, null);</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">canvas.drawBitmap(bitmap, 20, 150, null);</span> canvas.drawBitmap (bitmap, 20, 150, null);</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">Paint paint = new Paint();</span> Paint paint = new Paint ();</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">paint.setARGB(50, 0, 255, 0);</span> paint.setARGB (50, 0, 255, 0);</span>
    <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">canvas.drawRect(20 + (currentFrame * destRect.width()), 150, 20 + (currentFrame * destRect.width()) + destRect.width(), 150 + destRect.height(), paint);</span> canvas.drawRect (20+ (currentFrame * destRect.width ()), 150, 20+ (currentFrame * destRect.width ()) + destRect.width (), 150 + destRect.height (), paint);</span>
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span>

Это просто отображает изображение в (20, 150) и создает новый объект рисования, чтобы мы могли закрасить текущий кадр на исходном изображении.
Метод setARGB создает полупрозрачную зеленую краску. Первое значение 50, что означает, что оно прозрачно на 75%. 0 полностью прозрачен, а 255 полностью непрозрачен.
После того, как все было нарисовано, мы нарисуем прямоугольник размером с рамку на исходное изображение, чтобы вы увидели, какая рамка отображается в движении.

Ходьба с текущей рамой окрашены

Вот и все. Запустите его, и вы получите свою первую спрайт-анимацию.

Загрузите исходный код здесь (animation_walk.tar.gz)

Справка: Sprite Animation с Android от нашего партнера по JCG Тамаса Яно из блога « Против зерна ».

Не забудьте проверить нашу новую Android игру ArkDroid (скриншоты ниже) . Ваш отзыв будет более чем полезным!
Статьи по Теме: