html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Пишем игру под Android: Часть 1 - Рисуем картинки на SurfaceView

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

  1. Пишем игру под Android: Часть 1 — Рисуем картинки на SurfaceView
  2. Пишем игру под Android: Часть 2 — Создаем первый спрайт
  3. Пишем игру под Android: Часть 3 — Спрайтовая анимация, работа с несколькими спрайтами
  4. Пишем игру под Android: Часть 4 — onTouchEvent и определение столкновений
  5. Пишем игру под Android: Часть 5 — Создание полноценной 2D игры
  6. Пишем игру под Android: Часть 6: Добавление звука
  7. Пишем игру под Android: Часть 7: Меню для игры и окно приветствия
  8. Пишем игру под Android: Часть 8: Фоновая музыка в игре


И так, задача:
Для начала просто нарисуем ic_launcher.png на нашем Surface.

Для этого — создаем проект — Eclipse — New — Android project — MyFirstGame — Main.java.

Заходим в res/layout/main.xml и пишем вот такое:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <package.GameView
        android:id="@+id/game"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>


Вместо package пишите тот пак который у вас в проекте.

Открываем создавшийся файл Main.java и вносим в него одну строку, между super.onCreate() и setContentView().

//эта строка позволяет спрятать верхнее меню с экрана телефона
requestWindowFeature(Window.FEATURE_NO_TITLE);


Вот как оно будет выглядеть полностью:

Main.java
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
 public class Main extends Activity {
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(new GameView(this));
    }
}


Дальше нам нужно создать класс GameView.java который будет производить отрисовку нашей графики на сцене и унаследуем его от класса SurfaceView, для того что бы производить 

GameView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.View;
public class GameView extends SurfaceView {
       /**Загружаемая картинка*/
       private Bitmap bmp;
       
       /**Наше поле рисования*/
       private SurfaceHolder holder;
 
       //конструктор
       public GameView(Context context) 
       {
             super(context);
             holder = getHolder();
             holder.addCallback(new SurfaceHolder.Callback() 
             {
                    public void surfaceDestroyed(SurfaceHolder holder) 
                    {
                    }
 
                    @Override
                    public void surfaceCreated(SurfaceHolder holder) 
                    {
                           Canvas c = holder.lockCanvas(null);
                           onDraw(c);
                           holder.unlockCanvasAndPost(c);
                    }
 
                    @Override
                    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
                    {
                    }
             });
             bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
       }
 
       //Рисуем нашу картинку на черном фоне
       protected void onDraw(Canvas canvas) 
       {
             canvas.drawColor(Color.BLACK);
             canvas.drawBitmap(bmp, 10, 10, null);
       }
}


Для отрисовки мы вызываем метод OnDraw() который реализуется непосредственно программистом в коде игры. Что бы представить как работает Canvas — можете представить его как доску на которой можно рисовать то, что Вам вздумается. Для того что бы рисовать на сцене (Canvas) — получаем команду рисовать, при помощи функции OnDraw(). 

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

Мы должны принять во внимание, что во время отрисовки у нас есть ресурс который заблокирован и мы теряем производительность и очень важно, свести к минимуму время блокировки. Пока что у Вас должно получиться только вот такое:



Добавляем анимацию
Теперь можно добавить немного анимации, пусть наша картинка движется в каком-то направлении, я хочу что бы она медленно передвигалась вправо. Вот сейчас мы это и сделаем.

Игра это цикл повторений. Основные направления деятельности:

1. Физика обновления, это обновление данных игры, как, например х и у координаты позиции для маленьких символов.
2. Рисование, это отрисовка картинки, которую вы видите на экране. При вызове этого метода оно дает вам восприятие анимации.

Мы собираемся выполнить цикл игры в отдельном потоке. В одном потоке мы создаем обновления и рисование, а в основном потоке мы обрабатываем события. Для этого создаем еще один файл GameManager.java и вставляем в него следующий код:

GameManager.java
import android.graphics.Canvas;
 public class GameManager extends Thread {
       /**Объект класса*/
       private GameView view;
      
       /**Переменная задавания состояния потока рисования*/
       private boolean running = false;
      
       /**Конструктор класса*/
       public GameManager(GameView view) 
       {
             this.view = view;
       }
 
        /**Задание состояния потока*/
       public void setRunning(boolean run) 
       {
             running = run;
       }
 
       /** Действия, выполняемые в потоке */
       public void run() {
             while (running) {
                    Canvas c = null;
                    try {
                           c = view.getHolder().lockCanvas();
                           synchronized (view.getHolder()) {
                                  view.onDraw(c);
                           }
                    } finally {
                           if (c != null) {
                                  view.getHolder().unlockCanvasAndPost(c);
                           }
                    }
             }
       }
}  


Работает поле флаг, позволяющий остановить цикл игры. Внутри цикла мы вызываем метод OnDraw() о котором мы узнали в прошлом уроке. В этом случае для простоты мы делаем обновление и рисование в OnDraw() методе. Мы используем синхронизации, чтобы избежать других потоков, что бы потоки не конфликтовали.
В SurfaceView мы просто добавим интовое поле int х, координата по которой будет двигаться наша картинка Кроме того, в методе OnDraw() мы увеличиваем х на 1, если он не достиг правой границы, конечно же мы это будет делать на нашей сцене, а значит в файле GameView.java. Вот какой вид будет иметь GameView.java 

GameView.java
public class GameView extends SurfaceView {
       /**Загружаемая картинка*/
       private Bitmap bmp;
       
       /**Наше поле рисования*/
       private SurfaceHolder holder;

       /**Объект класса GameManager*/
       private GameManager gameLoopThread;

       /** Координата движения по Х=0*/
       private int x = 0; 
      
       /**Скорость изображения = 1*/
       private int xSpeed = 1;

       public GameView(Context context) 
       {
             super(context);
             gameLoopThread = new GameManager(this);
             holder = getHolder();
             holder.addCallback(new SurfaceHolder.Callback() 
             {
 
                    /** Уничтожение области рисования */
                    public void surfaceDestroyed(SurfaceHolder holder) 
                    {
                           boolean retry = true;
                           gameLoopThread.setRunning(false);
                           while (retry) {
                                  try {
                                        gameLoopThread.join();
                                        retry = false;
                                  } catch (InterruptedException e) {
                                  }
                           }
                    }
 
                    /** Создание области рисования */
                    public void surfaceCreated(SurfaceHolder holder) 
                    {
                           gameLoopThread.setRunning(true);
                           gameLoopThread.start();
                    }
 
                    /** Изменение области рисования */
                    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
                    {
                    }
             });
             bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
       }
 
       @Override
       protected void onDraw(Canvas canvas) 
       {
             if (x == getWidth() - bmp.getWidth()) 
             {
                    xSpeed = -1;
             }
             if (x == 0) 
             {
                    xSpeed = 1;
             }
             x = x + xSpeed;
             canvas.drawColor(Color.BLACK);
             canvas.drawBitmap(bmp, x , 10, null);
       }
}


Мы ограничили отрисовку до 10 кадров в секунду, что составляет 100 мс (миллисекунды). Мы используем метод sleep() за оставшееся время, чтобы получить 100 мс. Если цикл занимает больше, чем 100 мс мы спим 10 мс в любом случае, наше приложение будет требовать слишком много памяти процессора. Немного усложним код, в GameManager.java заменяем старый код на этот:

 GameManager.java
public class GameManager extends Thread
{
       /**Наша скорость в мс = 10*/
       static final long FPS = 10;
      
       /**Объект класса GameView*/
       private GameView view; 

       /**Задаем состояние потока*/
       private boolean running = false;
      
       /**Конструктор класса*/
       public GameManager(GameView view) 
       {
             this.view = view;
       }
 
        /**Задание состояния потока*/
       public void setRunning(boolean run) 
       {
             running = run;
       }
 
       /** Действия, выполняемые в потоке */
 
       @Override
       public void run() 
       {
             long ticksPS = 1000 / FPS;
             long startTime;
             long sleepTime;
             while (running) {
                    Canvas c = null;
                    startTime = System.currentTimeMillis();
                    try {
                           c = view.getHolder().lockCanvas();
                           synchronized (view.getHolder()) {
                                  view.onDraw(c);
                           }
                    } finally {
                           if (c != null) {
                                  view.getHolder().unlockCanvasAndPost(c);
                           }
                    }
                    sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
                    try {
                           if (sleepTime > 0)
                                  sleep(sleepTime);
                           else
                                  sleep(10);
                    } catch (Exception e) {}
             }
       }
}


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

Исходные коды
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с dajver.blogspot.ru

11

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • Chrono
          • домен blogspot.ru
          • домен dajver.blogspot.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции